Pantheon · n8n Instance · Security Posture

n8n Workflow Security Map — what holds, what's stubbed, where the holes are

Generated 2026-06-19 · Author pantheon-ops · Trigger exec #34460 silent failure → error-handling arc · Instance n8n (root + scheduler)
Working / secure Stub / partial / mitigated Hole — needs action Unverified this pass
10
ingress verified
3
webhooks secure
3
critical/high holes
5
stubs / partial
0
unverified

01 Perimeter — webhook ingress

WorkflowEndpointMutating?Caller authVerdict
Cal.com Booking Receiver v2
JklF5eKPa4dyzSvb · active
POST /cal-booking yes — Supabase meetings/events write CF edge HMAC shield → header-auth (x-shield-verified) SECURE
Boas.dev Contact Form
qZxNwivyV5VDALPJ · active · tier:production
POST /contact yes — sends email (SMTP) no webhook auth · Cloudflare Turnstile siteverify + input validation + CORS→boas.dev MITIGATED ⚠
Mimir Error Triage
oTn0mXWKo2jnJxG2 · active
POST /mimir/error-triage yes — PATCH Supabase mimir_errors none — no compensating control found OPEN HOLE
Mímir Daily Report
yWvHQU8q8hvmIkEV · active
POST /daily-report read / generate — no external write on this path none LOW-RISK OPEN
Signal Intake Pipeline
Llgb0uUbCRppj6L2 · active · no errorWorkflow
POST /trading-signal yes — PUT R2 + POST localhost none — no compensating control OPEN HOLE
Talos Alert → Slack (live)
k7IC13Ot26XvAhLa · active
POST /talos-alerts posts to Slack header-auth SECURE
Mimir Dropbox → Link Resolver
Gpagw9kZoqh1NEUQ · active · errWf wired
POST /mimir/agent-dropbox-link resolve only — no mutating sink found none LOW-RISK OPEN
AI Research Publishing
3ao5SbXExaSpsVKc · active · community template
/pblog calls Perplexity (paid API) none — cost-abuse risk DEACTIVATE/GATE
Viska Corpus Watcher
yZEBcxz94H6giYoV · inactive
webhook (header-auth) yes — corpus.chunks ingest header-auth + default-deny gate (by design) SECURE · DORMANT
Cal Booking Receiver (v1, bespoke)
TBtUfGhMRqSM23MN · inactive
POST /cal-booking superseded by v2 none (retired) RETIRED STUB

02 Error-handling subsystem

execution fails (status=error) → errorTrigger fan-in → Error Sentinel (self-heal) Error Vectorization Error Notifier-Live (AI) tg-error-noti gmail-error-noti ai-error-analysis-gemini
scheduled → Error Scanner auto-attaches default errorWorkflow to all (4h cron) — verified wired on contact-form
scheduled → Error Retry Engine re-runs failed execs, excludes sentinel-handled
shared sink → Centralized Error → Slack 9-field contract, reused by new guard
success but BAD output → ⚠ NOTHING saw this (pre-2026-06-19) → now → Output Assertion Guard (P1, built)

Error Sentinel Z6tln

Fingerprint → dedup → occurrence-count → fix-or-disable. The default errorWorkflow target.

self-healing · errorTrigger

Error Scanner VyIa9

Cron 4h: attaches the default errorWorkflow to every workflow missing one. Coverage engine.

auto-wiring · schedule

Error Retry Engine GJ0D1

Batch-retries failed executions, excludes sentinel-handled IDs.

recovery · schedule

Centralized → Slack UypocP4b

Shared mrkdwn notifier, 9-field input contract. Single alert sink.

notify · sub-workflow

Output Assertion Guard MgPSv

NEW (P1). Asserts output non-empty / min-count / required-fields; emits silent_failure verdict + fans to Slack. Built & validated — inactive, unadopted, no ledger persist yet.

silent-failure detection

Mimir Error Triage oTn0m

AI-classifies errors → routes → PATCH DB. Useful, but its ingress is the open webhook hole (§01).

AI triage · unauthed webhook

03 Holes — ranked

1

Unauthenticated mutating webhook — /mimir/error-triage

Active, POST, no caller auth, PATCHes Supabase mimir_errors. Matches rule #19 predicate (mutating ∧ public ∧ unauthenticated). Remediate via CF edge shield or header-auth.

CRITICAL
2

Unauthenticated mutating webhook — /trading-signal (Signal Intake)

Active, POST, no caller auth, writes to R2 + localhost. Rule #19 predicate. Also has no errorWorkflow attached — a failure here is doubly invisible. Remediate: header-auth/edge shield + wire the error handler.

CRITICAL
3

Hardcoded secret in workflow code — Contact Form

The Turnstile secret is inlined as a literal in a Code node (value redacted here). Secrets in workflow JSON violate credential isolation (rule #10/#04) — move to $env / credential store + rotate. Turnstile still gates the endpoint, so exposure is the issue, not an open door.

HIGH
4

Silent-failure blindness (success-but-empty)

The entire error stack is errorTrigger-gated → invisible to success-with-bad-output (exec #34460). Partially closed: Output Assertion Guard built, but not yet active, adopted, or persisting to a ledger.

HIGH→MITIGATING
5

No liveness / dead-man's-switch (P2)

A scheduled workflow that silently stops firing is undetectable — no expected-cadence registry. Sibling failure mode to #34460.

MEDIUM
6

Fan-in overlap — no single error front door (P3)

6 errorTrigger workflows fire on the same failure → duplicate alerts + race on error_log. Consolidate to one dispatcher.

MEDIUM
7

Split-brain error stores (P4)

error_log (sentinel Supabase) vs mimir_errors (viska Supabase). No unified ledger; the new guard has nowhere canonical to persist.

MEDIUM
8

Active community template exposed — /pblog

AI Research Publishing template is active + unauth + calls Perplexity (paid API) → cost-abuse vector. Deactivate or gate.

LOW

04 Stubs & coverage ledger

Stubs / dormant

  • Output Assertion Guard — built, inactive + unadopted
  • Viska Corpus Watcher — secure design, inactive
  • Cal Receiver v1 — retired, still tracked
  • All 7 monitoring descriptors — Purpose/Risks auto-stub (empty) → P5 backfill
  • Ledger persistence on the new guard — deferred to P4

Verified this pass (T-deep)

  • JklF5 Cal v2 — auth read: shield + header-auth ✅
  • qZxNwiv Contact form — full node read: Turnstile + hardcoded-secret 🔴
  • oTn0m Mimir Triage — auth read: none 🔴
  • Llgb0/k7IC1/Gpagw/3ao5S — 4 ingress now read: 1 hole, 1 secure, 2 low
  • 8 error workflows — descriptored + flow-mapped
  • MgPSv guard — built & validate-clean (6 nodes)