sfscanner 0.0.0-stage → 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.
Files changed (42) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +131 -3
  3. package/THIRD_PARTY_NOTICES.md +48 -0
  4. package/dist/index.d.ts +4 -0
  5. package/dist/index.js +10766 -0
  6. package/dist/index.js.map +7 -0
  7. package/dist/main.js +11941 -0
  8. package/dist/main.js.map +7 -0
  9. package/dist/mcp.js +10468 -0
  10. package/dist/mcp.js.map +7 -0
  11. package/dist/scan-worker.js +11800 -0
  12. package/dist/scan-worker.js.map +7 -0
  13. package/dist/v2/arguments.d.ts +87 -0
  14. package/dist/v2/arguments.js +403 -0
  15. package/dist/v2/arguments.js.map +7 -0
  16. package/dist/v2/atomic-output.d.ts +34 -0
  17. package/dist/v2/batch-runner.d.ts +50 -0
  18. package/dist/v2/cli-runner-internal.d.ts +28 -0
  19. package/dist/v2/cli-runner.d.ts +22 -0
  20. package/dist/v2/cli-runner.js +10037 -0
  21. package/dist/v2/cli-runner.js.map +7 -0
  22. package/dist/v2/commands.d.ts +155 -0
  23. package/dist/v2/config.d.ts +16 -0
  24. package/dist/v2/contracts.d.ts +97 -0
  25. package/dist/v2/exit-reducer.d.ts +23 -0
  26. package/dist/v2/help.d.ts +33 -0
  27. package/dist/v2/help.js +325 -0
  28. package/dist/v2/help.js.map +7 -0
  29. package/dist/v2/input-read.d.ts +26 -0
  30. package/dist/v2/input-selection.d.ts +38 -0
  31. package/dist/v2/json-output.d.ts +97 -0
  32. package/dist/v2/metadata-output.d.ts +37 -0
  33. package/dist/v2/metadata-output.js +7523 -0
  34. package/dist/v2/metadata-output.js.map +7 -0
  35. package/dist/v2/metadata-validation.d.ts +4 -0
  36. package/dist/v2/ndjson-output.d.ts +3 -0
  37. package/dist/v2/path-admission.d.ts +8 -0
  38. package/dist/v2/scan-config-load.d.ts +21 -0
  39. package/dist/v2/scan-worker-host.d.ts +29 -0
  40. package/dist/v2/table-output.d.ts +2 -0
  41. package/dist/v2/worker-host.d.ts +24 -0
  42. package/package.json +74 -6
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 n8n-secureflow contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,131 @@
1
- # Temporary Holding Version
2
-
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
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.
@@ -0,0 +1,48 @@
1
+ # Third-party notices
2
+
3
+ This package ships a built CLI bundle plus its own documentation. The package's own code is licensed
4
+ under [`LICENSE`](LICENSE) (MIT). No workflow corpus, private repository data, or runtime network
5
+ client is included in this package.
6
+
7
+ The classification below is derived from the packed artifact, not from declared intent: a module
8
+ counts as shipped only when the bundle's shipped `dist/*.js.map` sources name it. The same split is
9
+ machine-readable in `outputs/distribution/scanner-sbom.cyclonedx.json`
10
+ (`scope` plus the `sfscanner:observed-in-packed-artifact` property).
11
+
12
+ ## Inlined in the packed bundle
13
+
14
+ | Component | Version | License |
15
+ | --- | --- | --- |
16
+ | `@humanwhocodes/momoa` | 3.3.10 | Apache-2.0 |
17
+ | `@noble/hashes` | 2.3.0 | MIT |
18
+ | `@hub/contracts` | 0.1.0 | MIT — this project's workspace package |
19
+ | `@hub/scanner-core` | 0.1.0 | MIT — this project's workspace package |
20
+
21
+ `@hub/contracts` and `@hub/scanner-core` are this project's own MIT-licensed workspace packages. Their
22
+ code is compiled into `dist/main.js` and `dist/mcp.js`; they are not runtime package dependencies.
23
+
24
+ ## Declared runtime dependencies this build does not ship
25
+
26
+ These packages are installed as runtime dependencies of `@hub/scanner-core` and are imported by its
27
+ optional code-analysis modules, but they are unreachable from this CLI's admitted profile
28
+ (`beta-default` only, `packages/scanner-cli/src/v2/commands.ts`), so they are tree-shaken out of the
29
+ packed bundle. They are listed because their absence is a verified property of this artifact: the
30
+ string `acorn` / `@lezer` occurs zero times anywhere under `packages/scanner-cli/dist`, and the
31
+ shipped source maps name none of their modules.
32
+
33
+ | Component | Version | License |
34
+ | --- | --- | --- |
35
+ | `acorn` | 8.17.0 | MIT |
36
+ | `@lezer/common` | 1.5.2 | MIT |
37
+ | `@lezer/highlight` | 1.2.3 | MIT |
38
+ | `@lezer/lr` | 1.4.10 | MIT |
39
+ | `@lezer/python` | 1.1.19 | MIT |
40
+
41
+ The scanner package's build/test-only tooling (`esbuild`, `typescript`, `vitest`, `@types/node` and
42
+ their transitive dependencies) is likewise absent from the packed artifact and carries no notice
43
+ obligation for it.
44
+
45
+ This is a prepared dependency inventory, not a claim that the release's notice obligations are
46
+ complete. A release owner must reconcile these versions against the exact lockfile, attach the
47
+ verbatim upstream license texts, and complete the legal review (`PENDING_OWNER`). This package is
48
+ published on npm as `sfscanner`.
@@ -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';