fullshield 1.0.0 → 1.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/CHANGELOG.md +81 -1
- package/README.md +75 -5
- package/dist/agent.js +50 -40
- package/dist/cli/index.js +103 -93
- package/dist/compliance.js +2 -2
- package/dist/iac.js +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +84 -74
- package/dist/mcp.js +53 -43
- package/dist/runtime/auto.js +5 -5
- package/dist/runtime/rasp.js +7 -7
- package/dist/runtime/register.js +6 -6
- package/dist/supply.js +5 -5
- package/models/index.json +1 -1
- package/models/npm-builders.json +3 -0
- package/models/npm-popular.json +2414 -0
- package/models/ssti.json +14 -0
- package/models/vendored.json +15 -0
- package/models/webhooks.json +9 -0
- package/package.json +2 -2
- package/rules/CONFIG-ELECTRON-001.md +11 -0
- package/rules/CONFIG-ELECTRON-002.md +11 -0
- package/rules/CONFIG-ELECTRON-003.md +11 -0
- package/rules/CONFIG-ENGINES-001.md +11 -0
- package/rules/CONFIG-LIFECYCLE-001.md +11 -0
- package/rules/CONFIG-NEXT-001.md +11 -0
- package/rules/CONFIG-NEXT-002.md +11 -0
- package/rules/DEPS-ALIAS-SQUAT-001.md +11 -0
- package/rules/DEPS-BADINTEGRITY-001.md +11 -0
- package/rules/DEPS-BIDI-001.md +11 -0
- package/rules/DEPS-BIN-SHADOW-001.md +11 -0
- package/rules/DEPS-BUNDLED-001.md +11 -0
- package/rules/DEPS-COREPACK-001.md +11 -0
- package/rules/DEPS-DEPRECATED-REPLACE-001.md +11 -0
- package/rules/DEPS-DEV-PROD-EDGE-001.md +11 -0
- package/rules/DEPS-DUALPACKAGE-001.md +11 -0
- package/rules/DEPS-ENGINE-STRICT-001.md +11 -0
- package/rules/DEPS-FILESPEC-001.md +11 -0
- package/rules/DEPS-FLOAT-001.md +11 -0
- package/rules/DEPS-FLOAT-002.md +11 -0
- package/rules/DEPS-GITDEP-001.md +11 -0
- package/rules/DEPS-GITSPEC-001.md +11 -0
- package/rules/DEPS-GRAPH-ALIAS-001.md +11 -0
- package/rules/DEPS-GRAPH-OPTIONAL-001.md +11 -0
- package/rules/DEPS-HOMOGLYPH-001.md +11 -0
- package/rules/DEPS-LINKDEP-001.md +11 -0
- package/rules/DEPS-LOCKOMIT-001.md +11 -0
- package/rules/DEPS-LOCKPATH-001.md +11 -0
- package/rules/DEPS-LOCKVER-001.md +11 -0
- package/rules/DEPS-MIXEDSCRIPT-001.md +11 -0
- package/rules/DEPS-MULTLOCK-001.md +11 -0
- package/rules/DEPS-NAME-CASE-001.md +11 -0
- package/rules/DEPS-NAME-ENCODED-001.md +11 -0
- package/rules/DEPS-NAME-LENGTH-001.md +11 -0
- package/rules/DEPS-NOINTEGRITY-001.md +11 -0
- package/rules/DEPS-NONSEMVER-001.md +11 -0
- package/rules/DEPS-NORESOLVED-001.md +11 -0
- package/rules/DEPS-NPMALIAS-001.md +11 -0
- package/rules/DEPS-NPMRC-HOME-001.md +11 -0
- package/rules/DEPS-NPMRC-REG-001.md +11 -0
- package/rules/DEPS-NPMRC-SCRIPT-001.md +11 -0
- package/rules/DEPS-OPTIONAL-IMPORT-001.md +11 -0
- package/rules/DEPS-OSCPU-001.md +11 -0
- package/rules/DEPS-OVERRIDE-ALIAS-001.md +11 -0
- package/rules/DEPS-OVERRIDE-VULN-001.md +11 -0
- package/rules/DEPS-OVERRIDE-WIDE-001.md +11 -0
- package/rules/DEPS-PACKAGEMANAGER-001.md +13 -0
- package/rules/DEPS-PACKAGEMANAGER-002.md +11 -0
- package/rules/DEPS-PEER-MISSING-001.md +11 -0
- package/rules/DEPS-PEER-UNDECLARED-001.md +11 -0
- package/rules/DEPS-PHANTOM-002.md +11 -0
- package/rules/DEPS-PUBLISHCONFIG-001.md +11 -0
- package/rules/DEPS-PUBLISHCONFIG-002.md +11 -0
- package/rules/DEPS-REG-AGE-001.md +11 -0
- package/rules/DEPS-REG-BIN-001.md +11 -0
- package/rules/DEPS-REG-BUILDER-001.md +11 -0
- package/rules/DEPS-REG-DEPRECATED-001.md +11 -0
- package/rules/DEPS-REG-DEPS-001.md +11 -0
- package/rules/DEPS-REG-DRIFT-001.md +11 -0
- package/rules/DEPS-REG-ENGINES-001.md +11 -0
- package/rules/DEPS-REG-INSTALLSCRIPT-001.md +11 -0
- package/rules/DEPS-REG-INTEGRITY-001.md +11 -0
- package/rules/DEPS-REG-MAINTAINER-001.md +11 -0
- package/rules/DEPS-REG-NPMUSER-001.md +11 -0
- package/rules/DEPS-REG-PEER-001.md +11 -0
- package/rules/DEPS-REG-PROV-ABSENT-001.md +11 -0
- package/rules/DEPS-REG-REPO-001.md +11 -0
- package/rules/DEPS-REG-REPOSITORY-001.md +11 -0
- package/rules/DEPS-REG-SIGNATURES-001.md +11 -0
- package/rules/DEPS-REG-SUBJECT-001.md +11 -0
- package/rules/DEPS-REG-TARBALL-001.md +11 -0
- package/rules/DEPS-REG-TIME-001.md +11 -0
- package/rules/DEPS-REG-UNPUBLISHED-001.md +11 -0
- package/rules/DEPS-REPEAT-001.md +11 -0
- package/rules/DEPS-RESOLVED-HOST-001.md +11 -0
- package/rules/DEPS-RESOLVED-HTTP-001.md +11 -0
- package/rules/DEPS-ROOTVER-001.md +11 -0
- package/rules/DEPS-SCOPE-NEW-001.md +11 -0
- package/rules/DEPS-SCOPE-SYNTAX-001.md +11 -0
- package/rules/DEPS-SCOPE-TYPO-001.md +11 -0
- package/rules/DEPS-SCRIPT-BASE64-001.md +11 -0
- package/rules/DEPS-SCRIPT-BIN-001.md +11 -0
- package/rules/DEPS-SCRIPT-COND-001.md +11 -0
- package/rules/DEPS-SCRIPT-CURL-001.md +11 -0
- package/rules/DEPS-SCRIPT-DEV-001.md +11 -0
- package/rules/DEPS-SCRIPT-GIT-001.md +11 -0
- package/rules/DEPS-SCRIPT-LOCK-001.md +11 -0
- package/rules/DEPS-SCRIPT-MISMATCH-001.md +11 -0
- package/rules/DEPS-SCRIPT-MULTI-001.md +11 -0
- package/rules/DEPS-SCRIPT-NODEGYP-001.md +11 -0
- package/rules/DEPS-SCRIPT-OPTIONAL-001.md +11 -0
- package/rules/DEPS-SCRIPT-PREPARE-001.md +11 -0
- package/rules/DEPS-SCRIPT-PREPUBLISH-001.md +11 -0
- package/rules/DEPS-SCRIPT-PUBLISH-001.md +11 -0
- package/rules/DEPS-SCRIPT-ROLLUP-001.md +11 -0
- package/rules/DEPS-SCRIPT-SHEBANG-001.md +11 -0
- package/rules/DEPS-SCRIPT-TOKEN-001.md +11 -0
- package/rules/DEPS-SCRIPT-TRANSITIVE-001.md +11 -0
- package/rules/DEPS-SCRIPT-TRUSTED-001.md +11 -0
- package/rules/DEPS-SCRIPT-WRITE-001.md +11 -0
- package/rules/DEPS-SELFNAME-001.md +11 -0
- package/rules/DEPS-SEPARATOR-001.md +11 -0
- package/rules/DEPS-SHRINKWRAP-001.md +11 -0
- package/rules/DEPS-SHRINKWRAP-002.md +11 -0
- package/rules/DEPS-SUFFIX-001.md +11 -0
- package/rules/DEPS-TAGSPEC-001.md +11 -0
- package/rules/DEPS-TARBALL-BIN-001.md +11 -0
- package/rules/DEPS-TARBALL-CRED-001.md +11 -0
- package/rules/DEPS-TARBALL-DYNAMIC-001.md +11 -0
- package/rules/DEPS-TARBALL-ENV-001.md +11 -0
- package/rules/DEPS-TARBALL-HASH-001.md +11 -0
- package/rules/DEPS-TARBALL-HIDDEN-001.md +11 -0
- package/rules/DEPS-TARBALL-HOOK-001.md +11 -0
- package/rules/DEPS-TARBALL-ID-001.md +11 -0
- package/rules/DEPS-TARBALL-INSTALLJS-001.md +11 -0
- package/rules/DEPS-TARBALL-LICENSE-001.md +11 -0
- package/rules/DEPS-TARBALL-LIFECYCLE-001.md +11 -0
- package/rules/DEPS-TARBALL-MANIFEST-001.md +11 -0
- package/rules/DEPS-TARBALL-NATIVE-001.md +11 -0
- package/rules/DEPS-TARBALL-NET-001.md +11 -0
- package/rules/DEPS-TARBALL-OBFUSC-001.md +11 -0
- package/rules/DEPS-TARBALL-PATH-001.md +11 -0
- package/rules/DEPS-TARBALL-SHELL-001.md +11 -0
- package/rules/DEPS-TARBALL-SIZE-001.md +11 -0
- package/rules/DEPS-TARBALL-SKIP-001.md +11 -0
- package/rules/DEPS-TARBALL-TOPLEVEL-001.md +11 -0
- package/rules/DEPS-TRUSTED-001.md +11 -0
- package/rules/DEPS-TYPES-001.md +11 -0
- package/rules/DEPS-TYPO-TRANSITIVE-001.md +11 -0
- package/rules/DEPS-UNFIXED-001.md +11 -0
- package/rules/DEPS-URLSPEC-001.md +11 -0
- package/rules/DEPS-VENDORED-001.md +11 -0
- package/rules/DEPS-WEAKINTEGRITY-001.md +11 -0
- package/rules/DEPS-WORKSPACE-NAME-001.md +11 -0
- package/rules/README.md +35 -0
- package/rules/SAST-CIPHER-001.md +13 -0
- package/rules/SAST-CIPHER-002.md +11 -0
- package/rules/SAST-DOMXSS-001.md +11 -0
- package/rules/SAST-IDOR-001.md +11 -0
- package/rules/SAST-JWT-002.md +11 -0
- package/rules/SAST-LOGLEAK-001.md +11 -0
- package/rules/SAST-NEXT-001.md +11 -0
- package/rules/SAST-POSTMSG-001.md +11 -0
- package/rules/SAST-REACT-001.md +11 -0
- package/rules/SAST-RSA-001.md +11 -0
- package/rules/SAST-SESSION-002.md +11 -0
- package/rules/SAST-SSTI-001.md +11 -0
- package/rules/SAST-TLS-001.md +13 -0
- package/rules/SAST-TLS-002.md +13 -0
- package/rules/SAST-TOKENSTORE-001.md +11 -0
- package/rules/SAST-WEBHOOK-001.md +11 -0
- package/rules/SECRET-FILE-002.md +11 -0
- package/rules/SECRET-FILE-003.md +11 -0
- package/rules/SECRET-FILE-004.md +11 -0
- package/rules/SECRET-FILE-005.md +11 -0
- package/rules/SECRET-FILE-006.md +11 -0
- package/rules/SECRET-FILE-007.md +11 -0
- package/rules/SECRET-NEXTPUB-001.md +11 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,86 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to FullShield are documented here.
|
|
4
4
|
|
|
5
|
+
## 1.2.0
|
|
6
|
+
|
|
7
|
+
### Experimental
|
|
8
|
+
|
|
9
|
+
- Phase 105: committed credential files behind `FULLSHIELD_EXPERIMENTAL_CREDFILES` (`SECRET-FILE-002` through `SECRET-FILE-007`). Off by default. Default scan output is unchanged.
|
|
10
|
+
- Phase 95: disabled TLS verification behind `FULLSHIELD_EXPERIMENTAL_TLS` (`SAST-TLS-001`, `SAST-TLS-002`). Off by default. Default scan output is unchanged.
|
|
11
|
+
- Phase 96: crypto v2 behind `FULLSHIELD_EXPERIMENTAL_CRYPTO2` (`SAST-CIPHER-001`, `SAST-CIPHER-002`, `SAST-RSA-001`, `SAST-JWT-002`). Off by default. Default scan output is unchanged.
|
|
12
|
+
- Phase 102: Electron window settings behind `FULLSHIELD_EXPERIMENTAL_ELECTRON` (`CONFIG-ELECTRON-001`, `CONFIG-ELECTRON-002`, `CONFIG-ELECTRON-003`). Off by default. Default scan output is unchanged.
|
|
13
|
+
- Phase 104: vendored library files behind `FULLSHIELD_EXPERIMENTAL_VENDORED` (`DEPS-VENDORED-001`). Off by default. Default scan output is unchanged.
|
|
14
|
+
- Phase 97: server-side template injection behind `FULLSHIELD_EXPERIMENTAL_SSTI` (`SAST-SSTI-001`) and a RASP template-source hook (`RASP-SSTI-001`) on `ejs`, `pug`, and `nunjucks`. Off by default. Default scan output is unchanged.
|
|
15
|
+
- Phase 71: RASP hooks for MongoDB and Mongoose write and aggregate methods, Axios verbs and `axios.create()`, `undici.request`, and `undici:request:create`. Off unless `FULLSHIELD_EXPERIMENTAL_RASP=1`.
|
|
16
|
+
- Phase 72: in-request DNS pin (`dnsPinTtlMs`, default 60 seconds) refuses a later private address for a host already resolved in that request.
|
|
17
|
+
- Phase 99: webhook verifiers behind `FULLSHIELD_EXPERIMENTAL_WEBHOOK` (`SAST-WEBHOOK-001`). Off by default. Default scan output is unchanged.
|
|
18
|
+
- Phase 100: session fixation behind `FULLSHIELD_EXPERIMENTAL_SESSION2` (`SAST-SESSION-002`). Off by default. Default scan output is unchanged.
|
|
19
|
+
- Phase 98: secret logging behind `FULLSHIELD_EXPERIMENTAL_LOGLEAK` (`SAST-LOGLEAK-001`). Off by default. Default scan output is unchanged.
|
|
20
|
+
- Phase 103: Next.js boundary behind `FULLSHIELD_EXPERIMENTAL_NEXT` (`SAST-NEXT-001`, `CONFIG-NEXT-001`, `CONFIG-NEXT-002`, `SECRET-NEXTPUB-001`). Off by default. Default scan output is unchanged.
|
|
21
|
+
- Phase 101: browser JavaScript behind `FULLSHIELD_EXPERIMENTAL_BROWSER` (`SAST-DOMXSS-001`, `SAST-REACT-001`, `SAST-POSTMSG-001`, `SAST-TOKENSTORE-001`). Off by default. Default scan output is unchanged.
|
|
22
|
+
- Phase 106: unfixed dependencies behind `FULLSHIELD_EXPERIMENTAL_HEALTH` (`DEPS-UNFIXED-001`). Off by default. Default scan output is unchanged.
|
|
23
|
+
- Phase 107: IDOR hints behind `FULLSHIELD_EXPERIMENTAL_IDOR` (`SAST-IDOR-001`). Off by default. `source: rule` never fails CI. Default scan output is unchanged.
|
|
24
|
+
|
|
25
|
+
## 1.0.1 — 2026-10-20
|
|
26
|
+
|
|
27
|
+
Documentation-only release. Scanner behavior, default `scan --json` output, and exit
|
|
28
|
+
codes are unchanged. `default-scan-diff` against 1.0.0 is empty.
|
|
29
|
+
|
|
30
|
+
### Contract correction (docs/stability.md)
|
|
31
|
+
|
|
32
|
+
1.0.0's stability.md listed values in Stable that only experimental flags produce.
|
|
33
|
+
That was a documentation error. This release moves them to Experimental.
|
|
34
|
+
|
|
35
|
+
Moved from Stable to Experimental:
|
|
36
|
+
- `Finding.source` values `ai`, `user-rule`, `npm-audit`, `semgrep`, `osv-scanner`, `sarif`.
|
|
37
|
+
- `Finding.suppressedBy` (`types`, `model:<package>`).
|
|
38
|
+
- Error codes `FS-E005`–`FS-E009`, `FS-E012`–`FS-E016`.
|
|
39
|
+
- Config keys `ai`, `sast.sources`, `sast.sanitizers`.
|
|
40
|
+
|
|
41
|
+
Moved to Internal: `FS-E010`, `FS-E011` (contributor tooling only).
|
|
42
|
+
|
|
43
|
+
Added to Stable (shipped and documented as stable since 0.1.0 or 0.2.0): `watch`, `edge`,
|
|
44
|
+
`notify`, `doctor`, and the core `scan --json` finding fields.
|
|
45
|
+
|
|
46
|
+
If you depended on a moved value, it still works in 1.0.1. It may change in a later minor.
|
|
47
|
+
|
|
48
|
+
### Documentation
|
|
49
|
+
|
|
50
|
+
- `CAPABILITIES.md` rewritten. The 1.0.0 file described 0.1.1 and carried finding
|
|
51
|
+
counts that no longer match. It now links to generated files instead of copying numbers.
|
|
52
|
+
- `docs/demo.md` and `BENCHMARK.md` regenerated from runs at 1.0.1.
|
|
53
|
+
- `COMPARISON.md` is marked not citable until the Semgrep run is re-checked.
|
|
54
|
+
- History notes moved to `docs/history/`.
|
|
55
|
+
- Corrected stale lines in `errors.md`, `QUALITY.md`, `priority.md`, `NOISE-REPORT.md`,
|
|
56
|
+
and `CONTRIBUTING.md`.
|
|
57
|
+
|
|
58
|
+
### 1.0.0 notes corrected
|
|
59
|
+
|
|
60
|
+
- The 0.2.0 entry said 0.3.0 and 0.4.0 were not tagged. That was true when written.
|
|
61
|
+
Both were tagged later.
|
|
62
|
+
- 1.0.0 said Phases 52 and 78 were "merged locally". Both are in the `v1.0.0` commit
|
|
63
|
+
`d654c8b6f155bec88b2327a62402f0b35feb277d`, which contains `5a0d006` (phase 52) and
|
|
64
|
+
`4966d8b` (phase 78).
|
|
65
|
+
- Phase 77 is in 1.0.0 as `scripts/realworld-diff.mjs`. It is a dev gate and has no scan flag.
|
|
66
|
+
- Phase 81 is in 1.0.0 behind `FULLSHIELD_EXPERIMENTAL_MODELS`.
|
|
67
|
+
- Phase 82 is in 1.0.0 behind `FULLSHIELD_EXPERIMENTAL_SECRET_CHECK`.
|
|
68
|
+
- Phase 84 is in 1.0.0 behind `FULLSHIELD_EXPERIMENTAL_PRIORITY`.
|
|
69
|
+
- Phase 89 is in 1.0.0 behind `FULLSHIELD_EXPERIMENTAL_SPDX`.
|
|
70
|
+
- Phase 92 is in 1.0.0 as issue forms, companion-tool docs, and required check names. It has no scan flag.
|
|
71
|
+
- The Phase 75 and Phase 51 default-scan diffs were empty on every bench app. That shows
|
|
72
|
+
no regression. It does not show either change finds anything on those apps.
|
|
73
|
+
|
|
74
|
+
### Release check
|
|
75
|
+
|
|
76
|
+
1.0.0 was tagged before the six-job matrix was confirmed green on `main`.
|
|
77
|
+
The six required checks in `docs/branch-protection.md` passed on pull request #18:
|
|
78
|
+
https://github.com/kathanp/fullshield/actions/runs/39514123297
|
|
79
|
+
The same six checks passed on the changelog commit:
|
|
80
|
+
https://github.com/kathanp/fullshield/actions/runs/39521633354
|
|
81
|
+
`v1.0.1` is `dc2b719` on `main`. Publish succeeded:
|
|
82
|
+
https://github.com/kathanp/fullshield/actions/runs/39529799316
|
|
83
|
+
npm published `1.0.1` at 2026-10-21T02:43:27Z with SLSA provenance.
|
|
84
|
+
|
|
5
85
|
## 1.0.0 — 2026-10-20
|
|
6
86
|
|
|
7
87
|
1.0.0 freezes the stable CLI, config keys, exit codes, error codes `FS-E000`–`FS-E016`, and the library exports in `api/fullshield.api.json`. The promise is [docs/stability.md](docs/stability.md).
|
|
@@ -189,7 +269,7 @@ Off unless `FULLSHIELD_EXPERIMENTAL_DIFF=1` or `fullshield diff --experimental-d
|
|
|
189
269
|
|
|
190
270
|
## 0.2.0 — 2026-10-16
|
|
191
271
|
|
|
192
|
-
Phases 36–45 ship in this version. `0.3.0` and `0.4.0` were not tagged.
|
|
272
|
+
Phases 36–45 ship in this version. (At the time of writing, `0.3.0` and `0.4.0` were not yet tagged. Both were tagged later.)
|
|
193
273
|
|
|
194
274
|
### Phase 36 — provenance and semver
|
|
195
275
|
|
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# FullShield
|
|
2
2
|
|
|
3
|
-
**v1.
|
|
3
|
+
**v1.2.0.** One install for Node.js/TypeScript backends: detect → classify → report → notify → fix → gate (CI `--fail-on` + runtime monitor). It does not stop attacks by itself.
|
|
4
4
|
|
|
5
5
|
**Headline: dependency reachability.** A lockfile CVE is not the same as an unused package. FullShield classifies each OSV hit as `reachable` (imported and called), `imported-not-called` (−1), `reachable-via-dependency` (lockfile path from an imported direct dep — **severity kept**, path shown, e.g. `express > body-parser > qs`), `not-imported` (−2, only when no such path exists), or `reachability-unknown` (severity kept) when the lockfile format has no parsed dependency edges. DevDependency-only vulns are `info` with a `dev-only` note unless production sources import the package. Pair it with `fullshield sbom --format cyclonedx`.
|
|
6
6
|
|
|
@@ -10,7 +10,7 @@ npx fullshield scan --json --fail-on high
|
|
|
10
10
|
npx fullshield scan --sarif fullshield.sarif
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
-
1.
|
|
13
|
+
1.2.0 is the version of this tree. The stable contract is [docs/stability.md](docs/stability.md). The 1.0.1 release moved values that only experimental flags produce out of Stable. Experimental flags stay off unless you set them. Do not treat a scan as a penetration test. Reviewed recall for untouched apps is not published. The stored Next.js cold scan is 71.7 seconds, above the 60-second target.
|
|
14
14
|
|
|
15
15
|
**Supported runtime is Node.js >= 22.13.** `package.json` `engines` and `doctor` enforce that floor. `node:sqlite` runs without `--experimental-sqlite` from 22.13.0 (the module is still experimental and is loaded only by history/confirm, not by `--import` register).
|
|
16
16
|
|
|
@@ -48,7 +48,7 @@ Contributor quality gate: [docs/QUALITY.md](docs/QUALITY.md) (`npm run quality`)
|
|
|
48
48
|
|
|
49
49
|
## Non-goals (honesty is a feature)
|
|
50
50
|
|
|
51
|
-
- Does **not** find business-logic or authorization bugs (
|
|
51
|
+
- Does **not** find business-logic or authorization bugs (CSRF, missing ownership checks). It can flag routes with no auth middleware as *suspicious*. `SAST-IDOR-001` is an experimental low-confidence hint (`FULLSHIELD_EXPERIMENTAL_IDOR=1`) and does not fail CI.
|
|
52
52
|
- Does **not** replace a penetration test.
|
|
53
53
|
- Does **not** auto-delete code. `fix --apply` writes patches on a clean git tree. If project tests fail, each written file is restored from a byte-for-byte snapshot taken before the write — never `git checkout --`. `--force` on a dirty tree still refuses to touch files that have uncommitted changes.
|
|
54
54
|
- v1 is **JS/TS only**. Other languages are out of scope.
|
|
@@ -89,7 +89,7 @@ These fixtures are self-authored. Numeric SQL (`WHERE id = ` + input), ORM raw-q
|
|
|
89
89
|
|
|
90
90
|
In-scope public-bench patterns we still do not claim (one line each):
|
|
91
91
|
|
|
92
|
-
- Swig `{{
|
|
92
|
+
- Swig `{{ name }}` is `SAST-XSS-001` only when the view engine is Swig and that name is tainted from `req` or a database read. `{{csrftoken}}` and unrendered templates are not findings. Handlebars `{{ }}` stays unflagged. `autoescape: false` is still a finding.
|
|
93
93
|
- Juice Shop track-order XSS — server returns `res.json`; we do not treat JSON fields as HTML sinks.
|
|
94
94
|
- Juice Shop `url.includes(allowedUrl)` — weak allowlist helper is not a redirect sink; we flag `res.redirect(tainted)`.
|
|
95
95
|
- Juice Shop `{ _id: req.body.id }` — flagged as `SAST-NOSQLI-001` (medium) unless coerced (`String()`/`Number()`/`Boolean()`), schema-validated, or mongo-sanitize is applied. Same for goof `User.find({ password: req.body.password })`.
|
|
@@ -116,6 +116,59 @@ npx fullshield init
|
|
|
116
116
|
npx fullshield scan --fail-on high
|
|
117
117
|
```
|
|
118
118
|
|
|
119
|
+
## Commands you can run
|
|
120
|
+
|
|
121
|
+
No extra flag. These are the stable commands:
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
npx fullshield scan
|
|
125
|
+
npx fullshield scan --json --fail-on high
|
|
126
|
+
npx fullshield scan --sarif fullshield.sarif
|
|
127
|
+
npx fullshield scan --markdown report.md
|
|
128
|
+
npx fullshield scan --html report.html
|
|
129
|
+
npx fullshield scan --offline
|
|
130
|
+
npx fullshield scan --staged
|
|
131
|
+
npx fullshield fix
|
|
132
|
+
npx fullshield fix --apply
|
|
133
|
+
npx fullshield init
|
|
134
|
+
npx fullshield notify
|
|
135
|
+
npx fullshield sbom --format cyclonedx --out sbom.json
|
|
136
|
+
npx fullshield watch
|
|
137
|
+
npx fullshield edge https://app.example.com
|
|
138
|
+
npx fullshield doctor
|
|
139
|
+
npx fullshield doctor --offline
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
`scan` runs deps, secrets, sast, and config. `fix` prints patches and writes only with `--apply` on a clean git tree. `init` writes config, CI, and a pre-commit hook. `notify` sends the last scan to Slack, a webhook, or SMTP. `sbom` writes CycloneDX 1.5. `watch` alerts only on a new OSV hit. `edge` checks one URL you pass for a CDN, HTTPS, headers, and `/.env` or `/.git`. `doctor` prints Node, the lockfile, the cache, flags set to `1`, and whether OSV may use the network.
|
|
143
|
+
|
|
144
|
+
Each command below exits with `FS-E###` until its flag is exactly `1`. None of them run on a default `scan`.
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
FULLSHIELD_EXPERIMENTAL_DIFF=1 npx fullshield diff before.json after.json
|
|
148
|
+
FULLSHIELD_EXPERIMENTAL_INGEST=1 npx fullshield ingest report.sarif
|
|
149
|
+
FULLSHIELD_EXPERIMENTAL_EXPLAIN=1 npx fullshield explain <id> --from .fullshield/last-scan.json
|
|
150
|
+
FULLSHIELD_EXPERIMENTAL_DEPS_DIFF=1 npx fullshield deps-diff origin/main
|
|
151
|
+
FULLSHIELD_EXPERIMENTAL_CAPABILITIES=1 npx fullshield deps --capabilities
|
|
152
|
+
FULLSHIELD_EXPERIMENTAL_SUPPLY=1 npx fullshield install .
|
|
153
|
+
FULLSHIELD_EXPERIMENTAL_CONFIRM=1 npx fullshield confirm
|
|
154
|
+
FULLSHIELD_EXPERIMENTAL_MCP=1 npx fullshield mcp --stdio
|
|
155
|
+
FULLSHIELD_EXPERIMENTAL_HONEY=1 npx fullshield honey init
|
|
156
|
+
FULLSHIELD_EXPERIMENTAL_PLATFORM=1 npx fullshield threat-model
|
|
157
|
+
FULLSHIELD_EXPERIMENTAL_PLATFORM=1 npx fullshield report --serve
|
|
158
|
+
FULLSHIELD_EXPERIMENTAL_COMPLIANCE=1 npx fullshield report --compliance pci
|
|
159
|
+
FULLSHIELD_EXPERIMENTAL_IAC=1 npx fullshield iac
|
|
160
|
+
FULLSHIELD_EXPERIMENTAL_AGENT=1 npx fullshield agent
|
|
161
|
+
FULLSHIELD_EXPERIMENTAL_DEV=1 npx fullshield dev
|
|
162
|
+
FULLSHIELD_EXPERIMENTAL_VEX=1 npx fullshield vex
|
|
163
|
+
FULLSHIELD_EXPERIMENTAL_HOST=1 npx fullshield host --experimental-host
|
|
164
|
+
FULLSHIELD_EXPERIMENTAL_NPM_AUDIT_DIFF=1 npx fullshield npm-audit-diff --file audit.json
|
|
165
|
+
FULLSHIELD_EXPERIMENTAL_SPDX=1 npx fullshield sbom --format spdx --out sbom.spdx.json
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
`diff` compares two `scan --json` files and does not scan. `ingest` reads local SARIF, npm audit, OSV-Scanner, and Semgrep JSON and does not run those tools. `explain` prints one finding and never a verdict. `deps-diff` compares a lockfile at a git ref with the working tree. `deps --capabilities` profiles installed packages and does not run their scripts. `install` is static. `confirm` sends harmless canaries to localhost only. `mcp` is read-only. `agent` talks to a localhost mock and a local git remote. `host` reports OpenSSH exposure on Linux and does not block, patch, or harden sshd. `npm-audit-diff` compares an `npm audit --json` file you already have with scan findings. It does not run `npm`.
|
|
169
|
+
|
|
170
|
+
Default `scan` npm coverage is the lockfile `name@version`, one OSV query, import-level reachability, and a Levenshtein-1 typosquat check on direct names. Deeper npm checks are off until you set one `FULLSHIELD_EXPERIMENTAL_NPM_<NAME>=1` flag. A flag reads the lockfile, `package.json`, `.npmrc`, or a cache file already on disk. It does not install the package, run a lifecycle script, or fetch a tarball. Registry packument checks read `cacheDir/registry/` only. Tarball checks read a tarball cache only. The groups are lockfile truth, manifest and project policy, registry metadata, tarball bytes, lifecycle script text, package names, and the dependency graph. Advisory helpers for range type, withdrawn rows, CVSS, alias collapse, and package URLs do not change default OSV findings. Core and breadth rule ids are indexed in [`rules/README.md`](rules/README.md). The npm-depth ids are the `rules/DEPS-*.md` files for those flags.
|
|
171
|
+
|
|
119
172
|
Library:
|
|
120
173
|
|
|
121
174
|
```ts
|
|
@@ -137,7 +190,7 @@ app.use(shieldGuard({ mode: 'monitor', authRoutes: ['/login'] }));
|
|
|
137
190
|
|
|
138
191
|
**Experimental CI reports (off by default):** `FULLSHIELD_EXPERIMENTAL_CI_REPORTS=1` or `scan --experimental-ci-reports`, then `--github-annotations`, `--junit`, and `--gitlab`. Default console and `--json` output stay the same. Critical and high become GitHub `error` commands and JUnit failures. Medium is a GitHub warning and a JUnit failure. Low and info are GitHub notices and JUnit skips. GitLab severities are info, minor, major, critical, and blocker.
|
|
139
192
|
|
|
140
|
-
**Experimental scan diff (off by default):** `FULLSHIELD_EXPERIMENTAL_DIFF=1` or `fullshield diff --experimental-diff <before.json> <after.json>`. Compares two `scan --json` files. The match ignores the line number. It does not scan and does not decide which findings are real. Added findings at or above `--fail-on` (default high) exit 1. Baseline `suppressions` need an owner, a reason, and an expiry. The spec is [`docs/ADVANCED-SPEC.md`](docs/ADVANCED-SPEC.md).
|
|
193
|
+
**Experimental scan diff (off by default):** `FULLSHIELD_EXPERIMENTAL_DIFF=1` or `fullshield diff --experimental-diff <before.json> <after.json>`. Compares two `scan --json` files. The match ignores the line number. It does not scan and does not decide which findings are real. Added findings at or above `--fail-on` (default high) exit 1. Baseline `suppressions` need an owner, a reason, and an expiry. The spec is [`docs/history/ADVANCED-SPEC.md`](docs/history/ADVANCED-SPEC.md).
|
|
141
194
|
|
|
142
195
|
**Experimental ingest (off by default):** `FULLSHIELD_EXPERIMENTAL_INGEST=1` or `fullshield ingest --experimental-ingest <file...>`. Reads local SARIF 2.1.0, OSV-Scanner JSON, `npm audit --json`, and Semgrep JSON. It does not run those tools and does not fetch. Severity stays the tool's severity (`moderate` and Semgrep `WARNING` are stored as medium; the original token is `externalSeverity`). `fullshieldPriority` is not set.
|
|
143
196
|
|
|
@@ -176,12 +229,29 @@ app.use(shieldGuard({ mode: 'monitor', authRoutes: ['/login'] }));
|
|
|
176
229
|
| `scan --experimental-sast-gaps` | **Experimental** extra SAST sinks: ORM raw SQL, mongoose `$where`, `spawn('sh', ['-c'])`, execa `shell: true`, zx `$.raw` (`FULLSHIELD_EXPERIMENTAL_SAST_GAPS=1`). |
|
|
177
230
|
| `scan --experimental-frameworks` | **Experimental** Next.js / NestJS / Hono / Koa taint sources and AUTH (`FULLSHIELD_EXPERIMENTAL_FRAMEWORKS=1`). Default `scan` is unchanged. Runtime adapters: `fullshield/runtime/koa`, `fullshield/runtime/hono` (optional peers). |
|
|
178
231
|
| `scan --experimental-classes` | **Experimental** extra vuln classes: ReDoS, deser, XXE, upload, cookies, CSRF, mass assignment, timing compare, hash cost, GraphQL, trust-proxy (`FULLSHIELD_EXPERIMENTAL_CLASSES=1`). Default `scan` is unchanged. |
|
|
232
|
+
| `scan` crypto v2 | **Experimental** (`FULLSHIELD_EXPERIMENTAL_CRYPTO2=1`). `SAST-CIPHER-001`, `SAST-CIPHER-002`, `SAST-RSA-001`, and `SAST-JWT-002`: ECB and deprecated ciphers, literal IVs, literal symmetric keys, short RSA or secp192 keys, and JWTs with no expiry or a short HMAC secret. Off by default. |
|
|
233
|
+
| `scan` Electron | **Experimental** (`FULLSHIELD_EXPERIMENTAL_ELECTRON=1`). `CONFIG-ELECTRON-001` through `CONFIG-ELECTRON-003`: unsafe `webPreferences`, `shell.openExternal` without an https check, and a remote `loadURL` without navigation guards. Only when `electron` is installed. Off by default. |
|
|
234
|
+
| `scan` vendored JS | **Experimental** (`FULLSHIELD_EXPERIMENTAL_VENDORED=1`). `DEPS-VENDORED-001`: known-vulnerable copies of jquery, bootstrap, lodash, and the other libraries in `models/vendored.json`, matched by banner or `VERSION` only. Off by default. |
|
|
235
|
+
| `scan` template injection | **Experimental** (`FULLSHIELD_EXPERIMENTAL_SSTI=1`). `SAST-SSTI-001`: tainted template source for the engines in `models/ssti.json`. Off by default. |
|
|
236
|
+
| `scan` webhooks | **Experimental** (`FULLSHIELD_EXPERIMENTAL_WEBHOOK=1`). `SAST-WEBHOOK-001`: Stripe, GitHub, Slack, Shopify, and Twilio handlers with no verifier. Off by default. |
|
|
237
|
+
| `scan` session fixation | **Experimental** (`FULLSHIELD_EXPERIMENTAL_SESSION2=1`). `SAST-SESSION-002`: login writes the session without `regenerate`. `req.login` counts only for passport 0.6.0 or newer. Off by default. |
|
|
238
|
+
| `scan` log secrets | **Experimental** (`FULLSHIELD_EXPERIMENTAL_LOGLEAK=1`). `SAST-LOGLEAK-001`: credential headers, auth-route bodies, and secret-named identifiers written to a logger. Off by default. |
|
|
239
|
+
| `scan` Next.js boundary | **Experimental** (`FULLSHIELD_EXPERIMENTAL_NEXT=1`). `SAST-NEXT-001`, `CONFIG-NEXT-001`, `CONFIG-NEXT-002`, and `SECRET-NEXTPUB-001`. Off by default. |
|
|
240
|
+
| `scan` browser JS | **Experimental** (`FULLSHIELD_EXPERIMENTAL_BROWSER=1`). `SAST-DOMXSS-001`, `SAST-REACT-001`, `SAST-POSTMSG-001`, and `SAST-TOKENSTORE-001`. Server taint rules skip browser sources. Off by default. |
|
|
241
|
+
| `scan` unfixed deps | **Experimental** (`FULLSHIELD_EXPERIMENTAL_HEALTH=1`). `DEPS-UNFIXED-001`: a production dependency with no fixed version whose last publish is older than 730 days. Off by default. |
|
|
242
|
+
| `scan` IDOR hints | **Experimental** (`FULLSHIELD_EXPERIMENTAL_IDOR=1`). `SAST-IDOR-001`: a low-confidence hint. `source: rule` does not fail CI. Off by default. |
|
|
243
|
+
| `scan` TLS verification | **Experimental** (`FULLSHIELD_EXPERIMENTAL_TLS=1`). `SAST-TLS-001` and `SAST-TLS-002`: `rejectUnauthorized: false`, `checkServerIdentity` returning undefined, and `NODE_TLS_REJECT_UNAUTHORIZED=0` in source, Docker, compose, package scripts, and `.env` files. Test paths are low. A `NODE_ENV !== 'production'` guard is medium. Off by default. |
|
|
244
|
+
| `scan` credential files | **Experimental** (`FULLSHIELD_EXPERIMENTAL_CREDFILES=1`). `SECRET-FILE-002` through `SECRET-FILE-007`: `.npmrc` auth literals, Docker `config.json` auth, kubeconfig tokens, Terraform state, service-account keys, and private key files. Masked. Off by default. `--staged` includes them. |
|
|
179
245
|
| `scan --history` / `--bundle <dir>` / `--verify-secrets` | **Experimental** secrets advanced (`FULLSHIELD_EXPERIMENTAL_SECRETS_ADV=1` or `scan --experimental-secrets-adv`). History streams `git log -p` (first-introduced commit, still-at-HEAD). Bundle scans `dist/` `.next/static` `build/` for browser-exposed keys including `NEXT_PUBLIC_*`/`VITE_*`. `--verify-secrets` is never default and is **not** in generated CI templates; it needs `--i-own-these-credentials` and only hits read-only identity endpoints (AWS STS GetCallerIdentity, GitHub `GET /user`, Stripe `GET /v1/balance`, Slack `auth.test`). Results: `live` / `revoked` / `unknown`. The key is never logged. |
|
|
180
246
|
| `scan` provenance | **Experimental** (`FULLSHIELD_EXPERIMENTAL_PROVENANCE=1`). `SUPPLY-PROV-001` (medium) when an installed version drops `dist.attestations`, is published by a user absent from the previous 10 versions, or is inside the Phase 62 release-age window. `registry.npmjs.org` only. `--offline` uses the registry cache; a miss stays unknown and is not a finding. Not a malicious-package claim. |
|
|
181
247
|
| `vex` | **Experimental** OpenVEX / CycloneDX VEX from reachability (`FULLSHIELD_EXPERIMENTAL_VEX=1`). `not_affected` + `vulnerable_code_not_in_execute_path` only when reachability is `not-imported`; otherwise `under_investigation`. Never guessed. Also enables worm/workflow indicators, unsafe `dependency-override` proposals, and a provenance coverage score. Apply writes `package.json` and prints `run npm install`; it does not edit the lockfile. |
|
|
182
248
|
| `scan --experimental-mcpcfg` | **Experimental** MCP client/server config rules `MCP-001`–`MCP-005` (`FULLSHIELD_EXPERIMENTAL_MCPCFG=1`). Default `scan` emits no `MCP-*` IDs. |
|
|
183
249
|
| `scan --include-home` | **Experimental** also scan MCP configs under the user home (`.cursor/mcp.json`, `.vscode/mcp.json`, `.mcp.json`, Claude Desktop). Requires `FULLSHIELD_EXPERIMENTAL_MCPCFG=1`. Never implied. |
|
|
184
250
|
| `host --experimental-host` | **Experimental** Linux-only OpenSSH exposure check (`FULLSHIELD_EXPERIMENTAL_HOST=1`). Reports `HOST-SSH-001`..`003` (version, no `LoginGraceTime 0`, auth timeout attempts). Refuses without `--experimental-host`. Default `scan` is unchanged. Skips with an info message on macOS, Windows, containers without sshd, and PaaS. **What it does NOT do:** FullShield does not stop OS or SSH exploits. |
|
|
251
|
+
| `explain` | **Experimental** (`FULLSHIELD_EXPERIMENTAL_EXPLAIN=1`). `fullshield explain <id> --from <scan.json>` prints one finding. It never shows a verdict. |
|
|
252
|
+
| `deps-diff` | **Experimental** (`FULLSHIELD_EXPERIMENTAL_DEPS_DIFF=1`). Compare the lockfile at a git ref with the working tree. |
|
|
253
|
+
| `npm-audit-diff` | **Experimental** (`FULLSHIELD_EXPERIMENTAL_NPM_AUDIT_DIFF=1`). `fullshield npm-audit-diff --file audit.json --from scan.json` compares a local `npm audit --json` file with scan findings. Without `--from` it reads `.fullshield/last-scan.json`. It does not run `npm audit`. |
|
|
254
|
+
| `scan` npm depth | **Experimental** (`FULLSHIELD_EXPERIMENTAL_NPM_<NAME>=1`). Lockfile, manifest, `.npmrc`, registry cache, tarball cache, lifecycle script text, package names, and graph checks from phases 108–242. Off unless that flag is `1`. No install, no script execution, no tarball download. |
|
|
185
255
|
| `fix --experimental-fix-verify` | **Experimental** fix verification (`FULLSHIELD_EXPERIMENTAL_FIX_VERIFY=1`). Each `fix` patch and each `explain` diff is applied in memory and re-scanned. `introduces-finding` is never written. `does-not-remove` needs `--force-unverified`. Dependency version checks read the OSV cache only. |
|
|
186
256
|
|
|
187
257
|
Inline ignore (reason required): `// fullshield-ignore SAST-SQLI-001: reviewed`
|