FlowSentry

& SQL injection, exfil sinks). Free MCP server + paid x402 API ecurity scanner for n8n workflow exports: 18 static-analysis rules mapped to OWASP Agentic AI (webhook auth, hardcoded secrets, SSRF/IMDS, command (0.50 USDC/scan, settles on Base).

Documentation

FlowSentry

self-scan PyPI Python License

Security scanner for n8n workflows — 18 rules, zero dependencies, CI-ready.

FlowSentry parses your n8n workflow JSON exports and flags the failures we keep seeing in the wild: unauthenticated webhooks, hardcoded secrets, SSRF to cloud metadata, shell injection through Execute Command, eval-style code nodes, SQL built from user input, over-scoped credentials and more. Output: terminal, JSON, SARIF 2.1.0 (GitHub Code Scanning) and a self-contained HTML report.

  • Zero runtime dependencies (pure Python stdlib, Python 3.9+)
  • 18 rules mapped to the OWASP Agentic Top 10 (2026)
  • SARIF output → upload straight to GitHub Code Scanning
  • Exit code 1 on findings → drop it into CI as a quality gate
$ pip install flowsentry
$ flowsentry scan workflows/ --sarif flowsentry.sarif

PyPI: https://pypi.org/project/flowsentry/ · or install straight from GitHub: pip install git+https://github.com/vasilicasijarvis/flowsentry.git

No install at all:

git clone https://github.com/vasilicasijarvis/flowsentry
cd flowsentry
python3 flowsentry_cli.py scan ./workflows

Why

n8n webhooks are unauthenticated by default. Most self-hosted instances sit behind a single reverse proxy, and one exported workflow is enough to leak a hardcoded API key or an Execute Command node that interpolates request data straight into a shell.

We scanned 10 real, public n8n workflow files from GitHub with FlowSentry v0.1:

File (source repo)CriticalMediumNotable finding
AI_Bot.json (AnaamRasool/WhatsApp-Bot)14WhatsApp webhook with authentication: none, replies echo full node output
00485-library-install.json (DragonJAR/n8n-workflows-esp)21Bash script interpolating {{$json.library}} into shell
n8n/w1.json (Finfra/dockers)12Webhook authentication: 'none'
workflows/103.json (n8n-io/test-workflows)42echo 'test' > /tmp/{{$node["Set"].json["filename"]}}
subagente-citas.json (santifer/jacobo-workflows)19Public appointment-booking webhook, no auth
nl2sql.json (Wilsonoonn/n8n_nl2sql)19Natural-language-to-SQL behind an unauthenticated webhook
api-authentication.json (yorrickjansen/n8n-webhook-security)15Demo webhooks themselves accept unauthenticated requests
AIDA Preisalarm, nl2sql helper, openwebui-pipe (3 more files)07code nodes, missing error handling, response modes

Totals: 11 critical, 39 medium across 10 files. 100% of files had at least one finding.

These are public workflow exports shared by their authors for learning/demo purposes — nothing was exploited and no instance was accessed. FlowSentry is defensive tooling: it reads JSON files, it does not send requests.

Real findings, verbatim

1. Shell injection via Execute Command (n8n official test workflow):

[!] CRITICAL FS005 Execute Command node without guardrails
    node: Execute Command  (n8n-nodes-base.executeCommand)
[!] CRITICAL FS009 Expression-based command injection
    node: Execute Command
    evidence: echo 'test' > /tmp/{{$node["Set"].json["filename"]}}
    fix: Never interpolate data into commands; use argv-style APIs or strict
         allowlist validation of the entire command string.

2. Unauthenticated webhooks (5 of 10 files):

[!] CRITICAL FS001 Webhook endpoint without authentication
    node: HTTP Trigger  (n8n-nodes-base.webhook)
    Webhook node has authentication set to 'none'. Anyone who can reach the
    n8n instance can trigger this workflow and its downstream actions.
    fix: Set Webhook > Authentication to Basic/Header/JWT auth, or validate a
         shared-secret header in the workflow before doing anything sensitive.

3. What the other rules catch (crafted example from the test suite):

[!] CRITICAL FS002 Hardcoded secret in node parameters
    Parameter 'accessToken' looks like it contains a hardcoded secret
    (literal value, no expression). Exports of workflows leak like this.
    fix: Move the value into an n8n credential and reference it via expressions.

Rules FS002–FS004, FS011–FS013 and FS015–FS018 (secrets, SSRF/IMDS, SQL injection, plain http, community nodes, exfil sinks) did not fire on this particular sample but are fully covered by the 40-test suite in tests/test_rules.py.

Real run, 2026-09-06flowsentry scan examples/real on the 10 public workflow exports (exit code 1 as expected on critical findings):

  examples/real/AI_Bot.json  (WhatsApp bot) - 5 finding(s)
    [!] CRITICAL FS001 Webhook endpoint without authentication
           node: HTTP Trigger  (n8n-nodes-base.webhook)
    [~] MEDIUM   FS017 Webhook response mode exposes internals
           node: API: JWT auth with auth server validation  (n8n-nodes-base.webhook)
           Webhook responseMode='responseNode' - the last node's full output (possibly
           including credentials, internal IDs, stack traces) is returned to the
           unauthenticated caller.
           fix: Return an explicit minimal payload via the Respond to Webhook node.

  Summary
    critical: 11   high: 0   medium: 39   low: 0
    Result: FAIL - fix critical/high findings before production.

