Grimoire aggregates third-party documentation, serves a local web UI, and can expose itself to an AI model over MCP (optionally with an execution layer). This document states the threat model, the controls, and the residual risks you must understand before relying on it - especially the execution modes.
- Indexed sources are untrusted. Grimoire clones many third-party repos. Their content (markdown, YAML, notebooks, PDFs, images) is treated as hostile input: it is rendered, searched, and - in exec mode - read by an AI model.
- Search queries / paths are untrusted (anyone who can reach the web UI).
- The attached AI model is semi-trusted. In exec mode it can install software and run commands; a model can be steered by indirect prompt injection from a poisoned indexed document.
- No SQL injection. All queries are parameterized via
model.Index; free text is reduced to alphanumeric prefix tokens by_fts_querybefore reaching an FTS5 MATCH. (test_sqli_*,test_search_*.) - No stored XSS. Rendered docs and search snippets are HTML-escaped; pages
ship a strict per-load CSP nonce (
script-src 'nonce-...', nounsafe-inline), so injected<script>/on*/javascript:cannot run. (test_*_csp,test_search_snippet_is_escaped.) - No template injection. HTML is built with f-strings/escaping, never a
template engine on user data. (
test_no_template_injection.) - Path traversal blocked.
_resolve_docresolves and confines paths to the source dir (symlink escapes and NUL bytes handled)./assetis limited to image/PDF extensions;/docandgrimoire_fetch_docto document extensions (config.DOC_EXT) - so the server cannot be used to read.git/config,.env, keys, or source. (test_path_traversal_blocked,test_asset_extension_allowlist,test_doc_blocks_non_document_extensions.) - CSRF guard on the state-changing
/api/update(custom header, no CORS). - No command injection via tool names. Install tool names are validated
against
^[A-Za-z0-9][A-Za-z0-9._+-]*$; metacharacters are refused before any shell command is built. (test_runner_rejects_tool_name_injection,test_mcp_install_rejects_injection.) - No git transport RCE.
fetchonly cloneshttps/http/git/ssh/git@URLs;ext::,file://,fd::and option-injection (-x) are rejected. (test_safe_repo_url_blocks_transport_helpers.) - Execution is off by default.
mcpruns inreadmode unless you pass--mode assist|auto; the install/run tools are absent fromtools/listin read mode, so a model cannot attempt them. (test_mcp_mode_gates_exec_tools.)
- The exec denylist is a guardrail, not a sandbox. It refuses obvious
host-wreckers (
rm -rf /,mkfs, fork bombs,shutdown, ...) but is trivially bypassable ($(...), variable expansion, odd spacing). It stops accidents, not a determined adversary. Exec mode runs real commands on your host/container with your privileges (andsudowhen available). - Target scope is best-effort. It blocks out-of-scope IPv4/IPv6 literals and hostnames, but can be bypassed by decimal/hex/octal IP encodings, by names that resolve out of scope, or by tools that take targets from a file. Treat scope as defense-in-depth, not a boundary. Enforce real scope at the network layer too.
- Indirect prompt injection. A poisoned indexed doc can contain instructions
the AI may follow. In
automode (no per-call approval) this can lead to unintended installs/commands. Recommended posture:readfor knowledge work;assist(your MCP client approves every call) for live engagements;autoonly in a contained lab. grimoire buildruns upstream build systems. The optionalbuildcommand invokes each source's ownmdbook/mkdocsbuild, which can execute code/ plugins defined in a poisoned repo. It is optional and not used by search (which reads raw markdown). Only runbuildon sources you trust.servehas no authentication. It binds127.0.0.1by default. If you expose it (--host 0.0.0.0) put it behind a VPN/reverse proxy with auth - anyone who can reach it can search and read indexed docs and trigger updates.- The engagement context is sent to the model. Do not put secrets in
context.yamlthat you would not want the attached model to see.
This is part of the RF-Swift toolkit by Penthertz (https://penthertz.com). Report security issues privately rather than in a public issue.