Skip to main content

FlowSentry

self-scan

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 git+https://github.com/vasilicasijarvis/flowsentry.git
$ flowsentry scan workflows/ --sarif flowsentry.sarif

PyPI package (pip install flowsentry) is coming — for now install straight from GitHub.

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) Critical Medium Notable finding
AI_Bot.json (AnaamRasool/WhatsApp-Bot) 1 4 WhatsApp webhook with authentication: none, replies echo full node output
00485-library-install.json (DragonJAR/n8n-workflows-esp) 2 1 Bash script interpolating {{$json.library}} into shell
n8n/w1.json (Finfra/dockers) 1 2 Webhook authentication: 'none'
workflows/103.json (n8n-io/test-workflows) 4 2 echo 'test' > /tmp/{{$node["Set"].json["filename"]}}
subagente-citas.json (santifer/jacobo-workflows) 1 9 Public appointment-booking webhook, no auth
nl2sql.json (Wilsonoonn/n8n_nl2sql) 1 9 Natural-language-to-SQL behind an unauthenticated webhook
api-authentication.json (yorrickjansen/n8n-webhook-security) 1 5 Demo webhooks themselves accept unauthenticated requests
AIDA Preisalarm, nl2sql helper, openwebui-pipe (3 more files) 0 7 code 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 30-test suite in tests/test_rules.py.

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

Rules (v0.1)

Rule Severity Detects
FS001 critical Webhook endpoint without authentication
FS002 critical Hardcoded secret in node parameters
FS003 high Hardcoded secret in HTTP header/query
FS004 critical SSRF / cloud metadata endpoint access (IMDS 169.254.169.254, GCP, Alibaba)
FS005 critical Execute Command node without guardrails
FS006 medium Code node without sandbox hardening (no task runners)
FS007 critical Dynamic code construction (eval, new Function, child_process, os, subprocess, dynamic $())
FS008 medium Credential over-scoping (admin/root/owner names, unusual types)
FS009 critical Expression-based command injection ({{$json...}} into shell)
FS010 medium Missing error handling (no errorWorkflow, no Error Trigger)
FS011 high Raw SQL built from expressions
FS012 high HTTP node over plain http://
FS013 medium Exposed trigger (Form/Telegram/IMAP accepting unauthenticated input)
FS014 medium Credential reuse across 5+ nodes
FS015 medium Community/unknown node packages
FS016 medium Data sent to exfil-style sinks (webhook.site, pastebin, ngrok…)
FS017 medium Webhook response mode echoing internal data
FS018 medium Set 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     # 30 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.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

flowsentry-0.1.0.tar.gz (25.7 kB view details)

Uploaded Source

File details

Details for the file flowsentry-0.1.0.tar.gz.

File metadata

  • Download URL: flowsentry-0.1.0.tar.gz
  • Upload date:
  • Size: 25.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: flowsentry-stdlib-uploader/0.1 (stdlib)

File hashes

Hashes for flowsentry-0.1.0.tar.gz
Algorithm Hash digest
SHA256 9a7b144b102c7e0f19f6503825fabc9125e24d7702d10104abad3a399788d1f8
MD5 64df6646c5557cf8a3c51dc59fad2f72
BLAKE2b-256 b5763d9012e34ecada62b93b04d9d5ae35d7842b78f39153f2cd80f0ed974949

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.1.0 This release

1 file

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page