sfscanner 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +131 -214
- package/dist/index.d.ts +4 -0
- package/dist/index.js +10766 -0
- package/dist/index.js.map +7 -0
- package/dist/main.js +4419 -7667
- package/dist/main.js.map +4 -4
- package/dist/mcp.js +3374 -6611
- package/dist/mcp.js.map +4 -4
- package/dist/scan-worker.js +11800 -0
- package/dist/scan-worker.js.map +7 -0
- package/dist/v2/arguments.d.ts +4 -3
- package/dist/v2/arguments.js +126 -17
- package/dist/v2/arguments.js.map +3 -3
- package/dist/v2/batch-runner.d.ts +7 -1
- package/dist/v2/cli-runner-internal.d.ts +28 -0
- package/dist/v2/cli-runner.d.ts +16 -22
- package/dist/v2/cli-runner.js +3524 -6872
- package/dist/v2/cli-runner.js.map +4 -4
- package/dist/v2/commands.d.ts +5 -4
- package/dist/v2/config.d.ts +1 -1
- package/dist/v2/contracts.d.ts +23 -6
- package/dist/v2/help.d.ts +8 -2
- package/dist/v2/help.js +52 -5
- package/dist/v2/help.js.map +2 -2
- package/dist/v2/metadata-output.d.ts +2 -2
- package/dist/v2/metadata-output.js +6844 -139
- package/dist/v2/metadata-output.js.map +4 -4
- package/dist/v2/metadata-validation.d.ts +1 -1
- package/dist/v2/path-admission.d.ts +8 -0
- package/dist/v2/scan-config-load.d.ts +21 -0
- package/dist/v2/scan-worker-host.d.ts +29 -0
- package/package.json +74 -67
- package/dist/v2/sarif-helpers.d.ts +0 -69
- package/dist/v2/sarif-output.d.ts +0 -40
package/README.md
CHANGED
|
@@ -1,214 +1,131 @@
|
|
|
1
|
-
# sfscanner
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
> **Licensing:** MIT for this package's code and scanner tooling. The catalogue dataset has separate Personal / Non-Commercial terms; see
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
#
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
and
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
`--
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
with:
|
|
133
|
-
node-version: 22
|
|
134
|
-
|
|
135
|
-
- name: Install sfscanner
|
|
136
|
-
run: |
|
|
137
|
-
cd community-hub && npm ci && npm run build --workspace=sfscanner
|
|
138
|
-
npm link --workspace=sfscanner
|
|
139
|
-
|
|
140
|
-
- name: Run Scan
|
|
141
|
-
run: |
|
|
142
|
-
sfscanner scan ./workflows --format sarif > sfscanner.sarif
|
|
143
|
-
|
|
144
|
-
- name: Upload SARIF to GitHub Security Tab
|
|
145
|
-
uses: github/codeql-action/upload-sarif@v3
|
|
146
|
-
with:
|
|
147
|
-
sarif_file: sfscanner.sarif
|
|
148
|
-
```
|
|
149
|
-
|
|
150
|
-
---
|
|
151
|
-
|
|
152
|
-
## 6. Native AI MCP Server (`sfscanner-mcp`)
|
|
153
|
-
|
|
154
|
-
`sfscanner` includes a production-ready, native **Model Context Protocol (MCP)** server (`dist/mcp.js`) running over standard I/O JSON-RPC 2.0. It gives AI coding assistants the power to audit n8n workflows before executing or importing them.
|
|
155
|
-
|
|
156
|
-
```mermaid
|
|
157
|
-
graph LR
|
|
158
|
-
User["Developer / Operator"] --> Agent["AI Assistant (Claude / Cursor)"]
|
|
159
|
-
Agent -->|MCP stdio JSON-RPC| Server["sfscanner-mcp (dist/mcp.js)"]
|
|
160
|
-
Server -->|Static In-Memory Scan| Core["@hub/scanner-core Engine"]
|
|
161
|
-
Core -->|SARIF / JSON Finding| Server
|
|
162
|
-
Server -->|Diagnostic Report| Agent
|
|
163
|
-
Agent -->|Safe Workflow Advice| User
|
|
164
|
-
```
|
|
165
|
-
|
|
166
|
-
### Tool Definition
|
|
167
|
-
* **Tool Name:** `n8n_scan`
|
|
168
|
-
* **Description:** *"Scan local n8n workflow JSON with the admitted deterministic offline v2 profile."*
|
|
169
|
-
* **Parameters:**
|
|
170
|
-
* `inputs` (array of strings, required): Local workflow file paths.
|
|
171
|
-
* `format` (optional string): `'json' | 'ndjson' | 'sarif' | 'table'`.
|
|
172
|
-
* `failOn` (optional string): `'CRITICAL' | 'HIGH' | 'MEDIUM' | 'LOW' | 'INFO'`.
|
|
173
|
-
|
|
174
|
-
### Connecting to Claude Desktop
|
|
175
|
-
Add this entry to your `claude_desktop_config.json`:
|
|
176
|
-
|
|
177
|
-
```json
|
|
178
|
-
{
|
|
179
|
-
"mcpServers": {
|
|
180
|
-
"sfscanner": {
|
|
181
|
-
"command": "node",
|
|
182
|
-
"args": [
|
|
183
|
-
"/absolute/path/to/n8n-community/community-hub/packages/scanner-cli/dist/mcp.js"
|
|
184
|
-
]
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
```
|
|
189
|
-
|
|
190
|
-
### Connecting to Cursor
|
|
191
|
-
Add this entry to your Cursor Settings (`.cursor/mcp.json`):
|
|
192
|
-
|
|
193
|
-
```json
|
|
194
|
-
{
|
|
195
|
-
"mcpServers": {
|
|
196
|
-
"sfscanner": {
|
|
197
|
-
"command": "node",
|
|
198
|
-
"args": [
|
|
199
|
-
"d:/projects/n8n-community/community-hub/packages/scanner-cli/dist/mcp.js"
|
|
200
|
-
]
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
```
|
|
205
|
-
|
|
206
|
-
### Example AI Prompting
|
|
207
|
-
Once configured, you can prompt your AI agent:
|
|
208
|
-
> *"Before we deploy this automation, use the `n8n_scan` tool to check `workflows/lead-sync.json` for prompt injection or leaked credentials."*
|
|
209
|
-
|
|
210
|
-
---
|
|
211
|
-
|
|
212
|
-
## 7. Licensing Terms
|
|
213
|
-
|
|
214
|
-
`sfscanner` code and scanner tooling are MIT-licensed; see [`LICENSE`](LICENSE). The aggregated workflow catalogue dataset (`data/`) has separate Personal / Non-Commercial terms and is not included in this package. See the [canonical licensing policy](https://github.com/jitwark/n8n-Secureflow/blob/main/docs/LICENSING.md).
|
|
1
|
+
# sfscanner 🔍
|
|
2
|
+
|
|
3
|
+
**Deterministic, offline security scanning for n8n workflows** — JSON, NDJSON, a table, or SARIF 2.1.0. The workflow never leaves your machine.
|
|
4
|
+
|
|
5
|
+
> **Licensing:** MIT for this package's code and scanner tooling. The catalogue dataset has separate Personal / Non-Commercial terms; see https://github.com/jitwark/n8n-Secureflow/blob/main/docs/LICENSING.md.
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npx sfscanner scan my-workflow.json
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
> This package is the scanner. The workflow **catalogue** — 11,464 public n8n workflows, their
|
|
12
|
+
> provenance and how much of each one the scanner could actually read — lives on the website:
|
|
13
|
+
> <https://n8n-enterprise-1.web.app>.
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## ⚡ Quickstart
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
# one file, human-readable
|
|
21
|
+
npx sfscanner --schema v2 scan workflow.json --format table
|
|
22
|
+
|
|
23
|
+
# a directory, SARIF for GitHub code scanning
|
|
24
|
+
npx sfscanner --schema v2 scan ./workflows --format sarif > results.sarif
|
|
25
|
+
|
|
26
|
+
# pipe a workflow straight from a clipboard or curl
|
|
27
|
+
cat workflow.json | npx sfscanner scan -
|
|
28
|
+
|
|
29
|
+
# see the rules, then read one in full
|
|
30
|
+
npx sfscanner --schema v2 rules --format table
|
|
31
|
+
npx sfscanner --schema v2 explain N8N_EXECUTE_COMMAND
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Node **22** is the only supported line (`engines: >=22 <23`). The CLI is ESM-only and no CommonJS artifact is shipped; `require('sfscanner')` is not supported. Runs have been verified on Windows; Linux and macOS are not yet a verified matrix.
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## 🧠 What it actually checks
|
|
39
|
+
|
|
40
|
+
Seven admitted rules in the `beta-default` profile. Every row carries a severity, a confidence and a
|
|
41
|
+
CWE: these are deterministic pattern and configuration matches, **not** a safety guarantee, and not a
|
|
42
|
+
verdict about whether a workflow is safe to run.
|
|
43
|
+
|
|
44
|
+
| Rule | Severity | Confidence | CWE |
|
|
45
|
+
| --- | --- | --- | --- |
|
|
46
|
+
| `N8N_EXECUTE_COMMAND` | CRITICAL | HIGH | CWE-78 |
|
|
47
|
+
| `N8N_CODE_NODE` | LOW | HIGH | CWE-94 |
|
|
48
|
+
| `RAW_AUTH_HEADER` | HIGH | MEDIUM | CWE-522, CWE-798 |
|
|
49
|
+
| `RAW_SECRET_INDICATOR` | HIGH | MEDIUM | CWE-798 |
|
|
50
|
+
| `UNAPPROVED_DOMAIN` | MEDIUM | HIGH | — |
|
|
51
|
+
| `UNKNOWN_NODE_PACKAGE` | LOW | MEDIUM | CWE-1357 |
|
|
52
|
+
| `WEBHOOK_EXPOSURE` | MEDIUM | MEDIUM | CWE-306 |
|
|
53
|
+
|
|
54
|
+
The `beta-hardened` profile is **defined but not admitted** — `sfscanner --schema v2 profiles` says
|
|
55
|
+
so, and selecting it fails instead of silently running something weaker.
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## 📤 Output and exit codes
|
|
60
|
+
|
|
61
|
+
Formats: `json` (default), `ndjson`, `sarif`, `table`. SARIF is 2.1.0 with CWE tags, so GitHub,
|
|
62
|
+
GitLab and VS Code can read it directly.
|
|
63
|
+
|
|
64
|
+
| Exit | Meaning |
|
|
65
|
+
| :---: | --- |
|
|
66
|
+
| `0` | Clean — nothing met the `--fail-on` threshold. |
|
|
67
|
+
| `1` | Findings at or above `--fail-on`, or a degraded result under `--require-complete`. |
|
|
68
|
+
| `2` | Usage or configuration error. |
|
|
69
|
+
| `3` | Malformed input, a failed/timed-out input, or an `INDETERMINATE` result — unless a finding at/above `--fail-on` already decided exit 1. |
|
|
70
|
+
| `4` | Internal error or a memory ceiling. |
|
|
71
|
+
| `130` | Interrupted. |
|
|
72
|
+
|
|
73
|
+
`--fail-on <CRITICAL|HIGH|MEDIUM|LOW|INFO>` (Default: `INFO`). `--schema v2` is required for
|
|
74
|
+
directory scans, `--output` and `--fail-on`; without it those are usage errors by design.
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## 🤖 MCP server
|
|
79
|
+
|
|
80
|
+
The package ships `sfscanner-mcp` — a stdio JSON-RPC MCP server with **one** tool, `n8n_scan`. It
|
|
81
|
+
scans local workflow files with the same engine and returns the same structured output, so an agent
|
|
82
|
+
can read a workflow before it imports it.
|
|
83
|
+
|
|
84
|
+
```json
|
|
85
|
+
{
|
|
86
|
+
"mcpServers": {
|
|
87
|
+
"sfscanner": {
|
|
88
|
+
"command": "node",
|
|
89
|
+
"args": ["<npm-root>/sfscanner/dist/mcp.js"]
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
`<npm-root>` is `npm root -g`. The single tool takes `inputs` (local paths; stdin `-` is refused
|
|
96
|
+
because the transport owns stdin), plus optional `format`, `failOn`, `profile`, `include`, `exclude`.
|
|
97
|
+
Invalid arguments answer JSON-RPC `-32602` without running a scan.
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## 🛡️ Limits, honestly
|
|
102
|
+
|
|
103
|
+
- Inputs are bounded: 1,536,000 bytes per file by default, 5,000 nodes, 10,000 edges, a 30 s worker
|
|
104
|
+
deadline, and a validated `--limits` document can tighten or raise the byte ceiling.
|
|
105
|
+
- The scan runs in a worker; if the worker cannot be terminated the item is reported `FAILED` rather
|
|
106
|
+
than "probably fine".
|
|
107
|
+
- Node types the scanner does not model are reported as **unknown**, not as safe. Version ranges are
|
|
108
|
+
matched as catalogued; there is no nearest-neighbour guess.
|
|
109
|
+
- Coverage of the published corpus lives on the website, with explicit counts for bodies that are
|
|
110
|
+
missing, source-unavailable, degraded and indeterminate.
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
## 📚 Documentation
|
|
115
|
+
|
|
116
|
+
- [`docs/scanner/cli-v2.md`](../../docs/scanner/cli-v2.md) — v2 admission rules and Windows example
|
|
117
|
+
- [`docs/scanner/limitations.md`](../../docs/scanner/limitations.md) — what the scanner does not do
|
|
118
|
+
- [`docs/scanner/rule-reference.md`](../../docs/scanner/rule-reference.md) — every rule and remediation
|
|
119
|
+
- [`docs/scanner/migration-v1-v2.md`](../../docs/scanner/migration-v1-v2.md) — v1 remains supported
|
|
120
|
+
- [`docs/LICENSING.md`](../../docs/LICENSING.md) — licence terms
|
|
121
|
+
|
|
122
|
+
v1 (`sfscanner scan file.json`) still works for one input with the `beta-default` profile.
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
## ⚖️ Licence
|
|
127
|
+
|
|
128
|
+
MIT for this package's code and scanner tooling. The catalogue dataset has separate Personal /
|
|
129
|
+
Non-Commercial terms; see https://github.com/jitwark/n8n-Secureflow/blob/main/docs/LICENSING.md.
|
|
130
|
+
The dataset is not shipped in this package. A finding tells you what to read before importing a
|
|
131
|
+
workflow; it does not make one safe.
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { parseCliArguments } from './v2/arguments.js';
|
|
2
|
+
export { runCliV2, type PublicRunOptionsV2, type PublicRunResultV2, type PublicScanCommandV2, } from './v2/cli-runner.js';
|
|
3
|
+
export { getHelpV2 } from './v2/help.js';
|
|
4
|
+
export { emitMetadataCommandResultV2 } from './v2/metadata-output.js';
|