@blamejs/exceptd-skills 0.15.50 → 0.15.51

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.
@@ -544,7 +544,8 @@
544
544
  "opened_date": "2026-05-13",
545
545
  "evidence_cves": [
546
546
  "CVE-2026-45321",
547
- "MAL-2026-SHAI-HULUD-OSS"
547
+ "MAL-2026-SHAI-HULUD-OSS",
548
+ "MAL-2026-TRAPDOOR-CROSS-ECOSYSTEM"
548
549
  ],
549
550
  "atlas_refs": [
550
551
  "AML.T0010",
@@ -907,7 +908,9 @@
907
908
  "MAL-2026-3083",
908
909
  "MAL-2026-NODE-IPC-STEALER",
909
910
  "MAL-2026-SHAI-HULUD-OSS",
910
- "MAL-2026-TANSTACK-MINI"
911
+ "MAL-2026-TANSTACK-MINI",
912
+ "CVE-2022-23812",
913
+ "MAL-2026-MOIKA-DEPCONFUSION"
911
914
  ],
912
915
  "atlas_refs": [
913
916
  "AML.T0010",
@@ -2057,7 +2060,9 @@
2057
2060
  "evidence_cves": [
2058
2061
  "CVE-2026-45321",
2059
2062
  "MAL-2026-3083",
2060
- "MAL-2026-NODE-IPC-STEALER"
2063
+ "MAL-2026-NODE-IPC-STEALER",
2064
+ "CVE-2022-23812",
2065
+ "MAL-2026-MOIKA-DEPCONFUSION"
2061
2066
  ],
2062
2067
  "atlas_refs": [
2063
2068
  "AML.T0010",
@@ -2098,7 +2103,8 @@
2098
2103
  "CVE-2025-30154",
2099
2104
  "CVE-2026-48027",
2100
2105
  "MAL-2026-SHAI-HULUD-OSS",
2101
- "MAL-2026-TANSTACK-MINI"
2106
+ "MAL-2026-TANSTACK-MINI",
2107
+ "MAL-2026-TRAPDOOR-CROSS-ECOSYSTEM"
2102
2108
  ],
2103
2109
  "atlas_refs": [
2104
2110
  "AML.T0010"
@@ -3668,7 +3674,8 @@
3668
3674
  "CVE-2026-45321",
3669
3675
  "MAL-2026-3083",
3670
3676
  "MAL-2026-NODE-IPC-STEALER",
3671
- "MAL-2026-SHAI-HULUD-OSS"
3677
+ "MAL-2026-SHAI-HULUD-OSS",
3678
+ "MAL-2026-MOIKA-DEPCONFUSION"
3672
3679
  ],
3673
3680
  "atlas_refs": [
3674
3681
  "AML.T0010",
@@ -5900,7 +5907,10 @@
5900
5907
  "CVE-2026-46333",
5901
5908
  "CVE-2026-5760",
5902
5909
  "CVE-2026-9082",
5903
- "MAL-2026-SHAI-HULUD-OSS"
5910
+ "MAL-2026-SHAI-HULUD-OSS",
5911
+ "CVE-2022-23812",
5912
+ "MAL-2026-TRAPDOOR-CROSS-ECOSYSTEM",
5913
+ "MAL-2026-MOIKA-DEPCONFUSION"
5904
5914
  ],
5905
5915
  "atlas_refs": [],
5906
5916
  "attack_refs": [
@@ -6116,7 +6126,10 @@
6116
6126
  "MAL-2026-NODE-IPC-STEALER",
6117
6127
  "MAL-2026-RUBYGEMS-BUFFERZONECORP-SLEEPER",
6118
6128
  "MAL-2026-SHAI-HULUD-OSS",
6119
- "MAL-2026-TANSTACK-MINI"
6129
+ "MAL-2026-TANSTACK-MINI",
6130
+ "CVE-2022-23812",
6131
+ "MAL-2026-TRAPDOOR-CROSS-ECOSYSTEM",
6132
+ "MAL-2026-MOIKA-DEPCONFUSION"
6120
6133
  ],
6121
6134
  "atlas_refs": [
6122
6135
  "AML.T0010",
@@ -6707,7 +6720,9 @@
6707
6720
  "CVE-2025-68665",
6708
6721
  "CVE-2025-6965",
6709
6722
  "CVE-2026-22778",
6710
- "MAL-2025-AI-FOUND-FFMPEG-BIGSLEEP"
6723
+ "MAL-2025-AI-FOUND-FFMPEG-BIGSLEEP",
6724
+ "MAL-2026-TRAPDOOR-CROSS-ECOSYSTEM",
6725
+ "MAL-2026-MOIKA-DEPCONFUSION"
6711
6726
  ],
6712
6727
  "theater_test": {
6713
6728
  "claim": "We are compliant with Art-15 (Accuracy, robustness, and cybersecurity of high-risk AI systems) because we follow the documented requirement: Article 15 — high-risk AI systems must be designed and developed so as to achieve an appropriate level of accuracy, robustness, and cybersecurity throughout their lifecycle. Anchored on the assumption",
@@ -7519,7 +7534,10 @@
7519
7534
  "opened_at": "2026-05-18",
7520
7535
  "evidence_cves": [
7521
7536
  "MAL-2025-PYPI-COLORAMA-SOLANA-STEALER",
7522
- "MAL-2026-RUBYGEMS-BUFFERZONECORP-SLEEPER"
7537
+ "MAL-2026-RUBYGEMS-BUFFERZONECORP-SLEEPER",
7538
+ "MAL-2026-MOIKA-DEPCONFUSION",
7539
+ "CVE-2022-23812",
7540
+ "MAL-2026-TRAPDOOR-CROSS-ECOSYSTEM"
7523
7541
  ],
7524
7542
  "theater_test": {
7525
7543
  "claim": "We are compliant with A.5.21 (Managing information security in the ICT supply chain) because we follow the documented requirement: Annex A.5.21 — processes and procedures to manage information security risks associated with the ICT supply chain. Anchored on initial vendor / supplier assessment, contractual security clauses, and o",
@@ -8052,7 +8070,8 @@
8052
8070
  "opened_date": "2026-05-28",
8053
8071
  "evidence_cves": [
8054
8072
  "CVE-2025-30066",
8055
- "CVE-2026-48027"
8073
+ "CVE-2026-48027",
8074
+ "MAL-2026-MOIKA-DEPCONFUSION"
8056
8075
  ],
8057
8076
  "atlas_refs": [
8058
8077
  "AML.T0010"
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "_meta": {
3
3
  "id": "sbom",
4
- "version": "1.2.0",
4
+ "version": "1.3.0",
5
5
  "last_threat_review": "2026-05-13",
6
6
  "threat_currency_score": 96,
7
7
  "changelog": [
@@ -43,6 +43,16 @@
43
43
  "nis2-art21-2d",
44
44
  "dora-art28"
45
45
  ]
46
+ },
47
+ {
48
+ "version": "1.2.1",
49
+ "date": "2026-05-30",
50
+ "summary": "Add capability-creep behavioral detector: flags a dependency that gains network / filesystem-write / shell-spawn / credential-access / install-script capability across a version bump (pre-disclosure supply-chain signal), with five false-positive checks and a matching false-positive profile."
51
+ },
52
+ {
53
+ "version": "1.3.0",
54
+ "date": "2026-05-30",
55
+ "summary": "Add a package-capability taxonomy (network / filesystem / shell / env / eval / install-script / telemetry / native-binary): a package-capability-surface evidence artifact plus an absolute capability-surface screen that flags a no-CVE package whose install-script combines with shell/network/env/eval (the credential-harvesting delivery shape), complementing the across-version-bump capability-creep detector."
46
56
  }
47
57
  ],
48
58
  "owner": "@blamejs/supply-chain",
@@ -602,6 +612,13 @@
602
612
  "source": "Read .github/workflows/*.yml and *.yaml — extract `on:` triggers, `permissions:`, and `uses: actions/cache@*` step references",
603
613
  "description": "CVE-2026-45321 architectural pre-condition check — detects pull_request_target + id-token:write + shared actions/cache co-residency in the same repo.",
604
614
  "required": false
615
+ },
616
+ {
617
+ "id": "package-capability-surface",
618
+ "type": "config_file",
619
+ "source": "For each installed/locked npm + PyPI package, read its manifest to enumerate declared/observable capabilities: package.json scripts (preinstall/install/postinstall), bin, gypfile/binding.gyp (native-binary build), and dependencies on known network/child-process modules; PyPI setup.py/pyproject.toml build hooks + .so/.pyd payloads. Classify each package into the capability vocabulary: network, filesystem, shell, env, eval, install-script, telemetry, native-binary.",
620
+ "description": "Package-capability surface per dependency, using a capability taxonomy (network / filesystem / shell / env / eval / install-script / telemetry / native-binary). Complements the CVE-match register: a package with no catalogued CVE can still carry an outsized capability surface (an install-script that spawns a shell and reads env is the Shai-Hulud delivery shape). Capability is a property of the package, independent of any known vulnerability.",
621
+ "required": false
605
622
  }
606
623
  ],
607
624
  "collection_scope": {
@@ -800,6 +817,38 @@
800
817
  "description": "Mitigation gap for CVE-2026-45321 and similar fresh-publish worms. Without a registry cooldown, `npm install` will accept a version published seconds ago. Recommended: `before=72h` (npm 11+) or `minimumReleaseAge=4320` minutes. The worm was caught publicly within 20 minutes; 72h is overkill-safe.",
801
818
  "confidence": "high",
802
819
  "deterministic": false
820
+ },
821
+ {
822
+ "id": "dependency-capability-creep-across-version-bump",
823
+ "type": "behavioral_signal",
824
+ "value": "For any dependency present in repo-lockfiles, npm-global-packages, or container-image-layers whose resolved version advanced since the last recorded inventory (or across two lockfile revisions in scope), compare the package's capability surface between the two versions. CAPABILITY SURFACE = (a) network egress (new fetch/http/https/net/dgram/ws imports or new outbound hosts), (b) filesystem write beyond the package's own dir, (c) process/shell spawn (child_process/exec/spawn, os/system, subprocess, Runtime.exec), (d) environment / credential access (process.env enumeration, reads of ~/.aws ~/.ssh ~/.npmrc ~/.kube ~/.config, keychain/secrets API), (e) install-lifecycle scripts newly present or newly non-trivial (preinstall/install/postinstall, setup.py/cfg build hooks, gem extensions, Cargo build.rs). FIRES when a version bump GAINS one or more capability categories the prior in-scope version did not exercise — a capability the dependent never opted into when it first selected the package.",
825
+ "description": "Capability-creep — a dependency that suddenly gains network / filesystem-write / shell-spawn / credential-access / install-script capability across a version bump. Models the core behavioral supply-chain signal: most maintainer-account takeovers and protestware injections surface first as a new capability class in an otherwise-unchanged package, before any CVE is catalogued. Pre-disclosure detector — fires on behavior delta, not on a known-CVE match.",
826
+ "confidence": "medium",
827
+ "deterministic": false,
828
+ "attack_ref": "T1195.001",
829
+ "atlas_ref": "AML.T0010",
830
+ "false_positive_checks_required": [
831
+ "Confirm the new capability is not explained by a documented feature in the version's release notes / CHANGELOG that the dependent intentionally upgraded to consume (e.g. a logging library that added an opt-in OTLP-over-HTTP exporter). A capability gain matching a documented, in-changelog feature the operator pulled deliberately is benign — demote to inconclusive and record the changelog citation.",
832
+ "Distinguish a genuine capability gain from a refactor that merely RELOCATED an existing capability (the prior version already spawned a child process via a transitive dep; the new version inlines it). Diff the EFFECTIVE capability of the prior resolved tree (package + its own deps), not the single package file — relocation across the package boundary is not a gain. Demote when the capability was already present transitively.",
833
+ "Exclude build-time / dev-time-only dependencies whose new capability never reaches a runtime-loaded path (e.g. a test runner gaining child_process). Confirm runtime reachability before elevating; build/dev-only capability gain demotes to low.",
834
+ "Rule out the package's own first-party major-version migration where the maintainer key, publish provenance (SLSA / npm --provenance), and signing identity are UNCHANGED across the bump and the version follows the project's normal release cadence (not a sub-72h fresh publish). Unchanged provenance + normal cadence + documented breaking-change major demotes; an unchanged-version-string-but-changed-content republish, a new/rotated maintainer key, or a provenance attestation that regressed from present-to-absent ELEVATES (re-publication-over / account-takeover signature).",
835
+ "For install-lifecycle scripts: confirm the script is newly present OR newly non-trivial versus the prior version — many packages have always shipped a postinstall (e.g. native-addon compile via node-gyp). A long-standing, content-stable lifecycle script is not creep; only a newly-added or newly-mutated one fires."
836
+ ]
837
+ },
838
+ {
839
+ "id": "package-capability-creep",
840
+ "type": "config_value",
841
+ "value": "Within the package-capability-surface artifact: any direct or transitive package combines an install-time hook (install-script: preinstall/install/postinstall, or PyPI build hook) with at least one high-trust capability (shell, network, env, or eval). Capability vocabulary: network / filesystem / shell / env / eval / install-script / telemetry / native-binary. The install-script+shell+network+env quadruple is the credential-harvesting delivery shape (CVE-2026-45321 Mini Shai-Hulud, CVE-2024-3094 XZ class); install-script+native-binary is the compiled-payload shape.",
842
+ "description": "Capability-surface screen — flags packages whose capability surface is disproportionate to their declared function, independent of CVE match. A no-CVE package that runs an install-script which spawns a shell, opens the network, and reads env vars is the supply-chain delivery primitive even when the catalog shows zero matched CVEs. Surfaces alongside, not in place of, package-matches-catalogued-cve; absolute-surface complement to the across-version-bump capability-creep detector.",
843
+ "confidence": "medium",
844
+ "deterministic": false,
845
+ "attack_ref": "T1195.002",
846
+ "false_positive_checks_required": [
847
+ "Build-tooling and native-addon packages legitimately need install-script + native-binary (node-gyp, sass-embedded, esbuild, sharp, bcrypt, prebuild-install, electron, playwright, puppeteer). If the package is on the operator documented build-dependency allowlist AND its publisher identity / provenance attestation matches the expected one, demote — capability presence is expected for this class.",
848
+ "Confirm the install-script actually exercises the high-trust capability at install time, not merely that the package transitively depends on a network/shell module used only at runtime in an unrelated code path. Read the referenced script: a postinstall that only runs node-gyp rebuild is native-binary, not network+shell+env. Demote when the capability is declared-but-not-install-reachable.",
849
+ "Telemetry-only capability (a postinstall that pings an analytics endpoint with no env/credential read) is a noise/consent concern, not a credential-exfil primitive. Demote network+telemetry-without-env to informational unless env or filesystem-credential-path access co-occurs.",
850
+ "If the capability surface was read from a stale or non-build lockfile (archive/ or pre-migration/ subdir), it does not reflect what installs. Confirm against the build-consumed lockfile path before firing (same stale-lockfile check as lockfile-no-integrity)."
851
+ ]
803
852
  }
804
853
  ],
