governance linter for n8n automations

gatekeep

The two governance properties an AI automation lives or dies on, made into checks a pipeline can block on.

status live · CLIrole designed + built end to end
interactive · click and scroll itlive
The real report: seven workflows graded. The pre-fix Triage fails on the inline key, my current four pass, and a naive agent fails the AI-guard check that a governed reference agent clears.
1 real keyan inline Anthropic secret it caught in a live workflow, the reason it exists.
2 checksunguarded model-to-action and real human-gate reachability, which generic n8n scanners do not frame.
8 totalplus secrets, SSRF, code sinks, TLS, webhook auth, resilience, each CWE-mapped.
0 credsreads exported JSON, never touches a live instance or holds a key.
What it solves

Everything else in this portfolio argues one rule: nothing an AI system does reaches the outside world without a deterministic check and a human approving it, and no secret sits in the open. That rule is easy to state and easy to break by hand, which I proved by finding an API key inline in one of my own workflow headers. I looked at what already exists, and the n8n security scanners on the market are real but generic: secrets, SSRF, injection. None of them check the property that actually defines an AI automation, whether raw model output is allowed to drive an action. So gatekeep leads there.

The constraint

It had to be safe to run on a real automation estate without becoming a second liability. It reads exported JSON, never needs credentials or a live connection, and refuses to hold a real secret itself: even its test fixtures use redacted placeholders that match the patterns. The rubric is deliberately eight sharp checks with documented heuristics and a config file to extend them, not a hundred-rule scanner nobody trusts the scope of.

Who it serves

Anyone running AI automations who has to promise a client or an auditor that nothing fires unreviewed.

Who it is for

Governance as code, aimed at the AI-specific property generic scanners miss, and CI-blockable.

How it works
  1. Point it at exported workflowsA folder of n8n workflow JSON, no live instance and no credentials needed.
  2. It builds each graphNodes are classified and connections become a reachability graph it can walk backward from any action.
  3. Eight checks runUnguarded model output, real human-gate reachability, secrets, SSRF, code sinks, TLS, webhook auth, resilience, each finding CWE-tagged and tied to the exact node.
  4. A graded scorecard, and an exit codeA letter grade per workflow with a one-line fix on every finding, and a nonzero exit so a pipeline can block a merge.
The decision that was not obvious

The check no generic scanner has: raw model output must never reach an action unchecked. gatekeep walks backward from every external action, and a Code or IF node on the path shields it, so anything a deterministic guard validates is considered safe. If the walk reaches an LLM call with nothing in between, it fails. This is the 'model proposes, code decides' rule expressed as reachability, and it is paired with a stricter gate check that refuses to count a timer-resume Wait as human approval, because a lot of automations fake governance with a delay.

What I would change if I rebuilt it today

The model-to-action check is structural reachability, not true data-flow taint. A workflow that launders model output through a node type I do not classify as a guard, a Set node say, could read as guarded when it is not. I would add lightweight taint tracking on the actual field references, so the check follows the data instead of the graph shape.

Built with
Node graph reachability zero deps CWE-mapped rubric config-extensible CI exit codes