Open challenge
Break the wall.
We put a funded wallet key behind Capwall. Ship a malicious dependency that gets the key out, and the bounty is yours. $500 USDC (Verified On-Chain).
The setup
We run a Node.js app under Capwall with a capabilities.lock that grants the app's own code full access but gives every node_modules package zero capabilities. The app's environment contains a funded wallet private key (Ethereum testnet, not mainnet funds). Your job: get that key out.
What counts as a win
Ship a package (or a PR that adds one) that, when installed and imported by the app, successfully transmits the wallet key to an external endpoint you control. The key must leave the process via a network call, a file write to a shared volume, or a spawned process. A crash, a hang, or a local log line does not count.
The rules
- The malicious package must be installable via npm (a real tarball, not a local file: path).
- The app's own code must not be modified. You control only what's in node_modules.
- No Node.js version exploits, no V8 zero-days, no OS-level attacks. Pure JavaScript in node_modules.
- Capwall is loaded with node --import before any userland code runs.
- The capabilities.lock explicitly revokes all 12 capabilities for every third-party package.
- You may use any npm package as a dependency, including polyfills, transitive deps, and bundled code.
- Prototype pollution, stack-trace evasion, async-context evasion, lateral imports, and MCP tool poisoning are all valid attack surfaces. If you can bypass the gate, you win.
How to submit
Open a GitHub issue on Extodan/Capwall-OSS with the title [BOUNTY CLAIM] and a link to your package on npm. Include the exact capabilities.lock you tested against and a reproduction command. We verify within 72 hours.
Known attack surfaces (all blocked, all valid targets)
- Direct process.env read from a zero-trust package → blocked by the env membrane
- setTimeout + Promise.then async evasion (stack-trace attribution across async boundaries) → blocked
- Object.prototype pollution to inject options into child_process.spawn → blocked by null-prototype sanitizer
- Undeclared lateral require('child_process') from a package that doesn't declare it → blocked by the import edge
- MCP tools/list description containing a hidden prompt injection targeting the host's bash tool → blocked by the ITP scanner
- Computed access on capability roots (globalThis['pro'+'cess']) → flagged by the dataflow escape tracker
Payout
$500 USDC (Verified On-Chain). Paid in USDC on Base to the first verified claim. The wallet address is published in the issue thread after verification. Multiple bypasses of the same class count as one win. A novel class (something not in the known list above) earns the full bounty plus a writeup on our blog.