805
854
  "false_positive_profile": [
@@ -817,6 +866,16 @@
817
866
  "indicator_id": "ai-code-no-provenance",
818
867
  "benign_pattern": "Org has documented internal commit-trailer convention (Co-Authored-By:, Generated-By:, AI-Model:) but it isn't reflected in machine-readable SBOM.",
819
868
  "distinguishing_test": "Sample 20 commits in the repo. If commit-trailer convention is consistently used, downgrade to medium and recommend SBOM integration rather than flagging absence outright."
869
+ },
870
+ {
871
+ "indicator_id": "dependency-capability-creep-across-version-bump",
872
+ "benign_pattern": "A widely-used package legitimately adds a capability in a feature release — e.g. an HTTP client adds optional HTTP/2 (new net surface), an ORM adds a CLI migration runner (new child_process), a telemetry SDK adds an opt-in exporter (new egress host). The capability is documented, the maintainer key and publish provenance are unchanged, and the release follows normal cadence.",
873
+ "distinguishing_test": "Pull the version release notes / CHANGELOG and the npm/PyPI provenance attestation. Benign when ALL hold: (1) the new capability is documented as an intended feature, (2) the signing/maintainer identity is unchanged across the bump, (3) provenance present-before is still present, and (4) publish age exceeds the registry-cooldown threshold (not a sub-72h fresh publish). Malicious-leaning when ANY of: capability is undocumented, maintainer key rotated, provenance regressed from present-to-absent, content changed under an unchanged version string, or the gain is credential-path reads / outbound to a never-before-seen host."
874
+ },
875
+ {
876
+ "indicator_id": "package-capability-creep",
877
+ "benign_pattern": "Native-addon and build-tooling packages (node-gyp, sass-embedded, esbuild, sharp, bcrypt, prebuild-install, electron, playwright, puppeteer) legitimately carry install-script + native-binary + (sometimes) network capability — the prebuilt-binary download is network + install-script by design.",
878
+ "distinguishing_test": "Cross-reference the flagged package against the operator documented build-dependency allowlist and its npm/PyPI provenance attestation. If the package is a known build/native-addon dependency AND its publisher identity matches the expected signed publisher, downgrade to medium/informational. Reserve high confidence for packages whose capability surface is unexplained by their stated function (a date-formatting utility that opens the network and reads env)."
820
879
  }
