Refuted findings 13
Candidates the review stage examined and rejected, kept for transparency.
Persistence
criticalRefutedlow confidenceWhen no usable cwd exists, the engine adapter silently creates ~/Projects under the user's home directory and uses it as the working directory; this is a benign, documented fallback with no data source or sink chain.
fs.mkdirSync(projectsDir, { recursive: true });Why it was refuted
Creating ~/Projects is a commented fallback that applies only when no usable cwd exists. It creates an empty directory and has no data source or sink chain, so it is not persistence.
Code execution
highRefutedlow confidenceThe npm `debug` script starts the Node inspector bound to 0.0.0.0:9229, which would expose a remote debugger to the network if a developer runs it.
node --inspect-brk=0.0.0.0:9229 -r ts-node/register src/cli.ts
Why it was refuted
This is an openly named, opt-in developer 'debug' script. It is not a lifecycle hook, is never invoked by the server, and does what its name says, so there is no concealed harm or agent chain.
Code execution
highRefutedlow confidenceThe undeclared manual 'debug' npm script starts the Node inspector bound to all interfaces (0.0.0.0:9229), which would expose a remote debugger if a developer runs it; it is a dev-only script and not an install-time hook.
node --inspect-brk=0.0.0.0:9229 -r ts-node/register src/cli.ts
Why it was refuted
This is a manual, openly named 'debug' dev script, not an install-time hook, and nothing in the artifact invokes it. There is no concealment and no chain to an agent.
Supply chain
highRefutedlow confidenceThe Smithery start command runs `npx -y faf-mcp@latest`, so whatever is currently published under the mutable `latest` tag is fetched and executed without a pinned version.
args: ["-y", "faf-mcp@latest"]
Why it was refuted
The Smithery launch command runs the server's own package, faf-mcp, which is the declared launch mechanism, not a third-party dependency. The unpinned tag is a hygiene point, not concealed or undeclared behavior.
Supply chain
highRefutedmedium confidenceThe Smithery start command runs the server via `npx -y faf-mcp@latest`, fetching and executing the latest unpinned registry package without confirmation on every launch.
args: ["-y", "faf-mcp@latest"]
Why it was refuted
This is the same launch command as the previous finding. It launches the artifact's own published package as the declared stdio start command, so it is not undeclared or harmful.
Persistence
highRefutedlow confidenceThe agents export command writes project.faf-derived content into AGENTS.md, an agent rules/memory file that later agent sessions load; this is the tool's declared export purpose and is gated by an overwrite check, so it is a low-risk capability.
const outputPath = path.join(projectPath, 'AGENTS.md');
Why it was refuted
Writing AGENTS.md is the declared export function. It is gated by an overwrite check and force flag, and it only writes the user's own project.faf data in a managed block, so it is the core-capability carve-out.
Persistence
highRefutedlow confidenceThe cursor export command writes project.faf-derived content into .cursorrules, an agent rules file that Cursor loads; this is the declared export feature and is gated by an overwrite check, so it is a low-risk capability.
const outputPath = path.join(projectPath, '.cursorrules');
Why it was refuted
Writing .cursorrules is the declared cursor export feature. It is gated by an overwrite check and force flag, and it only writes the user's own project.faf content into a managed block.
Data exfiltration
highRefutedlow confidenceThe GitHub extractor makes outbound HTTPS calls to api.github.com (sending the owner/repo identifiers) even though the README describes the server as running locally over stdio; the network use is not declared as a tool dependency, though it appears to serve the `faf git` feature and is plausibly honest.
const response = await fetch(apiUrl, {Why it was refuted
The fetch goes to api.github.com for the declared `faf git` feature, and the only data sent is the user-supplied owner/repo. The README's 'runs locally over stdio' describes the transport, so this is not exfiltration.
Credential access
highRefutedlow confidenceGITHUB_TOKEN/GH_TOKEN from the environment is attached as an Authorization header to every GitHub API fetch, including one to a URL (data.languages_url) taken from an API response; the destination is GitHub's own API, so this is likely honest but the token is sent to a response-derived URL without a host check.
fetch(data.languages_url, {Why it was refuted
The GitHub token is the wrapped service's own env credential, sent only to GitHub endpoints, and the error message tells users to set GITHUB_TOKEN. The languages_url comes from api.github.com's own response, so this is the env-API-key carve-out with no attacker-controlled sink.
Credential access
highRefutedlow confidenceUndeclared read of GITHUB_TOKEN/GH_TOKEN from the environment, attached as an Authorization header to GitHub API requests including to a response-derived `languages_url`; this is consistent with the GitHub-wrapping purpose, but the destination for that URL is not pinned to api.github.com.
const token = process.env.GITHUB_TOKEN || process.env.GH_TOKEN;
Why it was refuted
Reading GITHUB_TOKEN/GH_TOKEN to authenticate GitHub API calls is the env-key-for-wrapped-service carve-out. It is user-facing in the error text, and the token only goes to GitHub-served URLs.
Persistence
highRefutedlow confidencefaf_auto writes CLAUDE.md (an agent memory/rules file) in the project directory from the faf-cli render of project.faf; this is the declared core function and the content is derived from the project's own data, with no external source.
writeClaudeMd(cwd, renderClaudeMd(readFaf(fafPath)));
Why it was refuted
faf_auto's documented step writes CLAUDE.md as a faf-managed block, rendered from the project's own project.faf. This is the declared core function, with no external content source and no concealment.
Supply chain
mediumRefutedlow confidencepackage.json defines a standard npm 'prepare' lifecycle script that runs the local build (tsc) on install from source; this is a routine, low-risk install-time hook with no remote fetch or secret access.
"prepare": "npm run build"
Why it was refuted
The prepare hook only runs the local tsc build, with no remote fetch, secret access or concealment. This is a routine npm lifecycle script, so there is no harm.
Reconnaissance
lowRefutedlow confidencefaf_list accepts a caller-supplied path (including ~ and absolute paths) with no confinement and enumerates directories and project.faf presence up to a caller-chosen depth, returning the listing to the agent; this is a bounded directory-enumeration capability that matches the tool's declared purpose.
const targetPath = args?.path || this.engineAdapter.getWorkingDirectory();
Why it was refuted
faf_list is a directory lister whose purpose is finding project.faf projects, and it returns only names and the project.faf flag. This is its declared function, with no hidden sink or exfiltration chain.