n8n-impl-workflow-design — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited n8n-impl-workflow-design (Agent Skill) and scored it 45/100 (orange). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 1 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 1 flagged
A base64 string of 128+ characters appears in a documentation file. Encoded prompt injection hides the hostile instruction in base64 — invisible to keyword filters — and relies on the agent's ability to decode it at runtime. There is no normal authoring reason to embed a multi-hundred-byte base64 blob in skill docs.
*.sig, SIGNATURES) outside the documentation.Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
| Pattern | Primary Node | When to Use |
|---|---|---|
| Sub-workflow | Execute Workflow | Reusable logic, separation of concerns, >20 nodes |
| Error handling | Error Trigger + Stop And Error | Centralized failure notification and recovery |
| Branching | IF / Switch | Conditional routing based on data values |
| Merging | Merge | Combining data from parallel branches |
| Looping | Loop Over Items | Batch processing, rate-limited API calls |
| Wait/Resume | Wait | Human approval, external callback, timed delay |
| Scheduling | Schedule Trigger | Recurring automated execution |
Need to reuse logic across workflows?
├─ YES → Sub-workflow (Execute Workflow node)
└─ NO
Need to handle failures gracefully?
├─ YES → Is it a single node that might fail?
│ ├─ YES → continueOnFail + IF node to check $json.error
│ └─ NO → Error workflow (Error Trigger node)
└─ NO
Need to route data conditionally?
├─ YES → Two outcomes? → IF node
│ Multiple outcomes? → Switch node
└─ NO
Need to combine data from multiple sources?
├─ YES → Merge node (choose mode based on use case)
└─ NO
Need to process items in batches?
├─ YES → Loop Over Items node
└─ NO
Need to pause and wait?
├─ YES → Wait node (time, webhook, or form resume)
└─ NO → Schedule Trigger for recurring executionALWAYS use the Execute Workflow node to call another workflow as a sub-workflow. NEVER duplicate logic across workflows.
Parameter passing:
Caller policy (callerPolicy in workflow settings):
workflowsFromSameOwner — Only workflows owned by the same user (DEFAULT)workflowsFromAList — Only workflow IDs listed in callerIdsany — Any workflow can call this sub-workflownone — NEVER allow this workflow to be called as a sub-workflowALWAYS set callerPolicy explicitly on sub-workflows in production. NEVER leave it as default when multiple users share the n8n instance.
When to extract a sub-workflow:
See: references/methods.md for Execute Workflow node details. See: references/examples.md for sub-workflow patterns.
Layer 1 — Node-level: continueOnFail
continueOnFail on individual nodes that might fail$json.error containing the error message$json.errorLayer 2 — Node-level: Retry on Fail
retryOnFail for transient failures (API timeouts, rate limits)maxTries (default: 3) and waitBetweenTries (default: 1000ms)Layer 3 — Workflow-level: Error Workflow
Use the Stop And Error node to deliberately fail a workflow when:
This triggers the configured error workflow, enabling centralized error notification.
Set executionTimeout in workflow settings to prevent runaway executions. Configure the global default via EXECUTIONS_TIMEOUT environment variable (default: disabled). Maximum allowed timeout is controlled by EXECUTIONS_TIMEOUT_MAX (default: 3600 seconds).
See: references/methods.md for error handling node details. See: references/examples.md for error handling patterns.
The IF node evaluates conditions and routes items to one of two outputs:
ALWAYS use the IF node for binary (true/false) decisions. NEVER use a Switch node with only two routes.
Conditions support:
and / or combinatorsThe Switch node routes items to multiple outputs based on rules or expression values:
ALWAYS use the Switch node when routing to 3+ destinations. NEVER chain multiple IF nodes for multi-way branching.
Every node supports the onError setting:
stopWorkflow — Stop execution (default)continueRegularOutput — Send error data to the regular outputcontinueErrorOutput — Send error data to a dedicated error outputSee: references/methods.md for IF and Switch node details.
The Merge node combines data from two or more inputs. ALWAYS choose the correct mode:
| Mode | Use Case | Behavior |
|---|---|---|
| Append | Combine all items from both inputs into one list | Concatenates items |
| Combine > Merge By Fields | Join items by matching field values | SQL-style JOIN |
| Combine > Merge By Position | Pair items by index position | items[0]+items[0], items[1]+items[1] |
| Combine > Multiplex | Create all combinations | Cartesian product |
| Choose Branch | Wait for one branch, discard others | First-to-complete wins |
| SQL Query | Complex data combination | Write SQL against inputs |
ALWAYS use "Merge By Fields" when combining data from different sources that share a key field. NEVER use "Merge By Position" for data with different item counts.
See: references/methods.md for Merge node modes.
The Loop Over Items node (formerly "Split In Batches") processes items in configurable batch sizes:
When to use:
ALWAYS set a reasonable batch size. NEVER process all items at once when calling rate-limited APIs.
Loop body rules:
See: references/examples.md for loop patterns.
The Wait node pauses execution and resumes via:
Resume on timer:
Resume on webhook:
$execution.resumeUrlResume on form:
$execution.resumeFormUrlALWAYS use Wait node webhook resume for human-in-the-loop approvals. NEVER poll for status changes when a webhook callback is possible.
Access the resume URL in expressions:
{{ $execution.resumeUrl }} — Webhook resume URL{{ $execution.resumeFormUrl }} — Form resume URLALWAYS send the resume URL to the external system (e.g., in an approval email) BEFORE the Wait node pauses execution.
The Schedule Trigger node starts workflow execution on a schedule:
ALWAYS set the correct timezone in workflow settings (settings.timezone). NEVER rely on the server's default timezone for scheduled workflows.
ALWAYS set GENERIC_TIMEZONE environment variable on deployment to ensure consistent schedule behavior.
| Expression | Meaning |
|---|---|
0 * * * * | Every hour at minute 0 |
0 9 * * 1-5 | Weekdays at 09:00 |
*/15 * * * * | Every 15 minutes |
0 0 1 * * | First day of every month at midnight |
0 8,12,17 * * * | At 08:00, 12:00, and 17:00 daily |
| Setting | Purpose | Default |
|---|---|---|
errorWorkflow | Workflow to execute on failure | None |
executionTimeout | Max execution time (seconds) | Disabled (-1) |
callerPolicy | Who can call this as sub-workflow | workflowsFromSameOwner |
callerIds | Allowed caller workflow IDs (when policy = fromAList) | Empty |
timezone | Timezone for schedule nodes | Instance default |
saveDataErrorExecution | Save data on error | all |
saveDataSuccessExecution | Save data on success | all |
executionOrder | Node execution algorithm | v1 |
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.