821
880
  ],
822
881
  "minimum_signal": {
@@ -17,7 +17,7 @@
17
17
  "rebuild_after_days": 365,
18
18
  "note": "Per-entry last_verified governs decay. Skills depending on this catalog must check entry freshness before high-stakes use."
19
19
  },
20
- "entry_count": 427
20
+ "entry_count": 430
21
21
  },
22
22
  "CVE-2026-31431": {
23
23
  "name": "Copy Fail",
@@ -24854,5 +24854,255 @@
24854
24854
  "ai_discovered_zeroday": false,
24855
24855
  "ai_discovery_source": "vendor_research",
24856
24856
  "ai_assist_factor": "none"
24857
+ },
24858
+ "CVE-2022-23812": {
24859
+ "name": "node-ipc geo-targeted file-wiper protestware (RU/BY heart-emoji overwrite; peacenotwar dropper in 11.0.0+)",
24860
+ "lesson_date": "2026-05-30",
24861
+ "attack_vector": {
24862
+ "description": "A trusted, legitimate package maintainer (node-ipc, ~1M weekly downloads, transitive via Vue CLI) authored a destructive payload directly into published versions 10.1.1/10.1.2 (2022-03-07/08): on require('node-ipc') the code resolved the host's public-IP geolocation and, for Russia/Belarus, recursively overwrote writable files with a heart character; a follow-on bundled the peacenotwar dropper (WITH-LOVE-FROM-AMERICA.txt, NVD-scoped into 11.0.0+). The payload ships in the MAIN MODULE, not a postinstall hook, so --ignore-scripts — the canonical post-Shai-Hulud npm mitigation — does NOT mitigate. Class: insider-maintainer protestware/sabotage, distinct from account-recovery takeover (node-ipc 2026 stealer) and typosquat.",
24863
+ "privileges_required": "downstream consumer runs install resolving 10.1.1/10.1.2 (directly or transitively); payload fires automatically on require('node-ipc')",
24864
+ "complexity": "low for downstream consumers (automatic on module load); trivial for the maintainer (any owner with publish rights can author it)",
24865
+ "ai_factor": "Not AI-discovered, not AI-built. Hand-authored geo-gated wiper; the novelty is the trust-abuse + main-module delivery, not algorithmic."
24866
+ },
24867
+ "defense_chain": {
24868
+ "prevention": {
24869
+ "what_would_have_worked": "Strict-lockfile installs (npm ci) against a lockfile predating 2022-03-07; pinning critical-path dependencies and gating upgrades on a review window; treating high-reach single-maintainer packages as a concentration risk.",
24870
+ "was_this_required": false,
24871
+ "framework_requiring_it": null,
24872
+ "adequacy": "--ignore-scripts does NOT help (main-module payload). Lockfile pinning helps only if the lockfile predates the malicious publish AND npm ci (not npm install) is used."
24873
+ },
24874
+ "detection": {
24875
+ "what_would_have_worked": "Behavioral telemetry on developer/CI hosts: an outbound geolocation lookup followed by recursive filesystem writes within a Node process's lifetime is a near-deterministic IoC for a main-module wiper. File-write telemetry on broad path globs at module-load time catches the class even when --ignore-scripts is set.",
24876
+ "was_this_required": false,
24877
+ "framework_requiring_it": null,
24878
+ "adequacy": "Most endpoints and CI runners do not retain process-level file-write telemetry; the geo-gating means absence of harm on a non-RU/BY host does not prove the payload was absent."
24879
+ },
24880
+ "response": {
24881
+ "what_would_have_worked": "npm removed 10.1.1/10.1.2; consumers upgraded to 10.1.3+. For the 11.0.0+ peacenotwar range, pin to a pre-11.0.0 line or a maintained fork. Restore any overwritten files from backup on affected RU/BY hosts.",
24882
+ "was_this_required": false,
24883
+ "framework_requiring_it": null,
24884
+ "adequacy": "Yank closes new exposure but does not restore wiped files; the destructive action is irreversible without backups."
24885
+ }
24886
+ },
24887
+ "framework_coverage": {
24888
+ "NIST-800-218-SSDF": {
24889
+ "covered": true,
24890
+ "adequate": false,
24891
+ "gap": "Reused-component controls assume maintainer good-faith; no coverage of trusted-maintainer sabotage."
24892
+ },
24893
+ "EU-CRA-Art13": {
24894
+ "covered": true,
24895
+ "adequate": false,
24896
+ "gap": "SBOM records what resolved; a pinned malicious version is SBOM-compliant."
24897
+ },
24898
+ "NIS2-Art21-supply-chain": {
24899
+ "covered": true,
24900
+ "adequate": false,
24901
+ "gap": "No main-module-vs-postinstall payload distinction; no maintainer-intent risk."
24902
+ },
24903
+ "UK-CAF-B4-supply-chain": {
24904
+ "covered": true,
24905
+ "adequate": false,
24906
+ "gap": "Outcome-based principle does not prescribe insider-maintainer-sabotage defense."
24907
+ },
24908
+ "ANY-FRAMEWORK": {
24909
+ "covered": false,
24910
+ "adequate": false,
24911
+ "gap": "No major framework treats a trusted maintainer shipping a geo-targeted destructive main-module payload as a distinct supply-chain class. NEW-CTRL-114 is the headline novel control."
24912
+ }
24913
+ },
24914
+ "new_control_requirements": [
24915
+ {
24916
+ "id": "NEW-CTRL-114",
24917
+ "name": "MAIN-MODULE-PAYLOAD-DETECTION",
24918
+ "description": "Supply-chain controls must not assume --ignore-scripts mitigates malicious dependencies. A payload shipped in the package main module (executing on require/import, not via a lifecycle hook) bypasses --ignore-scripts entirely. Detect via process-level behavioral telemetry: geolocation/IP lookups, broad recursive filesystem writes, or credential-path reads occurring at module-load time within a dependency. Pair with strict-lockfile installs (npm ci) and a publish-to-consume review window on high-reach single-maintainer packages.",
24919
+ "evidence": "CVE-2022-23812 — node-ipc 10.1.1/10.1.2 shipped a geo-targeted file-wiper in the MAIN MODULE; --ignore-scripts (the canonical npm-supply-chain mitigation since Shai-Hulud) did not mitigate because the payload was not in a postinstall hook.",
24920
+ "gap_closes": [
24921
+ "NIST-800-218-SSDF",
24922
+ "NIS2-Art21-supply-chain",
24923
+ "EU-CRA-Art13",
24924
+ "ANY-FRAMEWORK"
24925
+ ]
24926
+ }
24927
+ ],
24928
+ "compliance_exposure_score": {
24929
+ "percent_audit_passing_orgs_still_exposed": 90,
24930
+ "basis": "Most npm-hygiene programs lean on --ignore-scripts and SBOM, neither of which addresses a main-module payload from a trusted maintainer. Lockfile pinning helps only with npm ci and a pre-2022-03-07 lockfile.",
24931
+ "theater_pattern": "ignore_scripts_assumed_sufficient_for_all_supply_chain_payloads"
24932
+ },
24933
+ "ai_discovered_zeroday": false,
24934
+ "ai_discovery_source": "human_researcher",
24935
+ "ai_discovery_date": "2022-03-15",
24936
+ "ai_assist_factor": "low"
24937
+ },
24938
+ "MAL-2026-TRAPDOOR-CROSS-ECOSYSTEM": {
24939
+ "name": "TrapDoor cross-ecosystem crypto-stealer + AI-assistant poisoning campaign (npm/PyPI/crates.io)",
24940
+ "lesson_date": "2026-05-30",
24941
+ "attack_vector": {
24942
+ "description": "Cross-ecosystem (npm/PyPI/crates.io) coordinated malicious-package campaign (\"TrapDoor\", anchor OSV MAL-2026-4207 / GHSA-7r6r-hqg7-f6mq) using lure packages themed as security/crypto/AI tooling. npm: postinstall executes trap-core.js. PyPI: import-time node -e pulls JS from attacker GitHub Pages. crates.io: build.rs runs at compile time. All variants harvest cloud/SSH/GitHub credentials + crypto-wallet data and exfiltrate via a dynamic GitHub-Pages C2. The genuinely novel vector: the payload plants .cursorrules and CLAUDE.md files containing zero-width-Unicode-hidden instructions designed to trick AI coding assistants (Cursor, Claude Code) into running a fake \"security scan\" that self-exfiltrates local secrets — AI-assistant prompt-injection as a supply-chain weaponization channel.",
24943
+ "privileges_required": "developer/CI runs install (npm postinstall), import (PyPI), or compile (crates build.rs); AI-assistant poisoning additionally fires when a developer opens the repo in an LLM coding assistant",
24944
+ "complexity": "low — consumer-side execution is automatic on install/import/compile; --ignore-scripts mitigates only the npm postinstall path, not PyPI import-time or crates build-time triggers",
24945
+ "ai_factor": "AI-ASSISTED WEAPONIZATION (not AI-discovered). The .cursorrules/CLAUDE.md zero-width-Unicode prompt-injection that subverts an AI coding assistant into exfiltrating secrets is the differentiator — maps ATLAS AML.T0051 (LLM prompt injection). Ties directly to the Trojan-Source codepoint-threat surface (CVE-2021-42574) the catalog already tracks."
24946
+ },
24947
+ "defense_chain": {
24948
+ "prevention": {
24949
+ "what_would_have_worked": "Scope-pinning + provenance on dependencies; --ignore-scripts (npm path only); scanning .cursorrules/CLAUDE.md and other AI-assistant config files for zero-width Unicode before an assistant reads them; treating AI-assistant config as untrusted input.",
24950
+ "was_this_required": false,
24951
+ "framework_requiring_it": null,
24952
+ "adequacy": "No framework treats AI-coding-assistant config files as a prompt-injection attack surface. --ignore-scripts is partial (misses import-time + compile-time triggers)."
24953
+ },
24954
+ "detection": {
24955
+ "what_would_have_worked": "Install/import/compile-time egress monitoring (the GitHub-Pages C2 + Gist exfil); a zero-width-Unicode scan over repo config files (.cursorrules, CLAUDE.md) — the same codepoint-class the catalog flags for Trojan-Source; behavioral detection of a credential scan over ~/.aws, ~/.ssh, browser wallet stores following a package resolution.",
24956
+ "was_this_required": false,
24957
+ "framework_requiring_it": null,
24958
+ "adequacy": "PyPI variant pulls live JS at import time, so the on-disk package may not contain the final payload — network/DNS capture to the C2 is required to prove exfil. Zero-width Unicode in repo config is invisible in normal review."
24959
+ },
24960
+ "response": {
24961
+ "what_would_have_worked": "Remove the named packages; rotate ALL credentials reachable from any host that installed/imported/compiled them; audit .cursorrules/CLAUDE.md for hidden instructions; block egress to the C2.",
24962
+ "was_this_required": false,
24963
+ "framework_requiring_it": null,
24964
+ "adequacy": "Registry takedown was partial (some versions live at reporting time); crates.io ids not yet in OSV. Rotation is the only reliable response once secrets are harvested."
24965
+ }
24966
+ },
24967
+ "framework_coverage": {
24968
+ "EU-AI-Act-Art15": {
24969
+ "covered": true,
24970
+ "adequate": false,
24971
+ "gap": "AI robustness/accuracy controls do not address adversarial prompt-injection planted in repo config files that subvert a developer AI assistant."
24972
+ },
24973
+ "NIS2-Art21-supply-chain": {
24974
+ "covered": true,
24975
+ "adequate": false,
24976
+ "gap": "No coverage of cross-ecosystem coordinated campaigns or AI-assistant config-file poisoning as a supply-chain vector."
24977
+ },
24978
+ "DORA-ICT-third-party": {
24979
+ "covered": true,
24980
+ "adequate": false,
24981
+ "gap": "ICT third-party risk assumes vendor relationships, not transitive OSS lure-packages auto-executing on import/build."
24982
+ },
24983
+ "UK-CAF-B4-supply-chain": {
24984
+ "covered": true,
24985
+ "adequate": false,
24986
+ "gap": "Does not cover build-time (build.rs) or import-time auto-execution distinct from install-time hooks."
24987
+ },
24988
+ "ANY-FRAMEWORK": {
24989
+ "covered": false,
24990
+ "adequate": false,
24991
+ "gap": "No framework treats AI-coding-assistant config-file prompt-injection as a supply-chain exfiltration vector. NEW-CTRL-115/116 are the headline novel controls."
24992
+ }
24993
+ },
24994
+ "new_control_requirements": [
24995
+ {
24996
+ "id": "NEW-CTRL-115",
24997
+ "name": "AI-ASSISTANT-CONFIG-POISONING-DETECTION",
24998
+ "description": "Scan AI-coding-assistant configuration files (.cursorrules, CLAUDE.md, .github/copilot-instructions.md, and equivalents) for zero-width / bidirectional / invisible Unicode codepoints and for instructions that direct the assistant to read credential paths, run \"security scans\", or perform network egress. Treat AI-assistant config as untrusted input on dependency intake; render it through a codepoint-normalizer (the Trojan-Source class, CVE-2021-42574) before any assistant consumes it.",
24999
+ "evidence": "MAL-2026-TRAPDOOR-CROSS-ECOSYSTEM — the payload planted .cursorrules and CLAUDE.md with zero-width-Unicode-hidden instructions to trick Cursor/Claude Code into discovering and exfiltrating local secrets.",
25000
+ "gap_closes": [
25001
+ "EU-AI-Act-Art15",
25002
+ "NIS2-Art21-supply-chain",
25003
+ "ANY-FRAMEWORK"
25004
+ ]
25005
+ },
25006
+ {
25007
+ "id": "NEW-CTRL-116",
25008
+ "name": "MULTI-TRIGGER-DEPENDENCY-EXECUTION-POLICY",
25009
+ "description": "Dependency-execution policy must cover install-time (npm postinstall), import-time (PyPI module load / node -e), AND compile-time (crates build.rs) execution — not install hooks alone. --ignore-scripts addresses only the npm postinstall path. Enforce egress allowlists during install/import/compile in CI and monitor for second-stage fetches from dynamic config hosts.",
25010
+ "evidence": "MAL-2026-TRAPDOOR-CROSS-ECOSYSTEM — npm postinstall, PyPI import-time node -e, and crates.io build.rs were three distinct execution triggers; --ignore-scripts mitigated only the first.",
25011
+ "gap_closes": [
25012
+ "NIS2-Art21-supply-chain",
25013
+ "UK-CAF-B4-supply-chain",
25014
+ "DORA-ICT-third-party"
25015
+ ]
25016
+ }
25017
+ ],
25018
+ "compliance_exposure_score": {
25019
+ "percent_audit_passing_orgs_still_exposed": 96,
25020
+ "basis": "AI-coding-assistant config files are not in scope for any current supply-chain or AI-governance control; near-total exposure. Multi-trigger execution (import/compile) is uncovered by the install-hook-centric --ignore-scripts mitigation most programs rely on.",
25021
+ "theater_pattern": "ai_assistant_config_treated_as_trusted"
25022
+ },
25023
+ "ai_discovered_zeroday": false,
25024
+ "ai_discovery_source": "vendor_research",
25025
+ "ai_discovery_date": "2026-05-25",
25026
+ "ai_assist_factor": "high"
25027
+ },
25028
+ "MAL-2026-MOIKA-DEPCONFUSION": {
25029
+ "name": "oob.moika.tech dependency-confusion credential-exfiltration campaign (internal-scope namespace squat)",
25030
+ "lesson_date": "2026-05-30",
25031
+ "attack_vector": {
25032
+ "description": "Dependency-confusion / internal-scope namespace-squat campaign (C2 oob.moika.tech, OSV MAL-2026-4952/4978/5032). The attacker published public npm packages under organizational scopes that mirror targets internal namespaces (@cloudplatform-single-spa, @mlspace, @sber-ecom-core, etc.) at inflated semver (99.99.99 etc.) so default npm resolution prefers the public package when no scope->registry pin exists. A 7-13 KB obfuscated postinstall stager fetches a second stage from oob.moika.tech/payload (header X-Secret: l95HdDaz3kQx1Zsg3WxH6HvKANf51RY1) and POSTs the full process.env (NPM_TOKEN, AWS keys, GITHUB_TOKEN, DB URLs) + host fingerprint to oob.moika.tech/report. Microsoft documents a server-side toggle gating second-stage escalation, but the /report env-exfil is live. Class: dependency-confusion with postinstall second-stage staging — the catalog had zero dependency-confusion entries before this.",
25033
+ "privileges_required": "developer/CI runs npm install against a project referencing a squatted internal scope with no scope->registry pin; postinstall fires automatically",
25034
+ "complexity": "low — automatic on install; --ignore-scripts DOES mitigate (postinstall-gated, unlike the node-ipc main-module class). Attacker-side precondition (knowing internal scope names) is low: scope names leak via public source, CI logs, and job postings.",
25035
+ "ai_factor": "Not AI-discovered, not AI-built. Targets ML-tooling scopes (@mlspace, @data-science) among others, but the payload is conventional obfuscated JavaScript."
25036
+ },
25037
+ "defense_chain": {
25038
+ "prevention": {
25039
+ "what_would_have_worked": "Scope->registry pinning in .npmrc (@scope:registry=) for every internal scope — the structural fix for the entire dependency-confusion class; this prevents public-registry resolution regardless of version inflation. --ignore-scripts blocks the postinstall stager specifically.",
25040
+ "was_this_required": false,
25041
+ "framework_requiring_it": null,
25042
+ "adequacy": "Scope-pinning fully prevents the class but must be configured BEFORE exposure. No framework mandates it; default npm resolution silently prefers the higher public version."
25043
+ },
25044
+ "detection": {
25045
+ "what_would_have_worked": "Install-time egress monitoring (the oob.moika.tech C2); detection of a raw process.env serialization immediately followed by an outbound POST (the credential-harvest fingerprint); lockfile audit for any internal scope resolved to a PUBLIC-registry tarball at an inflated version (99.99.99 / 5.7.1 / 99.5.x).",
25046
+ "was_this_required": false,
25047
+ "framework_requiring_it": null,
25048
+ "adequacy": "A postinstall POST to /report proves exfil; postinstall execution alone does not. Most CI runners do not monitor install-time egress."
25049
+ },
25050
+ "response": {
25051
+ "what_would_have_worked": "Pin internal scopes to the private registry in project + CI .npmrc; rotate every credential exposed as an env var on any host that ran an affected install during the exposure windows; block egress to oob.moika.tech and the t-in-one lure domains.",
25052
+ "was_this_required": false,
25053
+ "framework_requiring_it": null,
25054
+ "adequacy": "Per-package yank is reactive — any attacker can re-publish an inflated version under an unpinned internal scope. Scope-pinning is the only durable fix."
25055
+ }
25056
+ },
25057
+ "framework_coverage": {
25058
+ "NIST-800-218-SSDF": {
25059
+ "covered": true,
25060
+ "adequate": false,
25061
+ "gap": "Component-provenance controls assume the consumed package is the intended one; SSDF does not mandate scope->registry pinning, so a confused resolution is SSDF-conformant."
25062
+ },
25063
+ "EU-CRA-Art13": {
25064
+ "covered": true,
25065
+ "adequate": false,
25066
+ "gap": "SBOM records what resolved, not whether resolution should have gone to a private registry; a confused public package is SBOM-listed and CRA-compliant."
25067
+ },
25068
+ "NIS2-Art21-supply-chain": {
25069
+ "covered": true,
25070
+ "adequate": false,
25071
+ "gap": "No requirement for scope-registry pinning, postinstall-hook policy, or internal-namespace-squat monitoring on public registries."
25072
+ },
25073
+ "SLSA-v1.0-Provenance": {
25074
+ "covered": true,
25075
+ "adequate": false,
25076
+ "gap": "Provenance attests who built an artifact; it cannot assert the resolver selected the artifact the org intended — orthogonal to dependency confusion."
25077
+ },
25078
+ "ANY-FRAMEWORK": {
25079
+ "covered": false,
25080
+ "adequate": false,
25081
+ "gap": "No major framework mandates internal-scope->registry pinning as a dependency-confusion control. NEW-CTRL-117 is the headline novel control."
25082
+ }
25083
+ },
25084
+ "new_control_requirements": [
25085
+ {
25086
+ "id": "NEW-CTRL-117",
25087
+ "name": "PACKAGE-INTERNAL-SCOPE-REGISTRY-PINNING",
25088
+ "description": "Every internal/private package scope must be pinned to its private registry in project and CI .npmrc (@scope:registry=https://private-registry/), so public-registry resolution can never win regardless of version inflation. Continuously monitor public registries for newly published packages under the organization internal scope names (namespace-squat detection). Lockfile-audit for any internal scope resolved to a public-registry tarball. This is the structural fix for the dependency-confusion class, which no current framework prescribes.",
25089
+ "evidence": "MAL-2026-MOIKA-DEPCONFUSION — ~164-179 public npm packages were published under squatted internal scopes at inflated versions (99.99.99 etc.) so default resolution preferred them; a postinstall stager exfiltrated full process.env. Scope->registry pinning would have prevented every install.",
25090
+ "gap_closes": [
25091
+ "NIST-800-218-SSDF",
25092
+ "NIS2-Art21-supply-chain",
25093
+ "EU-CRA-Art13",
25094
+ "ANY-FRAMEWORK"
25095
+ ]
25096
+ }
25097
+ ],
25098
+ "compliance_exposure_score": {
25099
+ "percent_audit_passing_orgs_still_exposed": 88,
25100
+ "basis": "Scope->registry pinning is a non-default npm configuration that no framework mandates; most organizations using internal scopes have not pinned them, leaving the public registry able to win resolution on an inflated version.",
25101
+ "theater_pattern": "default_registry_resolution_assumed_safe"
25102
+ },
25103
+ "ai_discovered_zeroday": false,
25104
+ "ai_discovery_source": "vendor_research",
25105
+ "ai_discovery_date": "2026-05-28",
25106
+ "ai_assist_factor": "low"
24857
25107
  }
24858
25108
  }