faf-mcp has an arbitrary local file read/write via unconfined `path` argument in FAF tools
- Product
- faf-mcp
- Affected
- faf-mcp <= 2.1.2
- Fixed in
- 2.1.3
Last verified against sources: October 26, 2026
Am I affected?
faf-mcp: affected faf-mcp <= 2.1.2. Fixed in 2.1.3.
- Check your version: run
npm ls faf-mcp. Versions <= 2.1.2 of faf-mcp are affected. [1]
What to do now
- Upgrade to the fixed version: run
npm install faf-mcp@2.1.3(first patched version 2.1.3). [1] - Upgrade to 2.1.3 with
npm install -g faf-mcp@2.1.3(ornpx faf-mcp). [1] - 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. [1]
General practice, not from the source: if the affected software could read tokens or credentials, rotate them after upgrading; pin versions and review changes before updating tools your agents run.
What happened
faf-mcpMCP tools accept a caller-controlledpathargument and resolve it (~expansion +path.resolve()) straight into a filesystem read/write without confining it to a trusted project directory. [1]- 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.fafproject context. [1] - The shared
getProjectPath()chokepoint (feeding the.faftools) and the general-purposefaf_read/faf_writefile tools resolved a caller path straight into a read/write with no confinement (denylist-only). [1] - 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). [1]
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),.envfiles, source,/etc/passwd; andfaf_writecould write outside the project. [1] - This is a sensitive-information-disclosure (CWE-200) primitive that far exceeds the declared
.fafproject-context scope. [1] - The only remaining limit is OS file permissions. [1]
What was done
- Fixed in **2.1.3** by confining every caller-supplied
pathbefore any filesystem access (safe-path.ts). [1] - Reads are restricted to
.faf/.fafmcontext files, so non-context files (secrets) are refused regardless of directory. [1] - General file ops (
faf_read/faf_write) are confined to the project root (cwd + system temp; override withFAF_ALLOWED_ROOTS). [1] - Paths are canonicalized through symlinks (closing the symlink bypass); absolute paths and
../escapes are rejected;callTool()gains a central PATH-DENIED guard. [1]
Sources
- GHSA-j4r7-8ph4-43g3 — GitHub Advisory Database
Every statement above was checked against these sources before publishing. Spotted an error? Tell us and we will correct it with a dated note.
Share advisory brief with your team
Copy a plain-text summary for Slack, GitHub issues, or team security channels.
faf-mcp has an arbitrary local file read/write via unconfined `path` argument in FAF tools
Product: faf-mcp | Affected: faf-mcp <= 2.1.2 | Fixed in: 2.1.3
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.
Source & remediation on AgentArmorHQ: https://agentarmorhq.com/incidents/2026/08/ghsa-j4r7-8ph4-43g3-faf-mcpCorrections
Report an error or request a correction. We review requests within 5 business days and add a dated correction note.
Discussions for faf-mcp
Ask questions or share configuration tips. Governed by our Community Rules & Terms.
No posts match this filter yet.
Be the first to ask a question or share a working tip.