Why this verdict
- inconclusive: gap no_dataflow_for_dynamic_code at ariadne_mcp/cli.py
Security findings 0
No individual findings recorded
The inconclusive verdict rests on the coverage gaps below; 4 candidate findings were refuted on review.
Refuted findings 4
Candidates the review stage examined and rejected, kept for transparency.
Persistence
criticalRefutedmedium confidenceThe `install` subcommand writes an MCP server entry into the workspace .mcp.json and injects a snippet into CLAUDE.md, which modifies the agent's control-plane and instruction files; the injected text is not shown here.
All-in-one setup: scan repos, write <workspace>/.mcp.json, inject CLAUDE.md.
Why it was refuted
The install subcommand openly declares in its docstring, help text and usage that it writes .mcp.json and CLAUDE.md. The registered server is this package's own module, and the injected snippet is shown and benign. The claimed contradiction with D29 concerns a different tool in server.py, not the CLI install command.
Destructive action
criticalRefutedlow confidencedemo.py's build_demo_db unconditionally deletes any existing file at the user-supplied --db path before rebuilding, so pointing --db at a real index would destroy it.
os.remove(db_path)
Why it was refuted
demo.py is a standalone script that regenerates its own output DB. The --db argument is documented as the output path and defaults to a file next to the script. This is overwrite-the-build-output behavior, not agent-reachable destruction. A user would have to deliberately point it at a real index.
Agent hijacking
highRefutedlow confidenceThe CLAUDE.md snippet that install appends to the user's agent rules file tells the agent to query the Ariadne tool before reading files for business or cross-service tasks, steering agent workflow via a persistent rules file, though within the tool's declared purpose.
query Ariadne first, then read files
Why it was refuted
The snippet only tells the agent to use the tool this package provides for cross-service tasks. It is the declared purpose of the install step and includes explicit skip conditions. It does not redirect the agent to anything outside that purpose.
Code execution
highRefutedlow confidenceScanner resolution dynamically imports an arbitrary module named in the config (`module:Class`) and instantiates it with config-supplied kwargs, so a modified config can run arbitrary code during scan/rescan; this is documented as the custom-scanner extension mechanism.
mod = importlib.import_module(mod_name)
Why it was refuted
The dynamic import is the documented custom-scanner plugin mechanism. The module name comes from the user's own scanner config, and the code only imports and instantiates a class from it. This is the declared core capability, not a concealed behavior.
Coverage gaps 1
Parts of the artifact the static analysis could not fully examine.
no_dataflow_for_dynamic_code line 118: invoked code is not structurally extracted
ariadne_mcp/cli.py