supply-chain-guard 6.3.0 → 6.3.2
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 +46 -7
- package/action.yml +39 -1
- package/dist/catalog-digest.d.ts +4 -4
- package/dist/catalog-digest.js +4 -4
- package/dist/cli.js +1 -1
- package/dist/dependency-confusion.js +1 -1
- package/dist/internal-disclosure.d.ts +7 -1
- package/dist/internal-disclosure.d.ts.map +1 -1
- package/dist/internal-disclosure.js +51 -8
- package/dist/internal-disclosure.js.map +1 -1
- package/dist/ioc-blocklist.d.ts.map +1 -1
- package/dist/ioc-blocklist.js +22 -0
- package/dist/ioc-blocklist.js.map +1 -1
- package/dist/npm-scanner.d.ts.map +1 -1
- package/dist/npm-scanner.js +10 -3
- package/dist/npm-scanner.js.map +1 -1
- package/dist/pattern-applicability.d.ts +7 -1
- package/dist/pattern-applicability.d.ts.map +1 -1
- package/dist/pattern-applicability.js +19 -4
- package/dist/pattern-applicability.js.map +1 -1
- package/dist/pattern-scanner.d.ts +4 -1
- package/dist/pattern-scanner.d.ts.map +1 -1
- package/dist/pattern-scanner.js +5 -2
- package/dist/pattern-scanner.js.map +1 -1
- package/dist/patterns.d.ts.map +1 -1
- package/dist/patterns.js +4 -0
- package/dist/patterns.js.map +1 -1
- package/dist/pypi-scanner.js +1 -1
- package/dist/reporter.js +12 -12
- package/dist/sbom-generator.js +1 -1
- package/dist/scanner.d.ts.map +1 -1
- package/dist/scanner.js +19 -9
- package/dist/scanner.js.map +1 -1
- package/dist/script-language.d.ts +48 -0
- package/dist/script-language.d.ts.map +1 -0
- package/dist/script-language.js +227 -0
- package/dist/script-language.js.map +1 -0
- package/dist/threat-intel.d.ts +1 -1
- package/dist/threat-intel.d.ts.map +1 -1
- package/dist/threat-intel.js +273 -1304
- package/dist/threat-intel.js.map +1 -1
- package/dist/vscode-scanner.js +1 -1
- package/dist/workflow-modeler.d.ts.map +1 -1
- package/dist/workflow-modeler.js +395 -7
- package/dist/workflow-modeler.js.map +1 -1
- package/package.json +2 -2
- package/self-scan-manifest.json +8 -8
package/README.md
CHANGED
|
@@ -36,7 +36,7 @@ Gate every pull request:
|
|
|
36
36
|
|
|
37
37
|
```yaml
|
|
38
38
|
- uses: actions/checkout@v4
|
|
39
|
-
- uses: homeofe/supply-chain-guard@v6.3.
|
|
39
|
+
- uses: homeofe/supply-chain-guard@v6.3.2
|
|
40
40
|
```
|
|
41
41
|
|
|
42
42
|
Let your AI coding agent check a package before it installs it (MCP):
|
|
@@ -126,6 +126,7 @@ is something to match:
|
|
|
126
126
|
- Shannon entropy analysis for encoded payloads
|
|
127
127
|
- Proxy handler traps, WebAssembly from external sources
|
|
128
128
|
- Scan-coverage transparency: files above the 5 MB content-scan limit are surfaced as `FILE_TOO_LARGE_SKIPPED` (info severity, never affects exit codes) instead of being silently skipped - padding a payload past the limit no longer hides it from the report
|
|
129
|
+
- Executable scripts without an extension are read in the language their shebang names (`#!/bin/sh`, `#!/usr/bin/env node`, `python3`, `ruby`, `perl` and others), and an extensionless file named like a git hook (`pre-commit`, `pre-push`, ...) is read as shell even without one, so hooks under `scripts/hooks/` or `.husky/` and `bin/` launchers in a directory scan or an npm tarball are content-scanned. `*.bats` suites are read as bash and, like `*.test.ts`, count as test files, and Perl source is read as `.pl`/`.pm` too. A file with no extension, no shebang and no hook name is still not read
|
|
129
130
|
|
|
130
131
|
### Supply Chain Attacks
|
|
131
132
|
- Install hook deep analysis (secret harvesting, download-exec chains, binary blobs)
|
|
@@ -209,7 +210,7 @@ Run the scanner as a [pre-commit](https://pre-commit.com) hook (Python-ecosystem
|
|
|
209
210
|
```yaml
|
|
210
211
|
repos:
|
|
211
212
|
- repo: https://github.com/homeofe/supply-chain-guard
|
|
212
|
-
rev: v6.3.
|
|
213
|
+
rev: v6.3.2
|
|
213
214
|
hooks:
|
|
214
215
|
- id: supply-chain-guard
|
|
215
216
|
```
|
|
@@ -241,7 +242,7 @@ The hook scans the repository root on every commit and fails on high or critical
|
|
|
241
242
|
Run the scanner without a Node toolchain via the official multi-arch image (linux/amd64, linux/arm64), published to GHCR on every release tag:
|
|
242
243
|
|
|
243
244
|
```bash
|
|
244
|
-
docker run --rm -v ${PWD}:/scan ghcr.io/homeofe/supply-chain-guard:6.3.
|
|
245
|
+
docker run --rm -v ${PWD}:/scan ghcr.io/homeofe/supply-chain-guard:6.3.2 scan /scan
|
|
245
246
|
```
|
|
246
247
|
|
|
247
248
|
`${PWD}` works in bash, zsh, and PowerShell; in cmd.exe use `%cd%` instead.
|
|
@@ -998,7 +999,7 @@ jobs:
|
|
|
998
999
|
runs-on: ubuntu-latest
|
|
999
1000
|
steps:
|
|
1000
1001
|
- uses: actions/checkout@v4
|
|
1001
|
-
- uses: homeofe/supply-chain-guard@v6.3.
|
|
1002
|
+
- uses: homeofe/supply-chain-guard@v6.3.2
|
|
1002
1003
|
with:
|
|
1003
1004
|
fail-on: critical
|
|
1004
1005
|
comment-on-pr: true
|
|
@@ -1086,7 +1087,7 @@ two are never confused. If a deliberately frozen rule set is the intent, exclude
|
|
|
1086
1087
|
the rule by name:
|
|
1087
1088
|
|
|
1088
1089
|
```yaml
|
|
1089
|
-
- uses: homeofe/supply-chain-guard@v6.3.
|
|
1090
|
+
- uses: homeofe/supply-chain-guard@v6.3.2
|
|
1090
1091
|
with:
|
|
1091
1092
|
exclude-rules: THREAT_FEED_STALE
|
|
1092
1093
|
```
|
|
@@ -1157,7 +1158,7 @@ preceding `feed refresh` in the workflow does not count. `catalog: required`
|
|
|
1157
1158
|
on the Action therefore needs:
|
|
1158
1159
|
|
|
1159
1160
|
```yaml
|
|
1160
|
-
- uses: homeofe/supply-chain-guard@v6.3.
|
|
1161
|
+
- uses: homeofe/supply-chain-guard@v6.3.2
|
|
1161
1162
|
with:
|
|
1162
1163
|
refresh-catalog: true
|
|
1163
1164
|
```
|
|
@@ -1168,11 +1169,49 @@ setting rather than firing on every scan. If scanning against the bundled set
|
|
|
1168
1169
|
alone is the intent, exclude the rule by name:
|
|
1169
1170
|
|
|
1170
1171
|
```yaml
|
|
1171
|
-
- uses: homeofe/supply-chain-guard@v6.3.
|
|
1172
|
+
- uses: homeofe/supply-chain-guard@v6.3.2
|
|
1172
1173
|
with:
|
|
1173
1174
|
exclude-rules: THREAT_FEED_CATALOG_MISSING
|
|
1174
1175
|
```
|
|
1175
1176
|
|
|
1177
|
+
### How the Action installs the scanner it runs
|
|
1178
|
+
|
|
1179
|
+
The Action does not trust the registry to hand it the right scanner. The npm
|
|
1180
|
+
version is pinned in `action.yml`, and that alone would let a registry or CDN
|
|
1181
|
+
response carrying other bytes under that version run as the scanner, next to
|
|
1182
|
+
your checkout and your token. So before anything is scanned:
|
|
1183
|
+
|
|
1184
|
+
1. The pinned version is installed into a throwaway project under
|
|
1185
|
+
`RUNNER_TEMP`, from `https://registry.npmjs.org/`, with `--ignore-scripts`,
|
|
1186
|
+
never globally. Its lockfile records the integrity of the tarball on disk.
|
|
1187
|
+
2. `npm audit signatures --include-attestations` verifies the registry
|
|
1188
|
+
signature and the Sigstore provenance of what was installed.
|
|
1189
|
+
3. `scripts/verify-action-install.mjs` then requires what npm does not: that
|
|
1190
|
+
the provenance exists at all, that its signing certificate was issued to
|
|
1191
|
+
this repository (by name and by numeric id) running
|
|
1192
|
+
`.github/workflows/ci.yml` at the release tag, and that it describes the
|
|
1193
|
+
tarball the lockfile recorded.
|
|
1194
|
+
|
|
1195
|
+
Any failure stops the job with an error annotation naming the check, before the
|
|
1196
|
+
scan step runs and before the scanner reaches `PATH`. No input changes this and
|
|
1197
|
+
the inputs and outputs are unchanged.
|
|
1198
|
+
|
|
1199
|
+
What this covers is the scanner package itself. Its npm dependencies (today one,
|
|
1200
|
+
`commander`, resolved within its declared range at install time) are checked by
|
|
1201
|
+
registry signature only: they carry no provenance from this repository, and the
|
|
1202
|
+
published package ships no shrinkwrap that would pin them.
|
|
1203
|
+
|
|
1204
|
+
Two operational requirements follow. The runner needs npm 11.12.0 or later,
|
|
1205
|
+
which Node 24.15.0 and later bundle. The Action's `actions/setup-node` step uses
|
|
1206
|
+
`check-latest: true`, so a runner whose tool cache holds an older Node 24
|
|
1207
|
+
resolves the newest 24.x instead; if npm is still too old after that, the install
|
|
1208
|
+
step fails closed with a message saying so. And the step talks to
|
|
1209
|
+
`registry.npmjs.org` and to the Sigstore trust root CDN
|
|
1210
|
+
(`tuf-repo-cdn.sigstore.dev`). The public registry is set explicitly, whatever a
|
|
1211
|
+
runner's `.npmrc` says, because the provenance check is only meaningful against
|
|
1212
|
+
the registry that recorded the attestation; a runner that can reach only a
|
|
1213
|
+
registry mirror cannot verify the scanner and will not run it.
|
|
1214
|
+
|
|
1176
1215
|
### Action Inputs
|
|
1177
1216
|
|
|
1178
1217
|
| Input | Description | Default |
|
package/action.yml
CHANGED
|
@@ -76,15 +76,53 @@ outputs:
|
|
|
76
76
|
runs:
|
|
77
77
|
using: "composite"
|
|
78
78
|
steps:
|
|
79
|
+
# check-latest: a runner's tool cache can hold an old Node 24 whose npm is
|
|
80
|
+
# older than 11.12.0, which cannot report the attestations the install step
|
|
81
|
+
# verifies. Resolving the newest 24.x avoids that; if npm is still too old,
|
|
82
|
+
# the install step fails closed and says so.
|
|
79
83
|
- name: Setup Node.js
|
|
80
84
|
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
|
|
81
85
|
with:
|
|
82
86
|
node-version: "24"
|
|
87
|
+
check-latest: true
|
|
83
88
|
package-manager-cache: false
|
|
84
89
|
|
|
90
|
+
# The scanner is verified before it runs, not only pinned by version: a
|
|
91
|
+
# registry or CDN response carrying other bytes under this version would
|
|
92
|
+
# otherwise run with the checkout and the token in reach. It is installed
|
|
93
|
+
# into a throwaway project (never -g, so a lockfile records exactly what was
|
|
94
|
+
# installed), npm verifies the registry signature and the Sigstore
|
|
95
|
+
# provenance, and scripts/verify-action-install.mjs then requires that the
|
|
96
|
+
# provenance exists and was signed by this repository's release workflow at
|
|
97
|
+
# this version's tag, for the tarball on disk. Any failure stops the Action
|
|
98
|
+
# before the scan step; nothing is added to PATH.
|
|
85
99
|
- name: Install supply-chain-guard
|
|
86
100
|
shell: bash
|
|
87
|
-
|
|
101
|
+
env:
|
|
102
|
+
SCG_VERSION: "6.3.2"
|
|
103
|
+
SCG_EXPECTED_REPOSITORY: "homeofe/supply-chain-guard"
|
|
104
|
+
SCG_EXPECTED_REPOSITORY_ID: "1185867580"
|
|
105
|
+
SCG_EXPECTED_WORKFLOW: ".github/workflows/ci.yml"
|
|
106
|
+
run: |
|
|
107
|
+
set -euo pipefail
|
|
108
|
+
SCG_INSTALL_DIR=$(mktemp -d "$RUNNER_TEMP/scg-install.XXXXXX")
|
|
109
|
+
export SCG_INSTALL_DIR
|
|
110
|
+
printf '{"name":"scg-action-install","version":"0.0.0","private":true}\n' > "$SCG_INSTALL_DIR/package.json"
|
|
111
|
+
# The public registry explicitly: provenance and registry keys are
|
|
112
|
+
# verified against it, and a runner-level .npmrc must not redirect this.
|
|
113
|
+
npm install --prefix "$SCG_INSTALL_DIR" --save-exact --ignore-scripts --no-audit --no-fund \
|
|
114
|
+
--registry=https://registry.npmjs.org/ "supply-chain-guard@$SCG_VERSION"
|
|
115
|
+
SCG_NPM_VERSION=$(npm --version)
|
|
116
|
+
export SCG_NPM_VERSION
|
|
117
|
+
export SCG_AUDIT_JSON="$SCG_INSTALL_DIR/audit-signatures.json"
|
|
118
|
+
if ! (cd "$SCG_INSTALL_DIR" && npm audit signatures --json --include-attestations \
|
|
119
|
+
--registry=https://registry.npmjs.org/ > "$SCG_AUDIT_JSON"); then
|
|
120
|
+
echo "::error title=supply-chain-guard install verification failed::npm audit signatures rejected the installed scanner; it will not be run." >&2
|
|
121
|
+
cat "$SCG_AUDIT_JSON" >&2 || true
|
|
122
|
+
exit 1
|
|
123
|
+
fi
|
|
124
|
+
node "$GITHUB_ACTION_PATH/scripts/verify-action-install.mjs"
|
|
125
|
+
echo "$SCG_INSTALL_DIR/node_modules/.bin" >> "$GITHUB_PATH"
|
|
88
126
|
|
|
89
127
|
- name: Run scan
|
|
90
128
|
id: scan
|
package/dist/catalog-digest.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
export declare const CATALOG_DIGEST: {
|
|
2
|
-
readonly version: "6.3.
|
|
3
|
-
readonly sha256: "
|
|
4
|
-
readonly entriesSha256: "
|
|
5
|
-
readonly entryCount:
|
|
2
|
+
readonly version: "6.3.2";
|
|
3
|
+
readonly sha256: "2b986e3d5e07d16bad13558323ffc5ad1f0463a3ca5a028dbf4bbeb3b4dfd7ac";
|
|
4
|
+
readonly entriesSha256: "e36ca343f6097a0a970d232244046bf90f2472a38ef90f8dc6afb469fed1b30f";
|
|
5
|
+
readonly entryCount: 87915;
|
|
6
6
|
readonly shardCount: 2;
|
|
7
7
|
};
|
|
8
8
|
//# sourceMappingURL=catalog-digest.d.ts.map
|
package/dist/catalog-digest.js
CHANGED
|
@@ -14,10 +14,10 @@ exports.CATALOG_DIGEST = void 0;
|
|
|
14
14
|
// read off loadThreatIntel()'s hot path, is typechecked, and supplies the
|
|
15
15
|
// version refreshFeed() needs to build the catalog URL.
|
|
16
16
|
exports.CATALOG_DIGEST = {
|
|
17
|
-
version: "6.3.
|
|
18
|
-
sha256: "
|
|
19
|
-
entriesSha256: "
|
|
20
|
-
entryCount:
|
|
17
|
+
version: "6.3.2",
|
|
18
|
+
sha256: "2b986e3d5e07d16bad13558323ffc5ad1f0463a3ca5a028dbf4bbeb3b4dfd7ac",
|
|
19
|
+
entriesSha256: "e36ca343f6097a0a970d232244046bf90f2472a38ef90f8dc6afb469fed1b30f",
|
|
20
|
+
entryCount: 87915,
|
|
21
21
|
shardCount: 2,
|
|
22
22
|
};
|
|
23
23
|
//# sourceMappingURL=catalog-digest.js.map
|
package/dist/cli.js
CHANGED
|
@@ -198,7 +198,7 @@ function assertDistinctOutputPaths(options) {
|
|
|
198
198
|
program
|
|
199
199
|
.name("supply-chain-guard")
|
|
200
200
|
.description("Open-source supply-chain security scanner. Detects GlassWorm and similar malware campaigns in npm packages, PyPI packages, code repos, VS Code extensions, and project dependencies.")
|
|
201
|
-
.version("6.3.
|
|
201
|
+
.version("6.3.2");
|
|
202
202
|
// ── scan command ────────────────────────────────────────────────────
|
|
203
203
|
program
|
|
204
204
|
.command("scan")
|
|
@@ -53,7 +53,7 @@ const types_js_1 = require("./types.js");
|
|
|
53
53
|
const pattern_scanner_js_1 = require("./pattern-scanner.js");
|
|
54
54
|
const json_utils_js_1 = require("./json-utils.js");
|
|
55
55
|
const publishing_anomaly_detector_js_1 = require("./publishing-anomaly-detector.js");
|
|
56
|
-
const TOOL_VERSION = "6.3.
|
|
56
|
+
const TOOL_VERSION = "6.3.2";
|
|
57
57
|
const NPM_REGISTRY = "https://registry.npmjs.org";
|
|
58
58
|
const NPM_DOWNLOADS_API = "https://api.npmjs.org/downloads/point/last-week";
|
|
59
59
|
const PYPI_REGISTRY = "https://pypi.org/pypi";
|
|
@@ -455,8 +455,14 @@ export declare function candidateTokens(line: string, meta?: {
|
|
|
455
455
|
*
|
|
456
456
|
* `runtime` carries the configured deny-list; pass
|
|
457
457
|
* `emptyInternalDisclosureRuntime()` to run the built-in shape rules alone.
|
|
458
|
+
*
|
|
459
|
+
* `languageExtension` is the language a file is read as when its path does not
|
|
460
|
+
* say (an extensionless `#!/usr/bin/env node` hook reads as `.js`; see
|
|
461
|
+
* script-language.ts). It decides only the lexical questions: comment syntax,
|
|
462
|
+
* string interpolation and `onlyExtensions`. Test-file and surface
|
|
463
|
+
* classification keep reading the real path.
|
|
458
464
|
*/
|
|
459
|
-
export declare function scanInternalDisclosure(content: string, relativePath: string, runtime?: InternalDisclosureRuntime): Finding[];
|
|
465
|
+
export declare function scanInternalDisclosure(content: string, relativePath: string, runtime?: InternalDisclosureRuntime, languageExtension?: string): Finding[];
|
|
460
466
|
/** Remediation text per rule id. */
|
|
461
467
|
export declare function getInternalDisclosureRecommendation(rule: string): string;
|
|
462
468
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"internal-disclosure.d.ts","sourceRoot":"","sources":["../src/internal-disclosure.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiEG;AAKH,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AA8GhF,qEAAqE;AACrE,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAIvD;AAED,+DAA+D;AAC/D,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAKpD;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAS5D;AAMD;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,IAAI,CAYxD;AAED,MAAM,MAAM,SAAS,GAAG,SAAS,GAAG,UAAU,GAAG,eAAe,GAAG,QAAQ,GAAG,SAAS,CAAC;AAExF;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,CAoBrD;AA0ED;;;;GAIG;AACH,cAAM,cAAc;IAaN,OAAO,CAAC,QAAQ,CAAC,OAAO;IAZpC,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,SAAS,CAAK;IACtB,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,KAAK,CAA0B;IACvC,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,WAAW,CAAM;IACzB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAsB;IAC7C,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,iBAAiB,CAAC,CAAU;IACpC,OAAO,CAAC,KAAK,CAAC,CAAiB;IAE/B,YAA6B,OAAO,EAAE,MAAM,EAAI;IAEhD,MAAM,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CA+ClC;IAED,OAAO,CAAC,SAAS;IAqIjB,OAAO,CAAC,aAAa;IASrB,OAAO,CAAC,UAAU;CAyBnB;AAED,2EAA2E;AAC3E,UAAU,6BAA6B;IACrC,EAAE,EAAE,cAAc,CAAC;CACpB;
|
|
1
|
+
{"version":3,"file":"internal-disclosure.d.ts","sourceRoot":"","sources":["../src/internal-disclosure.ts"],"names":[],"mappings":"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"}
|
|
@@ -621,8 +621,42 @@ function isPrivateAddressLexicalContextOkIndexed(content, matchStart, value, v8C
|
|
|
621
621
|
return true;
|
|
622
622
|
if (followsRequirementMarker(content, matchStart))
|
|
623
623
|
return false;
|
|
624
|
+
if (followsSpecCitation(content, matchStart))
|
|
625
|
+
return false;
|
|
624
626
|
return v8Context.allows(matchStart);
|
|
625
627
|
}
|
|
628
|
+
/**
|
|
629
|
+
* A section number cited after the specification it belongs to, on the same
|
|
630
|
+
* line: `(JSON Schema 2020-12, 10.3.2.3)`, `ECMA-262: 10.4.2.1`,
|
|
631
|
+
* `RFC 9110, 10.2.1.1`. Standards number their sections in dotted parts, and a
|
|
632
|
+
* chapter 10 four-part number has the 10/8 shape. Only a named specification
|
|
633
|
+
* (with an optional version) followed by a comma or colon counts, and only when
|
|
634
|
+
* adjacent: `JSON Schema server, 10.3.2.3` names a host. The RFCs that DEFINE
|
|
635
|
+
* private or special-purpose address space are excluded, because a literal after
|
|
636
|
+
* them is an example address, not a section: `RFC 1918, 10.3.2.3`.
|
|
637
|
+
*/
|
|
638
|
+
const SPEC_CITATION_AT_END = new RegExp(String.raw `(?:^|[^\w-])(?:` +
|
|
639
|
+
[
|
|
640
|
+
String.raw `json\s+schema(?:\s+(?:draft[-\s]?\d{1,2}|\d{4}-\d{2}))?`,
|
|
641
|
+
String.raw `ecma-\d{2,4}(?:\s+\d{1,2}(?:st|nd|rd|th)\s+edition)?`,
|
|
642
|
+
String.raw `iso(?:\/iec)?\s?\d{3,5}(?:-\d{1,3}){0,3}(?::\d{4})?`,
|
|
643
|
+
String.raw `rfc\s?(?!(?:1918|3927|4193|5735|6598|6890)\b)\d{3,5}`,
|
|
644
|
+
].join("|") +
|
|
645
|
+
String.raw `)\s*[,:]\s*$`, "i");
|
|
646
|
+
/** Longest citation plus punctuation and a little spacing; bounds the lookback. */
|
|
647
|
+
const SPEC_CITATION_WINDOW = 48;
|
|
648
|
+
function followsSpecCitation(content, matchStart) {
|
|
649
|
+
const start = Math.max(0, matchStart - SPEC_CITATION_WINDOW);
|
|
650
|
+
let prefix = content.slice(start, matchStart);
|
|
651
|
+
const newline = prefix.lastIndexOf("\n");
|
|
652
|
+
if (newline >= 0)
|
|
653
|
+
prefix = prefix.slice(newline + 1);
|
|
654
|
+
// Same sentinel as followsRequirementMarker: a window cut mid-line is not a
|
|
655
|
+
// word boundary.
|
|
656
|
+
else if (start > 0)
|
|
657
|
+
prefix = "x" + prefix;
|
|
658
|
+
return SPEC_CITATION_AT_END.test(prefix);
|
|
659
|
+
}
|
|
626
660
|
/**
|
|
627
661
|
* A requirement marker written directly in front of the candidate, on the same
|
|
628
662
|
* line: `Req 10.4.1.1`, `Requirement 10.4.1.1`, `§ 10.4.1.1`. PCI DSS v4.0
|
|
@@ -2085,19 +2119,26 @@ function truncatedFinding(relativePath, reasons) {
|
|
|
2085
2119
|
*
|
|
2086
2120
|
* `runtime` carries the configured deny-list; pass
|
|
2087
2121
|
* `emptyInternalDisclosureRuntime()` to run the built-in shape rules alone.
|
|
2122
|
+
*
|
|
2123
|
+
* `languageExtension` is the language a file is read as when its path does not
|
|
2124
|
+
* say (an extensionless `#!/usr/bin/env node` hook reads as `.js`; see
|
|
2125
|
+
* script-language.ts). It decides only the lexical questions: comment syntax,
|
|
2126
|
+
* string interpolation and `onlyExtensions`. Test-file and surface
|
|
2127
|
+
* classification keep reading the real path.
|
|
2088
2128
|
*/
|
|
2089
|
-
function scanInternalDisclosure(content, relativePath, runtime = emptyInternalDisclosureRuntime()) {
|
|
2129
|
+
function scanInternalDisclosure(content, relativePath, runtime = emptyInternalDisclosureRuntime(), languageExtension) {
|
|
2090
2130
|
const findings = [];
|
|
2091
2131
|
const normalizedPath = relativePath.replace(/\\/g, "/");
|
|
2132
|
+
const languagePath = languageExtension ? `${normalizedPath}${languageExtension}` : normalizedPath;
|
|
2092
2133
|
const isTestFile = TEST_FILE.test(normalizedPath);
|
|
2093
2134
|
const surface = classifyFileSurface(normalizedPath);
|
|
2094
|
-
const isMarkdown = MARKDOWN_FILE.test(
|
|
2095
|
-
const isCodeFile = CODE_FILE.test(
|
|
2096
|
-
const hashIsComment = !C_FAMILY_FILE.test(
|
|
2097
|
-
const isJsonFile = JSON_FILE.test(
|
|
2098
|
-
const interpolation = JS_FAMILY_FILE.test(
|
|
2135
|
+
const isMarkdown = MARKDOWN_FILE.test(languagePath);
|
|
2136
|
+
const isCodeFile = CODE_FILE.test(languagePath);
|
|
2137
|
+
const hashIsComment = !C_FAMILY_FILE.test(languagePath);
|
|
2138
|
+
const isJsonFile = JSON_FILE.test(languagePath);
|
|
2139
|
+
const interpolation = JS_FAMILY_FILE.test(languagePath)
|
|
2099
2140
|
? "js"
|
|
2100
|
-
: PYTHON_FILE.test(
|
|
2141
|
+
: PYTHON_FILE.test(languagePath)
|
|
2101
2142
|
? "python"
|
|
2102
2143
|
: null;
|
|
2103
2144
|
const index = buildLineIndex(content);
|
|
@@ -2162,7 +2203,9 @@ function scanInternalDisclosure(content, relativePath, runtime = emptyInternalDi
|
|
|
2162
2203
|
// Dockerfile (lastIndexOf on the whole path would slice from a directory dot).
|
|
2163
2204
|
const basename = normalizedPath.slice(normalizedPath.lastIndexOf("/") + 1);
|
|
2164
2205
|
const dotAt = basename.lastIndexOf(".");
|
|
2165
|
-
const fileExt =
|
|
2206
|
+
const fileExt = languageExtension
|
|
2207
|
+
? languageExtension.toLowerCase()
|
|
2208
|
+
: dotAt > 0 ? basename.slice(dotAt).toLowerCase() : "";
|
|
2166
2209
|
for (const pattern of exports.INTERNAL_DISCLOSURE_PATTERNS) {
|
|
2167
2210
|
// Mirrors checkFilePatterns() in scanner.ts, so a PatternEntry behaves the
|
|
2168
2211
|
// same way whichever loop consumes it.
|