GHSA-cc2g-gq8c-r332: Path Traversal
Summary Several grok-faf-mcp MCP tools accept a caller-controlled path argument and resolve it (~ expansion + path.resolve()) straight into a filesystem read 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 files outside the intended .faf project context. The only remaining limit is OS file permissions.
Affected tools refreshfaf, fafscore, fafgetorchestrationpolicy, refreshblend (and the shared getProjectPath() chokepoint feeding the .faf tools), plus the general-purpose fafread / fafwrite file tools (denylist-only; an absolute path still reached home-directory secrets, and fafwrite could write outside the project). refreshfaf echoes the file contents verbatim back to the caller as "fresh DNA"; fafgetorchestrationpolicy reflects values parsed out of the attacker-chosen file and echoes the resolved absolute path — confirming the read.
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/idrsa), cloud credentials (~/.aws/credentials), .env files, source, /etc/passwd. 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 is reached by a crafted tool call (e.g. a prompt-injected agent processing attacker-controlled content).
Patches Fixed in 1.5.3 by confining every caller-supplied path before any filesystem access (safe-path.ts): - Reads are restricted to .faf / .fafm context files, so non-context files (secrets) are refused regardless of directory. - General file ops (fafread / fafwrite) are confined to the project root (cwd + system temp; override with FAFALLOWEDROOTS). - Paths are canonicalized through symlinks (closing the symlink bypass); absolute paths and ../ escapes are rejected.
Upgrade: npm install -g grok-faf-mcp@1.5.3 (or bunx grok-faf-mcp).
Workarounds If you cannot upgrade immediately, run the server only against trusted local projects, and set FAFALLOWEDROOTS (patched versions) to a single project directory for a hard directory boundary.
Credits Discovered and responsibly reported via coordinated disclosure by Zhihao Zhang (Worcester Polytechnic Institute).
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Upgrade
Upgrade
npm/grok-faf-mcpto a version that resolves this vulnerability.Fixed in 1.5.3 - Upgrade
Upgrade
grok-faf-mcpto a version that resolves this vulnerability.Fixed in 1.5.3 - Compensating control
If you cannot upgrade immediately, run the server only against trusted local projects and set the environment variable FAF_ALLOWED_ROOTS (in patched versions) to a single trusted project directory to enforce a hard directory boundary.
Event History
Frequently Asked Questions
Who can trigger the unauthorized file reads?
Any MCP client able to invoke the affected tools can supply a path. An LLM can also be induced to make such a call through prompt-injected attacker-controlled content, including web pages, READMEs, tickets, or .faf files.
What access does an attacker need to read files outside the project?
The attacker needs only the ability to cause an affected MCP tool call with a caller-controlled path; no authentication, user interaction, or special privileges are required by the vulnerability. Read access is limited by the operating-system permissions of the server process.
Which operations create the most direct exposure?
refresh_faf can return the selected file's contents verbatim to the caller. faf_get_orchestration_policy can expose parsed values and the resolved absolute path, while faf_read and faf_write can respectively read from and write outside the intended project directory.