Full machine-readable results: examples/scan_report.json, examples/scan_report.sarif and examples/scan_report.html.

Rules (v0.1)

RuleSeverityDetects
FS001criticalWebhook endpoint without authentication
FS002criticalHardcoded secret in node parameters
FS003highHardcoded secret in HTTP header/query
FS004criticalSSRF / cloud metadata endpoint access (IMDS 169.254.169.254, GCP, Alibaba)
FS005criticalExecute Command node without guardrails
FS006mediumCode node without sandbox hardening (no task runners)
FS007criticalDynamic code construction (eval, new Function, child_process, os, subprocess, dynamic $())
FS008mediumCredential over-scoping (admin/root/owner names, unusual types)
FS009criticalExpression-based command injection ({{$json...}} into shell)
FS010mediumMissing error handling (no errorWorkflow, no Error Trigger)
FS011highRaw SQL built from expressions
FS012highHTTP node over plain http://
FS013mediumExposed trigger (Form/Telegram/IMAP accepting unauthenticated input)
FS014mediumCredential reuse across 5+ nodes
FS015mediumCommunity/unknown node packages
FS016mediumData sent to exfil-style sinks (webhook.site, pastebin, ngrok…)
FS017mediumWebhook response mode echoing internal data
FS018mediumSet node storing secrets in plaintext

Usage

# Scan files or directories (directories are walked for *.json)
flowsentry scan ./workflows
flowsentry scan export1.json export2.json

# Machine-readable outputs
flowsentry scan ./workflows --json report.json --sarif report.sarif --html report.html

# CI gate: exit 1 when findings at/above severity exist (default: high)
flowsentry scan ./workflows --fail-on critical
flowsentry scan ./workflows --fail-on never   # always exit 0

# List rules
flowsentry rules

GitHub Actions

name: flowsentry
on: [push, pull_request]
jobs:
  scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with: { python-version: "3.12" }
      - run: pip install git+https://github.com/vasilicasijarvis/flowsentry.git
      - run: flowsentry scan ./workflows --sarif flowsentry.sarif --fail-on high
      - uses: github/codeql-action/upload-sarif@v3
        if: always()
        with:
          sarif_file: flowsentry.sarif

Scan an n8n export bundle

# From your n8n UI: Workflows > Export (or via n8n CLI)
n8n export:workflow --all --output=./workflows
flowsentry scan ./workflows --html report.html

Demo

FlowSentry demo

Development

git clone https://github.com/vasilicasijarvis/flowsentry
cd flowsentry
python3 tests/run_tests.py     # 40 tests, zero dependencies

Re-fetch the public example workflows used in the README scan:

python3 scripts/fetch_workflows.py
flowsentry scan examples/real --json examples/scan_report.json

Roadmap

  • v0.2 — live scanning via the n8n REST API, drift detection (workflow changed since last scan)
  • v1.0 — FlowSentry Cloud: continuous monitoring, alerting, multi-instance dashboard
  • v1.5 — MCP server config auditing (tool poisoning, auth gaps, unpinned versions)
  • v2.0 — compliance evidence packs (OWASP Agentic Top 10, EU AI Act, SOC 2)

The hosted, continuous version is in the works — join the early list: flowsentry.vercel.app

License

Apache-2.0. Scan your own workflows or exports you have permission to analyze.