n8n Operator holds an n8n API key and is designed to sit between an LLM and real, side-effecting actions. Security issues here are taken seriously and reviewed against the project's own threat model, not just patched ad hoc.
Do not open a public GitHub issue for a security vulnerability.
Once this repository is public, report it privately using GitHub's private vulnerability reporting feature on this repository (Security tab → Report a vulnerability). If that is not visible, open a regular issue containing only a request for private maintainer contact—never include vulnerability or exploit details. While the release candidate is private, existing collaborators should use the repository's private issue tracker.
Include, as applicable:
- What you found and why it matters (which boundary in THREAT_MODEL.md section 9.2 it crosses, if you can tell).
- Steps to reproduce, or a minimal example.
- The version (git commit or release tag) you tested against.
- Whether you believe it's already listed as a known limitation in V1_LIMITATIONS.md or an accepted/partial threat in THREAT_MODEL.md — if so, say which one; that's useful signal even if it turns out to be a duplicate.
You'll get an acknowledgment as soon as practical. This is a small project without a dedicated security team or a formal SLA — response time depends on maintainer availability, not a contract.
In scope:
- Anything in
src/n8n_operator/— the MCP server, the CLI, the approval app, the storage layer, the n8n client. - The documented boundary controls (B1–B13) failing to hold as described.
- A threat marked
mitigatedin THREAT_MODEL.md that turns out not to be.
Out of scope (already documented, not going to be "found" as new):
- Everything in THREAT_MODEL.md section 8 ("Out of scope for v1") and V1_LIMITATIONS.md — read those first. A compromised operator machine, n8n's own security, downstream authorization, and unencrypted data at rest are all explicitly accepted v1 tradeoffs, not gaps waiting to be reported.
- Vulnerabilities in n8n itself, or in a workflow an operator chose to register — report those to the n8n project or the workflow's owner, respectively.
- Vulnerabilities in a direct dependency with no n8n-Operator-specific exploitation path — report those upstream; a dependency bump here is still welcome as a PR.
Pre-1.0: only the latest tagged release and main are supported. There is no
version-support matrix until a stable 1.0 ships (see
CHANGELOG.md for what's shipped so far).
A fix to a security issue lands as a normal PR, referencing the report (never
including exploit specifics in the public commit message or changelog entry until a
release has shipped), updates the relevant test(s) to prove the fix, and — if it
changes a control's actual behavior — updates
THREAT_MODEL.md's status for the affected threat. A mitigated
status is never assigned without a real, tested control backing it (see this
repository's own release-verification discipline in docs/BUILD_PLAN.md phase 9).
- The n8n API key and any webhook secrets are held in the server process's memory only
— resolved from environment or OS keychain at startup
(ADR-006) — and never written to
the registry, the database, or a log line.
logging_setup.py's scrubbing filter is defense in depth, not the primary control; the primary control is that a credential is never constructed into a loggable value in the first place. - No MCP tool accepts or returns a credential, an n8n instance URL, or a raw n8n
workflow ID — enforced structurally (the argument/result schemas have no field for
one), checked by a contract test (
tests/contract/test_mcp_tool_inventory.py), and independently checked by a Hypothesis property test (tests/property/test_redaction_properties.py).