GHSA-j4r7-8ph4-43g3 — faf-mcp
HIGHGHSA-j4r7-8ph4-43g3 is a high-severity (CVSS 7.5) vulnerability in faf-mcp. A fix is available for faf-mcp — see the affected versions and patch details below.
faf-mcp has an arbitrary local file read/write via unconfined `path` argument in FAF tools
Real-World Exposure
How broadly this vulnerability is actually deployed: weekly install volume shows current usage, and reverse-dependency count shows how many other packages break if it stays unpatched.
faf-mcpnpmDescription
Summary
faf-mcp MCP tools accept a caller-controlled path argument and resolve it (~ expansion + path.resolve()) straight into a filesystem read/write without confining it to a trusted project directory. An absolute path or ../ traversal is resolved and used as-is, so the server process can be made to read — and, via the file tools, write — files outside the intended .faf project context. The only remaining limit is OS file permissions.
Affected tools
The shared getProjectPath() chokepoint (feeding the .faf tools) and the general-purpose faf_read / faf_write file tools resolved a caller path straight into a read/write with no confinement (denylist-only); an absolute path still reached home-directory secrets, and faf_write could write outside the project.
Impact
An MCP client — or an LLM prompt-injected via attacker-controlled content (a web page, README, ticket, or .faf) into issuing a tool call — can read any file the server process can read: SSH keys (~/.ssh/id_rsa), cloud credentials (~/.aws/credentials), .env files, source, /etc/passwd; and faf_write could write outside the project. This is a sensitive-information-disclosure (CWE-200) primitive that far exceeds the declared .faf project-context scope. The server runs over stdio, so the read/write is reached by a crafted tool call (e.g. a prompt-injected agent processing attacker-controlled content).
Patches
Fixed in 2.1.3 by confining every caller-supplied path before any filesystem access (safe-path.ts):
- Reads are restricted to
.faf/.fafmcontext files, so non-context files (secrets) are refused regardless of directory. - General file ops (
faf_read/faf_write) are confined to the project root (cwd + system temp; override withFAF_ALLOWED_ROOTS). - Paths are canonicalized through symlinks (closing the symlink bypass); absolute paths and
../escapes are rejected;callTool()gains a central PATH-DENIED guard.
Upgrade: npm install -g [email protected] (or npx faf-mcp).
Workarounds
If you cannot upgrade immediately, run the server only against trusted local projects, and set FAF_ALLOWED_ROOTS (patched versions) to a single project directory for a hard directory boundary.
Credits
Identified by the maintainers during a sibling-server audit prompted by the coordinated disclosure of the same class of issue in grok-faf-mcp by Zhihao Zhang (Worcester Polytechnic Institute).
Affected Packages
| Ecosystem | Package | Vulnerable range | Fix |
|---|---|---|---|
| 📦npm | faf-mcp | all versions | 2.1.3npm install faf-mcp@2.1.3 |
Detection & mitigation playbook
Open-source dependencyDetect
Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for faf-mcp, including transitive dependencies — a direct dependency you never call can still pull in a vulnerable version.
Fix
Update faf-mcp to 2.1.3 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms GHSA-j4r7-8ph4-43g3 is resolved across your whole dependency graph.
Workarounds
Assume what was exposed is already known: rotate any credential, token or key that the affected component could return, restrict the endpoint to callers that genuinely need it, and strip sensitive fields from responses and error output at the boundary rather than relying on the client not to read them.
Frequently Asked Questions
Is GHSA-j4r7-8ph4-43g3 in your dependencies?
Find it across npm, including transitive dependencies.