supply-chain-guard 6.4.3 → 6.5.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 CHANGED
@@ -30,7 +30,7 @@ Gate every pull request:
30
30
 
31
31
  ```yaml
32
32
  - uses: actions/checkout@v4
33
- - uses: homeofe/supply-chain-guard@v6.4.3
33
+ - uses: homeofe/supply-chain-guard@v6.5.0
34
34
  ```
35
35
 
36
36
  Let your AI coding agent check a package before it installs it (MCP):
@@ -204,7 +204,7 @@ Run the scanner as a [pre-commit](https://pre-commit.com) hook (Python-ecosystem
204
204
  ```yaml
205
205
  repos:
206
206
  - repo: https://github.com/homeofe/supply-chain-guard
207
- rev: v6.4.3
207
+ rev: v6.5.0
208
208
  hooks:
209
209
  - id: supply-chain-guard
210
210
  ```
@@ -236,7 +236,7 @@ The hook scans the repository root on every commit and fails on high or critical
236
236
  Run the scanner without a Node toolchain via the official multi-arch image (linux/amd64, linux/arm64), published to GHCR on every release tag:
237
237
 
238
238
  ```bash
239
- docker run --rm -v ${PWD}:/scan ghcr.io/homeofe/supply-chain-guard:6.4.3 scan /scan
239
+ docker run --rm -v ${PWD}:/scan ghcr.io/homeofe/supply-chain-guard:6.5.0 scan /scan
240
240
  ```
241
241
 
242
242
  `${PWD}` works in bash, zsh, and PowerShell; in cmd.exe use `%cd%` instead.
@@ -245,8 +245,8 @@ The image keeps the catalog cache in `/cache` (`SCG_CACHE_DIR`), so it is gone
245
245
  after `--rm`. To keep it across runs, mount a named volume there:
246
246
 
247
247
  ```bash
248
- docker run --rm -v scg-cache:/cache ghcr.io/homeofe/supply-chain-guard:6.4.3 feed refresh
249
- docker run --rm -v scg-cache:/cache -v ${PWD}:/scan ghcr.io/homeofe/supply-chain-guard:6.4.3 scan /scan
248
+ docker run --rm -v scg-cache:/cache ghcr.io/homeofe/supply-chain-guard:6.5.0 feed refresh
249
+ docker run --rm -v scg-cache:/cache -v ${PWD}:/scan ghcr.io/homeofe/supply-chain-guard:6.5.0 scan /scan
250
250
  ```
251
251
 
252
252
  ## Quickstart
@@ -750,13 +750,13 @@ malicious package is known in that ecosystem yet, and the importer or a curated
750
750
  <!-- ecosystem-coverage:begin (generated by scripts/generate-coverage-table.mjs; edit src/ecosystem-coverage.json) -->
751
751
  | Ecosystem | Files read | Rule | Indicators shipped | Imported automatically from |
752
752
  | --- | --- | --- | --- | --- |
753
- | npm | `package.json`, `package-lock.json`, `yarn.lock`, `pnpm-lock.yaml`, `bun.lock` | `MALICIOUS_DEPENDENCY`, `LOCKFILE_MALICIOUS_VERSION`, `LOCKFILE_MALICIOUS_PACKAGE` | bundle + catalog | GitHub Advisory Database, OpenSSF / OSV |
754
- | PyPI | `requirements.txt`, `pyproject.toml`, `poetry.lock`, `uv.lock`, `Pipfile.lock` | `PYTHON_MALICIOUS_PACKAGE` | bundle + catalog | GitHub Advisory Database, OpenSSF / OSV |
753
+ | npm | `package.json`, `package-lock.json`, `yarn.lock`, `pnpm-lock.yaml`, `bun.lock` | `MALICIOUS_DEPENDENCY`, `LOCKFILE_MALICIOUS_VERSION`, `LOCKFILE_MALICIOUS_PACKAGE` | bundle + catalog | GitHub Advisory Database, OpenSSF / OSV, DataDog dataset |
754
+ | PyPI | `requirements.txt`, `pyproject.toml`, `poetry.lock`, `uv.lock`, `Pipfile.lock` | `PYTHON_MALICIOUS_PACKAGE` | bundle + catalog | GitHub Advisory Database, OpenSSF / OSV, DataDog dataset |
755
755
  | RubyGems | `Gemfile`, `Gemfile.lock` | `RUBY_MALICIOUS_GEM` | bundle + catalog | GitHub Advisory Database, OpenSSF / OSV |
756
756
  | Composer (PHP) | `composer.json`, `composer.lock` | `COMPOSER_MALICIOUS_PACKAGE` | bundle + catalog | GitHub Advisory Database, OpenSSF / OSV |
757
757
  | NuGet (.NET) | `packages.lock.json`, `*.csproj`, `packages.config` | `NUGET_MALICIOUS_PACKAGE` | bundle + catalog | GitHub Advisory Database, OpenSSF / OSV |
758
758
  | Cargo (Rust) | `Cargo.toml`, `Cargo.lock` | `CARGO_MALICIOUS_CRATE` | bundle + catalog | GitHub Advisory Database, OpenSSF / OSV |
759
- | Go modules | `go.mod`, `go.sum` | `GO_MALICIOUS_MODULE` | bundle | GitHub Advisory Database, OpenSSF / OSV |
759
+ | Go modules | `go.mod`, `go.sum` | `GO_MALICIOUS_MODULE` | bundle + catalog | GitHub Advisory Database, OpenSSF / OSV |
760
760
  | Maven / Gradle / SBT / Bazel | `pom.xml`, `gradle.lockfile`, `build.gradle`, `build.gradle.kts`, `libs.versions.toml`, `build.sbt`, `maven_install.json` | `MAVEN_MALICIOUS_PACKAGE` | bundle + catalog | GitHub Advisory Database, OpenSSF / OSV |
761
761
  | Dart / Flutter (pub) | `pubspec.lock`, `pubspec.yaml` | `PUB_MALICIOUS_PACKAGE` | bundle | GitHub Advisory Database, OSV |
762
762
  | Swift Package Manager | `Package.resolved`, `Package.swift` | `SWIFT_MALICIOUS_PACKAGE` | none yet (matcher ready) | GitHub Advisory Database, OSV (SwiftURL) |
@@ -801,7 +801,7 @@ There is one axis where it goes somewhere the others do not go at all. Credentia
801
801
 
802
802
  | Tool | Focus | Malware / behavior detection | Known-CVE lookup | Ecosystems | Open source | Account needed |
803
803
  |---|---|---|---|---|---|---|
804
- | **supply-chain-guard** | Malware campaigns, IOCs, behavior heuristics in installed artifacts; SBOM + SLSA provenance grading (in-toto/DSSE structural validation) | Yes: 350+ static heuristics plus multi-source GHSA/OpenSSF package verdicts and campaign-IOC matching, local at scan time (recent and curated indicators offline, the historical package catalog after a `feed refresh`) | No | 15 ecosystems of packages, extensions, plugins, providers, images and CI actions with shipped indicators, and tested matchers for more (see [Ecosystem Coverage](#ecosystem-coverage)), plus GitHub repos | Yes (Apache-2.0) | No |
804
+ | **supply-chain-guard** | Malware campaigns, IOCs, behavior heuristics in installed artifacts; SBOM + SLSA provenance grading (in-toto/DSSE structural validation) | Yes: 350+ static heuristics plus multi-source GHSA/OpenSSF/DataDog package verdicts and campaign-IOC matching, local at scan time (recent and curated indicators offline, the historical package catalog after a `feed refresh`) | No | 15 ecosystems of packages, extensions, plugins, providers, images and CI actions with shipped indicators, and tested matchers for more (see [Ecosystem Coverage](#ecosystem-coverage)), plus GitHub repos | Yes (Apache-2.0) | No |
805
805
  | [OSV-Scanner](https://github.com/google/osv-scanner) | Known vulnerabilities in dependency inventories (OSV.dev database lookup) | Known-malicious versions via OSV MAL- entries only; no behavior or IOC analysis | Yes (offline mode available) | 11+ ecosystems, 19+ lockfile formats, container images, SBOM input | Yes (Apache-2.0) | No |
806
806
  | [Socket](https://socket.dev) | Proactive behavioral analysis of entire registries (SaaS) | Yes: 70+ risk types registry-wide, before advisories exist; engine is closed source and cloud-side | Yes | npm, PyPI, Maven, Go, Cargo, RubyGems, NuGet, more; Actions workflows | CLI only (MIT); detection engine proprietary | Yes (except Firewall Free) |
807
807
  | [GuardDog](https://github.com/DataDog/guarddog) | Heuristic 0-10 risk scoring of individual packages (YARA + registry metadata) | Yes: heuristics only, no known-malware or campaign-IOC database; sandboxed scanning | No | npm, PyPI, Go, RubyGems, GitHub Actions, VS Code extensions | Yes (Apache-2.0) | No |
@@ -1001,7 +1001,7 @@ jobs:
1001
1001
  runs-on: ubuntu-latest
1002
1002
  steps:
1003
1003
  - uses: actions/checkout@v4
1004
- - uses: homeofe/supply-chain-guard@v6.4.3
1004
+ - uses: homeofe/supply-chain-guard@v6.5.0
1005
1005
  with:
1006
1006
  fail-on: critical
1007
1007
  comment-on-pr: true
@@ -1089,7 +1089,7 @@ two are never confused. If a deliberately frozen rule set is the intent, exclude
1089
1089
  the rule by name:
1090
1090
 
1091
1091
  ```yaml
1092
- - uses: homeofe/supply-chain-guard@v6.4.3
1092
+ - uses: homeofe/supply-chain-guard@v6.5.0
1093
1093
  with:
1094
1094
  exclude-rules: THREAT_FEED_STALE
1095
1095
  ```
@@ -1192,7 +1192,7 @@ preceding `feed refresh` in the workflow does not count. `catalog: required`
1192
1192
  on the Action therefore needs:
1193
1193
 
1194
1194
  ```yaml
1195
- - uses: homeofe/supply-chain-guard@v6.4.3
1195
+ - uses: homeofe/supply-chain-guard@v6.5.0
1196
1196
  with:
1197
1197
  refresh-catalog: true
1198
1198
  ```
@@ -1203,7 +1203,7 @@ setting rather than firing on every scan. If scanning against the bundled set
1203
1203
  alone is the intent, exclude the rule by name:
1204
1204
 
1205
1205
  ```yaml
1206
- - uses: homeofe/supply-chain-guard@v6.4.3
1206
+ - uses: homeofe/supply-chain-guard@v6.5.0
1207
1207
  with:
1208
1208
  exclude-rules: THREAT_FEED_CATALOG_MISSING
1209
1209
  ```
@@ -1362,8 +1362,8 @@ command exits non-zero, and the previous cache stays in effect.
1362
1362
  ### Where the feed comes from
1363
1363
 
1364
1364
  Curated entries are hand-added from vendor write-ups. Malicious-package entries
1365
- are additionally discovered through two public upstream paths, with no account
1366
- and no API key:
1365
+ are additionally discovered through three public upstream sources, with no
1366
+ account and no API key:
1367
1367
 
1368
1368
  - **[GitHub Advisory Database](https://github.com/advisories?query=type%3Amalware)** - malware
1369
1369
  advisories (CWE-506), one discovery source. Licensed
@@ -1374,6 +1374,13 @@ and no API key:
1374
1374
  records aggregate origins including ecosystem analysis services and security
1375
1375
  vendors, while retaining the original providers in every imported entry.
1376
1376
  Licensed Apache-2.0.
1377
+ - **[DataDog malicious-software-packages-dataset](https://github.com/DataDog/malicious-software-packages-dataset)** -
1378
+ npm and PyPI packages DataDog confirmed as malicious, read in full on every
1379
+ run. Only versions the dataset holds a malware sample for are pinned; a
1380
+ whole-package verdict becomes a name block only when the registry has
1381
+ already removed the package and no other source limits that name to
1382
+ specific versions. Licensed Apache-2.0; every imported entry carries
1383
+ `datadog-malicious-packages` in its `source` field.
1377
1384
 
1378
1385
  OSV querybatch separately corroborates GitHub-discovered packages. It is never
1379
1386
  used to corroborate an OpenSSF-discovered package against the same database.
package/action.yml CHANGED
@@ -99,7 +99,7 @@ runs:
99
99
  - name: Install supply-chain-guard
100
100
  shell: bash
101
101
  env:
102
- SCG_VERSION: "6.4.3"
102
+ SCG_VERSION: "6.5.0"
103
103
  SCG_EXPECTED_REPOSITORY: "homeofe/supply-chain-guard"
104
104
  SCG_EXPECTED_REPOSITORY_ID: "1185867580"
105
105
  SCG_EXPECTED_WORKFLOW: ".github/workflows/ci.yml"
@@ -1,8 +1,8 @@
1
1
  export declare const CATALOG_DIGEST: {
2
- readonly version: "6.4.3";
3
- readonly sha256: "adf29af6e41628a4ff49c37ffa9024510ebf0d6f012143e3047fb19a2d734544";
4
- readonly entriesSha256: "e0633c45006564ca06ee62d292c3adc508806f97b48055cc1e00f46e6a34a4e1";
5
- readonly entryCount: 92902;
6
- readonly shardCount: 2;
2
+ readonly version: "6.5.0";
3
+ readonly sha256: "fcb3ab88062edc07fe3f096f735bfe8432e71b79d8f964a53c7447f7dd3f30a1";
4
+ readonly entriesSha256: "0c2103fb6dee6d717eb008aa0edd54ee4232a1d9e53fbee765e76467709b009f";
5
+ readonly entryCount: 263681;
6
+ readonly shardCount: 6;
7
7
  };
8
8
  //# sourceMappingURL=catalog-digest.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"catalog-digest.d.ts","sourceRoot":"","sources":["../src/catalog-digest.ts"],"names":[],"mappings":"AAYA,eAAO,MAAM,cAAc;aACzB,OAAO,EAAE,OAAO;aAChB,MAAM,EAAE,kEAAkE;aAC1E,aAAa,EAAE,kEAAkE;aACjF,UAAU,EAAE,KAAK;aACjB,UAAU,EAAE,CAAC;CACL,CAAC"}
1
+ {"version":3,"file":"catalog-digest.d.ts","sourceRoot":"","sources":["../src/catalog-digest.ts"],"names":[],"mappings":"AAYA,eAAO,MAAM,cAAc;aACzB,OAAO,EAAE,OAAO;aAChB,MAAM,EAAE,kEAAkE;aAC1E,aAAa,EAAE,kEAAkE;aACjF,UAAU,EAAE,MAAM;aAClB,UAAU,EAAE,CAAC;CACL,CAAC"}
@@ -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.4.3",
18
- sha256: "adf29af6e41628a4ff49c37ffa9024510ebf0d6f012143e3047fb19a2d734544",
19
- entriesSha256: "e0633c45006564ca06ee62d292c3adc508806f97b48055cc1e00f46e6a34a4e1",
20
- entryCount: 92902,
21
- shardCount: 2,
17
+ version: "6.5.0",
18
+ sha256: "fcb3ab88062edc07fe3f096f735bfe8432e71b79d8f964a53c7447f7dd3f30a1",
19
+ entriesSha256: "0c2103fb6dee6d717eb008aa0edd54ee4232a1d9e53fbee765e76467709b009f",
20
+ entryCount: 263681,
21
+ shardCount: 6,
22
22
  };
23
23
  //# sourceMappingURL=catalog-digest.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"catalog-digest.js","sourceRoot":"","sources":["../src/catalog-digest.ts"],"names":[],"mappings":";;;AAAA,kEAAkE;AAClE,EAAE;AACF,0EAA0E;AAC1E,2EAA2E;AAC3E,4EAA4E;AAC5E,0EAA0E;AAC1E,4EAA4E;AAC5E,6EAA6E;AAC7E,EAAE;AACF,6EAA6E;AAC7E,0EAA0E;AAC1E,wDAAwD;AAC3C,QAAA,cAAc,GAAG;IAC5B,OAAO,EAAE,OAAO;IAChB,MAAM,EAAE,kEAAkE;IAC1E,aAAa,EAAE,kEAAkE;IACjF,UAAU,EAAE,KAAK;IACjB,UAAU,EAAE,CAAC;CACL,CAAC"}
1
+ {"version":3,"file":"catalog-digest.js","sourceRoot":"","sources":["../src/catalog-digest.ts"],"names":[],"mappings":";;;AAAA,kEAAkE;AAClE,EAAE;AACF,0EAA0E;AAC1E,2EAA2E;AAC3E,4EAA4E;AAC5E,0EAA0E;AAC1E,4EAA4E;AAC5E,6EAA6E;AAC7E,EAAE;AACF,6EAA6E;AAC7E,0EAA0E;AAC1E,wDAAwD;AAC3C,QAAA,cAAc,GAAG;IAC5B,OAAO,EAAE,OAAO;IAChB,MAAM,EAAE,kEAAkE;IAC1E,aAAa,EAAE,kEAAkE;IACjF,UAAU,EAAE,MAAM;IAClB,UAAU,EAAE,CAAC;CACL,CAAC"}
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.4.3");
201
+ .version("6.5.0");
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.4.3";
56
+ const TOOL_VERSION = "6.5.0";
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";
@@ -66,7 +66,7 @@ const threat_intel_js_1 = require("./threat-intel.js");
66
66
  const install_guard_js_1 = require("./install-guard.js");
67
67
  const json_utils_js_1 = require("./json-utils.js");
68
68
  const remote_download_js_1 = require("./remote-download.js");
69
- const TOOL_VERSION = "6.4.3";
69
+ const TOOL_VERSION = "6.5.0";
70
70
  const NPM_REGISTRY = "https://registry.npmjs.org";
71
71
  const NPM_REGISTRY_HOST = "registry.npmjs.org";
72
72
  const RAW_GITHUB_HOST = "raw.githubusercontent.com";
@@ -56,7 +56,7 @@ const patterns_js_1 = require("./patterns.js");
56
56
  const pattern_scanner_js_1 = require("./pattern-scanner.js");
57
57
  const extracted_file_walker_js_1 = require("./extracted-file-walker.js");
58
58
  const remote_download_js_1 = require("./remote-download.js");
59
- const TOOL_VERSION = "6.4.3";
59
+ const TOOL_VERSION = "6.5.0";
60
60
  const PYPI_API = "https://pypi.org/pypi";
61
61
  const PYPI_METADATA_HOST = "pypi.org";
62
62
  const PYPI_ARTIFACT_HOST = "files.pythonhosted.org";
package/dist/reporter.js CHANGED
@@ -294,7 +294,7 @@ function formatJson(report) {
294
294
  function formatText(report, options = {}) {
295
295
  const lines = [];
296
296
  // ── layout constants ───────────────────────────────────────────────────────
297
- const VERSION = "6.4.3";
297
+ const VERSION = "6.5.0";
298
298
  const W = 76; // visible chars between "│ " and " │" (total line = 80)
299
299
  // ── ANSI helpers ───────────────────────────────────────────────────────────
300
300
  const stripAnsi = (s) => s.replace(/\x1b\[[0-9;]*m/g, "");
@@ -739,7 +739,7 @@ function formatMarkdown(report) {
739
739
  lines.push("");
740
740
  lines.push(`| Property | Value |`);
741
741
  lines.push(`|----------|-------|`);
742
- lines.push(`| Tool | \`${mdCell(report.tool || "supply-chain-guard v6.4.3")}\` |`);
742
+ lines.push(`| Tool | \`${mdCell(report.tool || "supply-chain-guard v6.5.0")}\` |`);
743
743
  lines.push(`| Target | \`${mdCell(report.target)}\` |`);
744
744
  lines.push(`| Type | ${mdText(report.scanType)} |`);
745
745
  lines.push(`| Time | ${mdText(report.timestamp)} |`);
@@ -993,7 +993,7 @@ function formatSarif(report) {
993
993
  tool: {
994
994
  driver: {
995
995
  name: "supply-chain-guard",
996
- version: "6.4.3",
996
+ version: "6.5.0",
997
997
  informationUri: "https://github.com/homeofe/supply-chain-guard",
998
998
  rules,
999
999
  },
@@ -1217,7 +1217,7 @@ function formatSbom(report) {
1217
1217
  ...(properties.length > 0 ? { properties } : {}),
1218
1218
  }];
1219
1219
  });
1220
- const annotations = buildIncidentAnnotations(report.incidents, subjectsByIncident, metadata.timestamp, metadata.tools.components[0]?.version ?? "6.4.3");
1220
+ const annotations = buildIncidentAnnotations(report.incidents, subjectsByIncident, metadata.timestamp, metadata.tools.components[0]?.version ?? "6.5.0");
1221
1221
  const withVulns = {
1222
1222
  ...document,
1223
1223
  metadata: {
@@ -1266,7 +1266,7 @@ function formatSbom(report) {
1266
1266
  ...(properties.length > 0 ? { properties } : {}),
1267
1267
  };
1268
1268
  });
1269
- const fallbackAnnotations = buildIncidentAnnotations(report.incidents, fallbackSubjectsByIncident, report.timestamp, "6.4.3");
1269
+ const fallbackAnnotations = buildIncidentAnnotations(report.incidents, fallbackSubjectsByIncident, report.timestamp, "6.5.0");
1270
1270
  const sbom = {
1271
1271
  bomFormat: "CycloneDX",
1272
1272
  specVersion: "1.6",
@@ -1276,7 +1276,7 @@ function formatSbom(report) {
1276
1276
  timestamp: report.timestamp,
1277
1277
  tools: {
1278
1278
  components: [
1279
- { type: "application", name: "supply-chain-guard", version: "6.4.3" },
1279
+ { type: "application", name: "supply-chain-guard", version: "6.5.0" },
1280
1280
  ],
1281
1281
  },
1282
1282
  component: {
@@ -1352,8 +1352,8 @@ function formatBadge(report) {
1352
1352
  label: "supply-chain-guard",
1353
1353
  message,
1354
1354
  color,
1355
- tool: report.tool || "supply-chain-guard v6.4.3",
1356
- version: report.tool ? (report.tool.includes("@") ? report.tool.split("@")[1] : report.tool.replace(/^supply-chain-guard v?/, "")) : "6.4.3",
1355
+ tool: report.tool || "supply-chain-guard v6.5.0",
1356
+ version: report.tool ? (report.tool.includes("@") ? report.tool.split("@")[1] : report.tool.replace(/^supply-chain-guard v?/, "")) : "6.5.0",
1357
1357
  timestamp: report.timestamp,
1358
1358
  commit: report.commit ?? "none",
1359
1359
  detectionSet: report.detectionSet,
@@ -1409,7 +1409,7 @@ function formatGitlab(report) {
1409
1409
  name: "supply-chain-guard",
1410
1410
  url: "https://github.com/homeofe/supply-chain-guard",
1411
1411
  vendor: { name: "supply-chain-guard" },
1412
- version: "6.4.3",
1412
+ version: "6.5.0",
1413
1413
  };
1414
1414
  const vulnerabilities = report.findings
1415
1415
  .filter((f) => !f.suppressed)
@@ -1534,7 +1534,7 @@ function formatJunit(report) {
1534
1534
  // (unreleased, issue 205): the coverage properties are ALWAYS emitted, so a JUnit
1535
1535
  // artefact states its own denominator instead of only what was found.
1536
1536
  lines.push(" <properties>");
1537
- lines.push(` <property name="supply-chain-guard:tool-version" value="${xmlEscape(report.tool || "supply-chain-guard v6.4.3")}"/>`);
1537
+ lines.push(` <property name="supply-chain-guard:tool-version" value="${xmlEscape(report.tool || "supply-chain-guard v6.5.0")}"/>`);
1538
1538
  lines.push(` <property name="supply-chain-guard:timestamp" value="${xmlEscape(report.timestamp)}"/>`);
1539
1539
  lines.push(` <property name="supply-chain-guard:commit" value="${xmlEscape(report.commit ?? "none (not a git repository)")}"/>`);
1540
1540
  if (report.detectionSet) {
@@ -1664,7 +1664,7 @@ footer{text-align:center;padding:24px;color:#94a3b8;font-size:13px}
1664
1664
  <body>
1665
1665
  <div class="container">
1666
1666
  <header>
1667
- <h1>${escapeHtml(report.tool || "supply-chain-guard v6.4.3")} Scan Report</h1>
1667
+ <h1>${escapeHtml(report.tool || "supply-chain-guard v6.5.0")} Scan Report</h1>
1668
1668
  <div class="meta">
1669
1669
  <span>Target: ${escapeHtml(report.target)}</span>
1670
1670
  <span>Type: ${report.scanType}</span>
@@ -1726,7 +1726,7 @@ footer{text-align:center;padding:24px;color:#94a3b8;font-size:13px}
1726
1726
  ` : ""}
1727
1727
 
1728
1728
  <footer>
1729
- Generated by <a href="https://github.com/homeofe/supply-chain-guard">${escapeHtml(report.tool || "supply-chain-guard v6.4.3")}</a>
1729
+ Generated by <a href="https://github.com/homeofe/supply-chain-guard">${escapeHtml(report.tool || "supply-chain-guard v6.5.0")}</a>
1730
1730
  </footer>
1731
1731
  </div>
1732
1732
  <script>
@@ -87,7 +87,7 @@ const fs = __importStar(require("node:fs"));
87
87
  const path = __importStar(require("node:path"));
88
88
  const node_crypto_1 = require("node:crypto");
89
89
  const json_utils_js_1 = require("./json-utils.js");
90
- const TOOL_VERSION = "6.4.3";
90
+ const TOOL_VERSION = "6.5.0";
91
91
  /** bom-ref of the component the document is about. */
92
92
  const SUBJECT_BOM_REF = "target";
93
93
  /** Property namespace, matching the `supply-chain-guard:scan-status` property reporter.ts adds. */
package/dist/scanner.js CHANGED
@@ -114,7 +114,7 @@ const mcp_scanner_js_1 = require("./mcp-scanner.js");
114
114
  const skills_scanner_js_1 = require("./skills-scanner.js");
115
115
  const disguised_asset_js_1 = require("./disguised-asset.js");
116
116
  const self_scan_trust_js_1 = require("./self-scan-trust.js");
117
- const TOOL_VERSION = "6.4.3";
117
+ const TOOL_VERSION = "6.5.0";
118
118
  /**
119
119
  * Pattern literals in this matcher module deliberately spell out signatures
120
120
  * that the public scanner detects. Suppress only those exact rule definitions
@@ -24,7 +24,7 @@ export type FeedIOCInput = Omit<FeedIOC, "confidence"> & {
24
24
  * Generation timestamp for the bundled IOC feed (v5.29, issue #208).
25
25
  * Pure function of feed updates; preserved across builds.
26
26
  */
27
- export declare const FEED_GENERATED_AT = "2026-10-04T00:00:00.000Z";
27
+ export declare const FEED_GENERATED_AT = "2026-10-05T00:00:00.000Z";
28
28
  export declare const CACHE_DIR = ".scg-cache";
29
29
  export declare const FEED_CACHE_FILE = "threat-feed.json";
30
30
  /** Where the downloaded catalog is cached, beside the feed cache. */
@@ -208,15 +208,16 @@ export declare function updateThreatFeed(feedUrl: string, cacheDir?: string, lim
208
208
  * deviation -> file is scanned like everything else.
209
209
  */
210
210
  export declare function isInertThreatFeedFile(filename: string, content: string): boolean;
211
- /** Basename of the committed catalog store. */
212
- export declare const CATALOG_FILE = "threat-catalog.jsonl";
211
+ /** Directory of the committed catalog store (scripts/catalog-store.mjs). */
212
+ export declare const CATALOG_DIR = "data/threat-catalog";
213
213
  /**
214
- * Exact repository-relative path of the catalog store. The exemption is bound
215
- * to this path, not merely to the basename: a basename match would let ANY
216
- * scanned repository place a file with this name at any depth and have it
217
- * skipped, which is an evasion primitive rather than a convenience.
214
+ * Exact repository-relative shape of one catalog part. The exemption is bound
215
+ * to this anchored path, not merely to a basename: a basename match would let
216
+ * ANY scanned repository place a file with this name at any depth and have it
217
+ * skipped, which is an evasion primitive rather than a convenience. The store
218
+ * was one file, data/threat-catalog.jsonl, until it grew past 40 MB.
218
219
  */
219
- export declare const CATALOG_RELATIVE_PATH = "data/threat-catalog.jsonl";
220
+ export declare const CATALOG_PART_PATH: RegExp;
220
221
  /**
221
222
  * Structural check: is this file supply-chain-guard's own catalog store?
222
223
  *
@@ -1 +1 @@
1
- {"version":3,"file":"threat-intel.d.ts","sourceRoot":"","sources":["../src/threat-intel.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"threat-intel.d.ts","sourceRoot":"","sources":["../src/threat-intel.ts"],"names":[],"mappings":"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"}