@blamejs/exceptd-skills 0.12.7 → 0.12.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/AGENTS.md +14 -0
  2. package/CHANGELOG.md +67 -0
  3. package/bin/exceptd.js +189 -52
  4. package/data/_indexes/_meta.json +37 -37
  5. package/data/_indexes/activity-feed.json +26 -26
  6. package/data/_indexes/catalog-summaries.json +8 -8
  7. package/data/_indexes/chains.json +238 -0
  8. package/data/_indexes/frequency.json +63 -5
  9. package/data/_indexes/jurisdiction-map.json +13 -3
  10. package/data/_indexes/section-offsets.json +881 -845
  11. package/data/_indexes/summary-cards.json +2 -2
  12. package/data/_indexes/token-budget.json +145 -125
  13. package/data/atlas-ttps.json +189 -1
  14. package/data/cwe-catalog.json +290 -1
  15. package/data/d3fend-catalog.json +163 -1
  16. package/data/framework-control-gaps.json +243 -0
  17. package/data/playbooks/containers.json +23 -5
  18. package/data/playbooks/cred-stores.json +9 -9
  19. package/data/playbooks/crypto.json +8 -8
  20. package/data/playbooks/hardening.json +46 -10
  21. package/data/playbooks/library-author.json +16 -20
  22. package/data/playbooks/runtime.json +7 -7
  23. package/data/playbooks/sbom.json +11 -11
  24. package/data/playbooks/secrets.json +4 -4
  25. package/data/rfc-references.json +144 -0
  26. package/lib/refresh-external.js +25 -5
  27. package/lib/schemas/skill-frontmatter.schema.json +2 -2
  28. package/manifest-snapshot.json +1 -1
  29. package/manifest.json +67 -67
  30. package/package.json +2 -1
  31. package/sbom.cdx.json +6 -6
  32. package/scripts/check-sbom-currency.js +87 -0
  33. package/scripts/check-test-coverage.README.md +148 -0
  34. package/scripts/check-test-coverage.js +455 -0
  35. package/scripts/hooks/pre-commit.sh +19 -0
  36. package/scripts/predeploy.js +16 -30
  37. package/skills/age-gates-child-safety/skill.md +3 -0
  38. package/skills/ai-attack-surface/skill.md +4 -1
  39. package/skills/ai-c2-detection/skill.md +6 -1
  40. package/skills/ai-risk-management/skill.md +3 -0
  41. package/skills/api-security/skill.md +3 -0
  42. package/skills/attack-surface-pentest/skill.md +3 -0
  43. package/skills/cloud-security/skill.md +3 -0
  44. package/skills/container-runtime-security/skill.md +3 -0
  45. package/skills/coordinated-vuln-disclosure/skill.md +8 -1
  46. package/skills/defensive-countermeasure-mapping/skill.md +1 -1
  47. package/skills/dlp-gap-analysis/skill.md +3 -0
  48. package/skills/email-security-anti-phishing/skill.md +9 -1
  49. package/skills/identity-assurance/skill.md +6 -1
  50. package/skills/incident-response-playbook/skill.md +8 -2
  51. package/skills/kernel-lpe-triage/skill.md +24 -4
  52. package/skills/mcp-agent-trust/skill.md +4 -1
  53. package/skills/mlops-security/skill.md +3 -0
  54. package/skills/ot-ics-security/skill.md +3 -0
  55. package/skills/rag-pipeline-security/skill.md +3 -0
  56. package/skills/sector-energy/skill.md +3 -0
  57. package/skills/sector-federal-government/skill.md +3 -0
  58. package/skills/sector-financial/skill.md +3 -0
  59. package/skills/sector-healthcare/skill.md +3 -0
  60. package/skills/security-maturity-tiers/skill.md +19 -1
  61. package/skills/skill-update-loop/skill.md +32 -0
  62. package/skills/supply-chain-integrity/skill.md +3 -0
  63. package/skills/threat-modeling-methodology/skill.md +3 -0
  64. package/skills/webapp-security/skill.md +3 -0
@@ -442,7 +442,7 @@
442
442
  {
443
443
  "id": "ml-kem-absent",
444
444
  "type": "log_pattern",
445
- "value": "openssl list -kem-algorithms does NOT contain ML-KEM-768 (or ML-KEM-512 / ML-KEM-1024)",
445
+ "value": "Within the openssl-kem-algorithms artifact: `openssl list -kem-algorithms` output does NOT contain ML-KEM-768 (or ML-KEM-512 / ML-KEM-1024); cross-reference openssl-providers artifact — if no oqsprovider / pqc provider is loaded the KEM absence is library-wide not provider-conditional",
446
446
  "description": "Primary detector — TLS library cannot negotiate ML-KEM. Entire stack is classical-only.",
447
447
  "confidence": "deterministic",
448
448
  "deterministic": true
@@ -450,7 +450,7 @@
450
450
  {
451
451
  "id": "ml-dsa-slh-dsa-absent",
452
452
  "type": "log_pattern",
453
- "value": "openssl list -signature-algorithms does NOT contain ML-DSA-44/65/87 AND does NOT contain SLH-DSA-*",
453
+ "value": "Within the openssl-kem-algorithms artifact (its `openssl list -signature-algorithms` half): output does NOT contain ML-DSA-44/65/87 AND does NOT contain SLH-DSA-*",
454
454
  "description": "TLS library cannot use PQC signatures. Certificate-chain PQC migration is blocked.",
455
455
  "confidence": "deterministic",
456
456
  "deterministic": true
@@ -458,7 +458,7 @@
458
458
  {
459
459
  "id": "openssl-pre-3-5",
460
460
  "type": "log_pattern",
461
- "value": "openssl version starts with 'OpenSSL 1.', 'OpenSSL 2.', 'OpenSSL 3.0', 'OpenSSL 3.1', 'OpenSSL 3.2', 'OpenSSL 3.3', or 'OpenSSL 3.4'",
461
+ "value": "Within the openssl-version artifact: output starts with 'OpenSSL 1.', 'OpenSSL 2.', 'OpenSSL 3.0', 'OpenSSL 3.1', 'OpenSSL 3.2', 'OpenSSL 3.3', or 'OpenSSL 3.4'; cross-check libssl-libraries artifact to detect coexisting older libcrypto.so loaded via LD_LIBRARY_PATH or vendored builds (LibreSSL, BoringSSL, vendored OpenSSL under /usr/local/lib)",
462
462
  "description": "Pre-3.5 OpenSSL lacks native ML-KEM. Requires oqsprovider or upgrade.",
463
463
  "confidence": "deterministic",
464
464
  "deterministic": true
@@ -466,7 +466,7 @@
466
466
  {
467
467
  "id": "sshd-no-pqc-kex",
468
468
  "type": "log_pattern",
469
- "value": "sshd -T effective KexAlgorithms does NOT contain sntrup761x25519-sha512@openssh.com AND does NOT contain mlkem768x25519-sha256",
469
+ "value": "Within the sshd-config-effective artifact: KexAlgorithms does NOT contain sntrup761x25519-sha512@openssh.com AND does NOT contain mlkem768x25519-sha256; cross-check ssh-version artifact — OpenSSH 9.0+ supports sntrup761 hybrid, so an older ssh-version reading explains why even an updated sshd-config-effective would lack it",
470
470
  "description": "SSH daemon cannot negotiate PQC hybrid KEX. All SSH session keys HNDL-recordable.",
471
471
  "confidence": "deterministic",
472
472
  "deterministic": true,
@@ -475,7 +475,7 @@
475
475
  {
476
476
  "id": "tls-no-hybrid-group",
477
477
  "type": "network_pattern",
478
- "value": "openssl s_client -groups X25519MLKEM768 fails to negotiate (server returns 'no shared group' or downgrades to X25519)",
478
+ "value": "Within the tls-server-handshake artifact: `openssl s_client -groups X25519MLKEM768` against each locally-terminated TLS port fails to negotiate (server returns 'no shared group' or downgrades to X25519)",
479
479
  "description": "Local TLS service cannot negotiate hybrid PQC group. HNDL-recordable handshake.",
480
480
  "confidence": "high",
481
481
  "deterministic": false,
@@ -484,7 +484,7 @@
484
484
  {
485
485
  "id": "rsa-2048-cert-long-life",
486
486
  "type": "file_path",
487
- "value": "Any cert in trust chain or as host cert uses RSA <= 2048 AND validity period > 10 years (or signs long-retention data)",
487
+ "value": "Across the certificate-store and host-cert-keys artifacts: any cert in the trust chain or serving as a TLS host cert uses RSA <= 2048 AND validity period > 10 years (or signs long-retention data)",
488
488
  "description": "Classical RSA cert with sensitivity horizon exceeding CRQC estimate.",
489
489
  "confidence": "deterministic",
490
490
  "deterministic": true
@@ -492,7 +492,7 @@
492
492
  {
493
493
  "id": "weak-mac-or-cipher",
494
494
  "type": "log_pattern",
495
- "value": "sshd MACs contain hmac-sha1, hmac-md5, or *-cbc, OR sshd Ciphers contain 3des-cbc / aes*-cbc / arcfour*",
495
+ "value": "Within the sshd-config-effective artifact: MACs contain hmac-sha1, hmac-md5, or *-cbc, OR Ciphers contain 3des-cbc / aes*-cbc / arcfour*",
496
496
  "description": "Weak symmetric or MAC algorithms accepted by sshd.",
497
497
  "confidence": "deterministic",
498
498
  "deterministic": true
@@ -500,7 +500,7 @@
500
500
  {
501
501
  "id": "no-crypto-inventory",
502
502
  "type": "behavioral_signal",
503
- "value": "No /etc/crypto-inventory, no centralized PQC migration tracker, no per-asset cryptography mapping",
503
+ "value": "The crypto-policy artifact returns empty / no /etc/crypto-policies/config, no /etc/crypto-inventory, no /etc/ssl/openssl.cnf-derived organisation-level policy, no centralized PQC migration tracker, no per-asset cryptography mapping",
504
504
  "description": "NIS2 Art.21(2)(h) requires cryptographic asset inventory. Absence is itself a finding.",
505
505
  "confidence": "high",
506
506
  "deterministic": false
@@ -397,7 +397,7 @@
397
397
  {
398
398
  "id": "kptr-restrict-disabled",
399
399
  "type": "behavioral_signal",
400
- "value": "kernel.kptr_restrict == 0",
400
+ "value": "Within the sysctl-kernel-hardening artifact: kernel.kptr_restrict == 0",
401
401
  "description": "/proc/kallsyms is world-readable; KASLR is effectively defeated for any local user. Decisive for kernel LPE exploitability.",
402
402
  "confidence": "deterministic",
403
403
  "deterministic": true,
@@ -406,7 +406,7 @@
406
406
  {
407
407
  "id": "unprivileged-userns-enabled",
408
408
  "type": "behavioral_signal",
409
- "value": "kernel.unprivileged_userns_clone == 1",
409
+ "value": "Within the sysctl-kernel-hardening artifact: kernel.unprivileged_userns_clone == 1",
410
410
  "description": "Unprivileged user namespaces enabled. Required primitive for CVE-2026-31431 and userns-class LPEs.",
411
411
  "confidence": "deterministic",
412
412
  "deterministic": true,
@@ -415,7 +415,7 @@
415
415
  {
416
416
  "id": "unprivileged-bpf-allowed",
417
417
  "type": "behavioral_signal",
418
- "value": "kernel.unprivileged_bpf_disabled == 0",
418
+ "value": "Within the sysctl-kernel-hardening artifact: kernel.unprivileged_bpf_disabled == 0",
419
419
  "description": "Unprivileged BPF allowed. Required primitive for BPF-class LPEs.",
420
420
  "confidence": "deterministic",
421
421
  "deterministic": true,
@@ -424,7 +424,7 @@
424
424
  {
425
425
  "id": "yama-ptrace-permissive",
426
426
  "type": "behavioral_signal",
427
- "value": "kernel.yama.ptrace_scope == 0",
427
+ "value": "Within the sysctl-kernel-hardening artifact: kernel.yama.ptrace_scope == 0",
428
428
  "description": "Yama ptrace_scope=0 allows any process to ptrace any same-UID process. Credential-theft + privilege-pivot primitive.",
429
429
  "confidence": "deterministic",
430
430
  "deterministic": true,
@@ -433,7 +433,7 @@
433
433
  {
434
434
  "id": "kaslr-disabled-at-boot",
435
435
  "type": "log_pattern",
436
- "value": "/proc/cmdline contains 'nokaslr' OR 'kaslr=off'",
436
+ "value": "Within the kernel-cmdline artifact: /proc/cmdline contains 'nokaslr' OR 'kaslr=off'",
437
437
  "description": "Boot-time KASLR disabled. Makes catalogued kernel LPEs deterministic.",
438
438
  "confidence": "deterministic",
439
439
  "deterministic": true,
@@ -442,7 +442,7 @@
442
442
  {
443
443
  "id": "mitigations-off",
444
444
  "type": "log_pattern",
445
- "value": "/proc/cmdline contains 'mitigations=off'",
445
+ "value": "Within the kernel-cmdline artifact: /proc/cmdline contains 'mitigations=off'; corroborate against cpu-vulnerabilities artifact which should then report 'Vulnerable' for at least one of Spectre v1/v2, Meltdown, MDS, L1TF, Retbleed, Downfall, GDS, RFDS, or Reptar",
446
446
  "description": "Boot-time CPU mitigations disabled. Spectre/Meltdown/MDS/Retbleed/Downfall class becomes exploitable.",
447
447
  "confidence": "deterministic",
448
448
  "deterministic": true,
@@ -451,7 +451,7 @@
451
451
  {
452
452
  "id": "selinux-not-enforcing",
453
453
  "type": "behavioral_signal",
454
- "value": "getenforce != 'Enforcing' AND aa-status reports no enforcing profiles",
454
+ "value": "Within the selinux-state artifact: getenforce != 'Enforcing' AND within the apparmor-state artifact: aa-status reports no enforcing profiles",
455
455
  "description": "No MAC enforcement. Several catalogued LPEs that would be blocked by an Enforcing MAC layer are open.",
456
456
  "confidence": "high",
457
457
  "deterministic": false
@@ -459,7 +459,7 @@
459
459
  {
460
460
  "id": "sshd-permitrootlogin-yes",
461
461
  "type": "log_pattern",
462
- "value": "sshd_config effective: PermitRootLogin yes (or 'without-password' on legacy)",
462
+ "value": "Within the sshd-config artifact: effective PermitRootLogin yes (or 'without-password' on legacy)",
463
463
  "description": "Direct root SSH login enabled. Eliminates the privilege-escalation step.",
464
464
  "confidence": "deterministic",
465
465
  "deterministic": true,
@@ -468,7 +468,7 @@
468
468
  {
469
469
  "id": "sshd-password-auth-enabled",
470
470
  "type": "log_pattern",
471
- "value": "sshd_config effective: PasswordAuthentication yes AND no MFA via PAM",
471
+ "value": "Within the sshd-config artifact: effective PasswordAuthentication yes AND within the pam-stack artifact: no MFA module loaded (pam_google_authenticator / pam_u2f / pam_oath / pam_yubico absent from common-auth or system-auth)",
472
472
  "description": "Password-only SSH authentication. Credential-spray primitive.",
473
473
  "confidence": "high",
474
474
  "deterministic": false,
@@ -477,10 +477,46 @@
477
477
  {
478
478
  "id": "core-pid-dumpable",
479
479
  "type": "behavioral_signal",
480
- "value": "fs.suid_dumpable >= 1",
480
+ "value": "Within the sysctl-kernel-hardening artifact: fs.suid_dumpable >= 1",
481
481
  "description": "SUID binaries can produce core dumps. Credential leakage primitive (cores can contain decrypted secrets in memory).",
482
482
  "confidence": "high",
483
483
  "deterministic": false
484
+ },
485
+ {
486
+ "id": "kernel-lockdown-none",
487
+ "type": "behavioral_signal",
488
+ "value": "Within the kernel-lockdown artifact: /sys/kernel/security/lockdown reports 'none' (no integrity / no confidentiality bracket), OR the file is absent AND the kernel-cmdline artifact contains no `lockdown=integrity` / `lockdown=confidentiality` parameter",
489
+ "description": "Lockdown 'none' leaves /dev/mem-style reads, kexec_load, BPF tracing of kernel addresses, kprobe attach, and unsigned-module loading all available — each is a primitive that catalogued kernel-LPE chains rely on.",
490
+ "confidence": "deterministic",
491
+ "deterministic": true,
492
+ "attack_ref": "T1068"
493
+ },
494
+ {
495
+ "id": "sudoers-tty-pty-logging-absent",
496
+ "type": "log_pattern",
497
+ "value": "Within the sudoers-structure artifact: Defaults line does NOT include `requiretty` AND does NOT include `use_pty` AND does NOT include `log_input,log_output` (or `logfile=` directive)",
498
+ "description": "Sudo missing pty enforcement + I/O logging means privileged-session forensics is unrecoverable post-incident: no record of what root commands were executed by which operator, which defeats CMMC AU.L2-3.3.1 / NIST 800-53 AU-2 / NIS2 Art.21(2)(j) accountability obligations.",
499
+ "confidence": "high",
500
+ "deterministic": false,
501
+ "attack_ref": "T1548.003"
502
+ },
503
+ {
504
+ "id": "audit-rules-empty-or-skeletal",
505
+ "type": "log_pattern",
506
+ "value": "Within the audit-rules artifact: `auditctl -l` returns 'No rules' OR the loaded ruleset has fewer than 10 rules AND does NOT include watches on /etc/passwd, /etc/shadow, /etc/sudoers, /etc/sudoers.d/, OR -a always,exit -F arch=b64 -S execve",
507
+ "description": "Skeletal audit ruleset means none of the catalogued kernel LPE chains (sudoers tampering, execve under attacker-controlled paths, /etc/shadow read) leave a trail. Detection coverage for the very anti-patterns this playbook enumerates is missing.",
508
+ "confidence": "high",
509
+ "deterministic": false,
510
+ "attack_ref": "T1562.006"
511
+ },
512
+ {
513
+ "id": "umask-permissive",
514
+ "type": "log_pattern",
515
+ "value": "Within the umask-defaults artifact: effective default UMASK is 022 OR a more permissive value (000, 002) in /etc/login.defs, /etc/profile, /etc/bash.bashrc, or /etc/profile.d/*.sh — and no shell-rc override tightens it",
516
+ "description": "Permissive default umask leaves new files world-readable; combined with credentials-file-bad-perms class findings (cred-stores playbook), permissive umask is the upstream cause that produces those file modes in the first place.",
517
+ "confidence": "high",
518
+ "deterministic": false,
519
+ "attack_ref": "T1552.004"
484
520
  }
485
521
  ],
486
522
  "false_positive_profile": [
@@ -52,10 +52,6 @@
52
52
  {
53
53
  "playbook_id": "framework",
54
54
  "condition": "analyze.compliance_theater_check.verdict == 'theater'"
55
- },
56
- {
57
- "playbook_id": "compliance-theater",
58
- "condition": "analyze.compliance_theater_check.verdict == 'theater'"
59
55
  }
60
56
  ]
61
57
  },
@@ -755,7 +751,7 @@
755
751
  {
756
752
  "id": "publish-workflow-uses-static-token",
757
753
  "type": "file_path",
758
- "value": "Any .github/workflows/*.yml publish/release job references secrets.NPM_TOKEN / secrets.PYPI_TOKEN / secrets.CARGO_TOKEN / secrets.RUBYGEMS_API_KEY / secrets.GEM_HOST_API_KEY without an OIDC alternative path",
754
+ "value": "Within the release-workflows artifact: any .github/workflows/*.yml publish/release job references secrets.NPM_TOKEN / secrets.PYPI_TOKEN / secrets.CARGO_TOKEN / secrets.RUBYGEMS_API_KEY / secrets.GEM_HOST_API_KEY without an OIDC alternative path; corroborate via the repo-secrets artifact — the listed secret name is also present in the org/repo-level secret inventory",
759
755
  "description": "Long-lived publisher credential — fingerprint for non-OIDC publishing (theater #7).",
760
756
  "confidence": "deterministic",
761
757
  "deterministic": true,
@@ -764,7 +760,7 @@
764
760
  {
765
761
  "id": "publish-workflow-no-id-token-write",
766
762
  "type": "file_path",
767
- "value": "Publish/release job lacks permissions.id-token: write AND lacks Trusted Publisher configuration",
763
+ "value": "Within the release-workflows artifact: publish/release job lacks permissions.id-token: write AND lacks Trusted Publisher configuration",
768
764
  "description": "Cannot use Sigstore keyless or registry Trusted Publisher — OIDC publish is structurally unavailable.",
769
765
  "confidence": "deterministic",
770
766
  "deterministic": true
@@ -772,7 +768,7 @@
772
768
  {
773
769
  "id": "publish-workflow-action-refs-mutable",
774
770
  "type": "file_path",
775
- "value": "Any uses: in the publish/release workflow references a tag or branch (e.g. @v4, @main) rather than a 40-char SHA",
771
+ "value": "Within the release-workflows artifact: any uses: in the publish/release workflow references a tag or branch (e.g. @v4, @main) rather than a 40-char SHA",
776
772
  "description": "Mutable action reference — upstream owner can substitute action code under the same tag.",
777
773
  "confidence": "deterministic",
778
774
  "deterministic": true,
@@ -781,7 +777,7 @@
781
777
  {
782
778
  "id": "package-json-provenance-missing",
783
779
  "type": "file_path",
784
- "value": "For npm publishers: package.json has no publishConfig.provenance == true AND publish workflow command does not carry --provenance",
780
+ "value": "Within the package-manifest artifact (for npm publishers): package.json has no publishConfig.provenance == true AND within the release-workflows artifact the publish command does not carry --provenance; corroborate via the registry-publisher-config artifact — dist.attestations should be absent on the latest registry-published version",
785
781
  "description": "npm provenance not enabled — no dist.attestations on the published package (theater #2).",
786
782
  "confidence": "deterministic",
787
783
  "deterministic": true
@@ -789,7 +785,7 @@
789
785
  {
790
786
  "id": "release-workflow-non-frozen-install",
791
787
  "type": "file_path",
792
- "value": "Release workflow uses `npm install` / `pnpm install` / `pip install -r` / `bundle install` (not the --frozen / --locked / --require-hashes variant) before the build step",
788
+ "value": "Within the release-workflows artifact: release workflow uses `npm install` / `pnpm install` / `pip install -r` / `bundle install` (not the --frozen / --locked / --require-hashes variant) before the build step",
793
789
  "description": "Mid-build dependency resolution — release artifact is not reproducible (theater #5).",
794
790
  "confidence": "high",
795
791
  "deterministic": false
@@ -805,7 +801,7 @@
805
801
  {
806
802
  "id": "sbom-absent-or-unsigned",
807
803
  "type": "file_path",
808
- "value": "No SBOM artifact present in repo OR most-recent-release SBOM is present but no matching .sig / .sigstore / *.intoto.jsonl signature artifact",
804
+ "value": "Within the sbom-artifacts artifact: no SBOM file present in repo OR most-recent-release SBOM is present but no matching .sig / .sigstore artifact AND no entry in the intoto-attestations artifact carries an in-toto predicateType referencing the SBOM digest",
809
805
  "description": "SBOM theater #1 — present but unsigned, OR absent entirely.",
810
806
  "confidence": "deterministic",
811
807
  "deterministic": true,
@@ -814,7 +810,7 @@
814
810
  {
815
811
  "id": "sbom-regenerated-at-request-time",
816
812
  "type": "behavioral_signal",
817
- "value": "SBOM generation script exists in repo (e.g. scripts/generate-sbom.*) but no SBOM artifact is committed AND no release-workflow step uploads an SBOM to release assets",
813
+ "value": "SBOM generation script exists in repo (e.g. scripts/generate-sbom.*) but the sbom-artifacts artifact has no committed SBOM file AND the release-workflows artifact has no step that uploads an SBOM to release assets",
818
814
  "description": "SBOM-on-demand — historical releases have no immutable SBOM.",
819
815
  "confidence": "high",
820
816
  "deterministic": false
@@ -822,7 +818,7 @@
822
818
  {
823
819
  "id": "no-rekor-entry-for-latest-release",
824
820
  "type": "behavioral_signal",
825
- "value": "Network mode: rekor-cli search by sha256 of latest release artifact returns empty AND project README/docs claim SLSA L3 or higher",
821
+ "value": "Network mode: rekor-cli search by sha256 of the latest entry in the release-history artifact returns empty AND project README/docs claim SLSA L3 or higher",
826
822
  "description": "SLSA-claim-without-attestation (theater #4).",
827
823
  "confidence": "high",
828
824
  "deterministic": false
@@ -830,7 +826,7 @@
830
826
  {
831
827
  "id": "tag-protection-absent",
832
828
  "type": "api_response",
833
- "value": "gh api repos/${owner}/${repo}/tags/protection returns empty array OR 404 AND publish workflow triggers on push tags: ['v*']",
829
+ "value": "Within the branch-tag-protection artifact: gh api repos/${owner}/${repo}/tags/protection returns empty array OR 404 AND the release-workflows artifact contains a publish workflow that triggers on push tags: ['v*']",
834
830
  "description": "Release tags unprotected (theater #6) — any branch can push v* and trigger publish.",
835
831
  "confidence": "deterministic",
836
832
  "deterministic": true
@@ -838,7 +834,7 @@
838
834
  {
839
835
  "id": "release-tag-not-signed",
840
836
  "type": "behavioral_signal",
841
- "value": "git tag -v <latest_release_tag> returns 'no signature found' OR signature does not verify",
837
+ "value": "Within the release-history artifact: `git tag -v <latest_release_tag>` returns 'no signature found' OR signature does not verify",
842
838
  "description": "Tag-signing absent — release authenticity rests on push-time access control only.",
843
839
  "confidence": "deterministic",
844
840
  "deterministic": true
@@ -846,7 +842,7 @@
846
842
  {
847
843
  "id": "release-signed-with-personal-gpg-key",
848
844
  "type": "behavioral_signal",
849
- "value": "Tag signature verifies against a PGP key whose UID is a personal email (not an org / project address) AND key is not registered in Sigstore Rekor / Web Key Directory",
845
+ "value": "From the release-history artifact: tag signature verifies against a PGP key whose UID is a personal email (not an org / project address) AND that key (located via the signing-key-material artifact) is not registered in Sigstore Rekor / Web Key Directory",
850
846
  "description": "Personal-laptop signing key (theater #3) — XZ-class compromise vector.",
851
847
  "confidence": "high",
852
848
  "deterministic": false
@@ -878,7 +874,7 @@
878
874
  {
879
875
  "id": "vex-feed-absent",
880
876
  "type": "file_path",
881
- "value": "Absence of vex/, *.vex.json, *.csaf.json, *.openvex.json AND project has at least one published GitHub Security Advisory OR at least one filed CVE in NVD",
877
+ "value": "Within the vex-feed artifact: absence of vex/, *.vex.json, *.csaf.json, *.openvex.json AND the github-security-advisories artifact lists at least one published advisory for the repo (or NVD has at least one filed CVE against the product)",
882
878
  "description": "VEX issuance gap (theater #9) — CVEs filed against the product, no machine-readable exploitability declaration.",
883
879
  "confidence": "deterministic",
884
880
  "deterministic": true
@@ -886,7 +882,7 @@
886
882
  {
887
883
  "id": "vendored-no-provenance",
888
884
  "type": "file_path",
889
- "value": "vendor/ or third_party/ directories present AND no provenance manifest (vendor.json, THIRD_PARTY_PROVENANCE.md, modules.txt) AND not a Go vendored module",
885
+ "value": "Within the vendored-code artifact: vendor/ or third_party/ directories present AND no provenance manifest (vendor.json, THIRD_PARTY_PROVENANCE.md, modules.txt) AND not a Go vendored module",
890
886
  "description": "Vendored code without machine-verifiable upstream provenance (theater #11).",
891
887
  "confidence": "deterministic",
892
888
  "deterministic": true
@@ -894,7 +890,7 @@
894
890
  {
895
891
  "id": "skill-signing-but-verification-not-gated",
896
892
  "type": "file_path",
897
- "value": "Repo contains skill / plugin signing infrastructure (sign.js / cosign sign-blob in workflow) AND verify step exists in a separate workflow OR is conditionally skipped on the publish workflow",
893
+ "value": "The skill-signing-infrastructure artifact reports sign.js / cosign sign-blob present AND within the release-workflows artifact the verify step exists in a separate workflow OR is conditionally skipped on the publish workflow",
898
894
  "description": "Signing-without-gating (theater #8) — AI-tool publisher fingerprint.",
899
895
  "confidence": "high",
900
896
  "deterministic": false
@@ -902,7 +898,7 @@
902
898
  {
903
899
  "id": "ssdf-claimed-cra-not-ready",
904
900
  "type": "behavioral_signal",
905
- "value": "README / docs / SECURITY.md claim NIST SSDF compliance AND no five-year-support-commitment statement AND no CSAF advisory pipeline AND no signed-and-distributed SBOM",
901
+ "value": "README / docs / SECURITY.md (security-md artifact) claim NIST SSDF compliance AND the changelog artifact + release-checklist artifact carry no documented five-year-support-commitment statement AND no CSAF advisory pipeline (github-security-advisories artifact shows no CSAF-formatted disclosures) AND no signed-and-distributed SBOM (cross-references the sbom-absent-or-unsigned finding)",
906
902
  "description": "SSDF-as-CRA-readiness theater (theater #12).",
907
903
  "confidence": "high",
908
904
  "deterministic": false
@@ -910,7 +906,7 @@
910
906
  {
911
907
  "id": "publish-workflow-runs-on-self-hosted",
912
908
  "type": "file_path",
913
- "value": "Publish/release job runs-on includes 'self-hosted' OR a non-GitHub-hosted ephemeral runner",
909
+ "value": "Within the release-workflows artifact: publish/release job runs-on includes 'self-hosted' OR a non-GitHub-hosted ephemeral runner",
914
910
  "description": "Self-hosted runner — persistent runner state can be poisoned across runs.",
915
911
  "confidence": "high",
916
912
  "deterministic": false
@@ -406,7 +406,7 @@
406
406
  {
407
407
  "id": "non-baseline-suid",
408
408
  "type": "file_path",
409
- "value": "Any SUID/SGID binary not in /var/lib/exceptd/suid-baseline.txt AND not in the distro's official SUID list for the running version",
409
+ "value": "Within the suid-binaries artifact: any SUID/SGID binary not in /var/lib/exceptd/suid-baseline.txt AND not in the distro's official SUID list for the running version",
410
410
  "description": "Non-baseline SUID binary. Could be (a) post-install drift, (b) attacker-planted persistence, or (c) third-party install. All three need a finding.",
411
411
  "confidence": "high",
412
412
  "deterministic": false,
@@ -415,7 +415,7 @@
415
415
  {
416
416
  "id": "sudoers-nopasswd-wildcard",
417
417
  "type": "log_pattern",
418
- "value": "sudoers entry matching regex `NOPASSWD:\\s*(ALL|/[^,]*\\*)` for non-root user",
418
+ "value": "Within the sudo-rules artifact: any sudoers entry matching regex `NOPASSWD:\\s*(ALL|/[^,]*\\*)` for non-root user",
419
419
  "description": "Wildcard NOPASSWD entry for a non-root user is an LPE primitive. Indistinguishable on the host from an attacker-planted backdoor.",
420
420
  "confidence": "deterministic",
421
421
  "deterministic": true,
@@ -424,7 +424,7 @@
424
424
  {
425
425
  "id": "duplicate-uid-zero",
426
426
  "type": "log_pattern",
427
- "value": "/etc/passwd contains more than one entry with UID 0",
427
+ "value": "Within the passwd-shadow-baseline artifact: /etc/passwd contains more than one entry with UID 0",
428
428
  "description": "Multiple UID=0 accounts. T1136.001 persistence pattern. Outside legitimate installs.",
429
429
  "confidence": "deterministic",
430
430
  "deterministic": true,
@@ -433,7 +433,7 @@
433
433
  {
434
434
  "id": "listening-socket-unknown-bind",
435
435
  "type": "network_pattern",
436
- "value": "Listening TCP/UDP socket bound to 0.0.0.0 or :: on a port not in the host's documented service inventory",
436
+ "value": "Within the union of listening-sockets and listening-sockets-udp artifacts: any TCP/UDP socket bound to 0.0.0.0 or :: on a port not in the host's documented service inventory",
437
437
  "description": "Unknown external-bound listener. Could be a forgotten test service, a rogue agent, or a C2 listener.",
438
438
  "confidence": "high",
439
439
  "deterministic": false,
@@ -442,7 +442,7 @@
442
442
  {
443
443
  "id": "cron-or-timer-outside-policy",
444
444
  "type": "file_path",
445
- "value": "Cron entry in /etc/cron.{d,hourly,daily,weekly,monthly} OR systemd timer in /etc/systemd/system/ NOT in the org's scheduled-task inventory",
445
+ "value": "Across the cron-entries, user-cron, systemd-timers, and systemd-services artifacts: any unit / cron entry NOT in the org's scheduled-task inventory (system-wide cron under /etc/cron.{d,hourly,daily,weekly,monthly}, per-user crontab from user-cron, OR systemd .timer / enabled .service in systemd-timers/systemd-services)",
446
446
  "description": "Scheduled task not in change-management record. T1053.003 / T1053.006 persistence.",
447
447
  "confidence": "high",
448
448
  "deterministic": false,
@@ -451,7 +451,7 @@
451
451
  {
452
452
  "id": "world-writable-in-trusted-path",
453
453
  "type": "file_path",
454
- "value": "World-writable file under /etc, /usr/local/bin, /usr/local/sbin, /opt",
454
+ "value": "Within the world-writable-paths artifact: any world-writable file under /etc, /usr/local/bin, /usr/local/sbin, /opt",
455
455
  "description": "Hijack-execution-flow primitive. Any non-root process can replace the file.",
456
456
  "confidence": "deterministic",
457
457
  "deterministic": true,
@@ -460,7 +460,7 @@
460
460
  {
461
461
  "id": "orphan-privileged-process",
462
462
  "type": "process_name",
463
- "value": "Process running as UID 0 with PPID 1 AND parent != systemd/init AND executable path under /tmp, /dev/shm, /var/tmp, /home",
463
+ "value": "Within the process-tree artifact: any process running as UID 0 with PPID 1 AND parent != systemd/init AND executable path under /tmp, /dev/shm, /var/tmp, /home",
464
464
  "description": "Privileged orphan in a writable temp path. Common implant shape.",
465
465
  "confidence": "deterministic",
466
466
  "deterministic": true,
@@ -627,7 +627,7 @@
627
627
  {
628
628
  "id": "package-matches-catalogued-cve",
629
629
  "type": "log_pattern",
630
- "value": "Any inventoried package version falls inside any catalogued CVE's affected_versions range, where the CVE's framework and category match the package's class",
630
+ "value": "Across the union of inventoried packages — dpkg-packages, rpm-packages, brew-packages, npm-global-packages, pip-packages, cargo-installed, gem-packages, go-binaries, repo-lockfiles entries, AND container-image-layers package manifests — any version falls inside any affected_versions range in the cve-catalog artifact, where the cve-catalog entry's framework and category match the inventoried package's class",
631
631
  "description": "Primary detector — installed-package version matches a catalogued CVE.",
632
632
  "confidence": "high",
633
633
  "deterministic": false,
@@ -636,7 +636,7 @@
636
636
  {
637
637
  "id": "lockfile-no-integrity",
638
638
  "type": "log_pattern",
639
- "value": "Any pinned dependency in walked lockfiles lacks an integrity field (sha512/sha384/sha256, sri-integrity, go.sum-style hash)",
639
+ "value": "Within the repo-lockfiles artifact: any pinned dependency lacks an integrity field (sha512/sha384/sha256, sri-integrity, go.sum-style hash)",
640
640
  "description": "Theater fingerprint #2 detection — name-pinned without integrity.",
641
641
  "confidence": "deterministic",
642
642
  "deterministic": true
@@ -644,7 +644,7 @@
644
644
  {
645
645
  "id": "transitive-deps-incomplete-sbom",
646
646
  "type": "log_pattern",
647
- "value": "SBOM artifact present AND transitive dep count > SBOM component count * 1.05",
647
+ "value": "The sbom-artifacts artifact has at least one entry present AND the transitive dep count (computed from repo-lockfiles + container-image-layers) > SBOM component count * 1.05",
648
648
  "description": "Theater fingerprint #3 — SBOM lists direct deps only.",
649
649
  "confidence": "high",
650
650
  "deterministic": false
@@ -652,7 +652,7 @@
652
652
  {
653
653
  "id": "matched-cve-without-vex",
654
654
  "type": "log_pattern",
655
- "value": "package-matches-catalogued-cve == true AND no VEX statement exists for the matched CVE in the org's VEX register",
655
+ "value": "package-matches-catalogued-cve == true AND no entry in the vex-statements artifact covers the matched CVE (no *.vex.json / *.csaf.json statement carrying status_notes for the CVE id) — and the cve-catalog entry for that CVE is not marked vendor-rejected",
656
656
  "description": "Theater fingerprint #4 detection — matched CVE without exploitability declaration.",
657
657
  "confidence": "deterministic",
658
658
  "deterministic": true
@@ -660,7 +660,7 @@
660
660
  {
661
661
  "id": "ai-code-no-provenance",
662
662
  "type": "behavioral_signal",
663
- "value": "ai-coding-assistant-inventory shows at least one installed assistant AND SBOM has no fields capturing AI-emitted code (no ml-bom, no spdx ai-profile, no commit-trailer convention)",
663
+ "value": "ai-coding-assistant-inventory shows at least one installed assistant AND the sbom-artifacts artifact has no fields capturing AI-emitted code (no ml-bom, no spdx ai-profile, no commit-trailer convention)",
664
664
  "description": "Theater fingerprint #5 detection — AI in use, AI-emitted code not in SBOM.",
665
665
  "confidence": "high",
666
666
  "deterministic": false
@@ -694,7 +694,7 @@
694
694
  {
695
695
  "id": "tanstack-worm-payload-files",
696
696
  "type": "file_path",
697
- "value": "node_modules/@tanstack/*/router_init.js exists OR node_modules/@tanstack/*/router_runtime.js exists",
697
+ "value": "Within the tanstack-payload-sweep artifact: node_modules/@tanstack/*/router_init.js exists OR node_modules/@tanstack/*/router_runtime.js exists",
698
698
  "description": "CVE-2026-45321 (Mini Shai-Hulud) payload markers — these files do not exist in clean TanStack packages.",
699
699
  "confidence": "deterministic",
700
700
  "deterministic": true,
@@ -703,7 +703,7 @@
703
703
  {
704
704
  "id": "tanstack-worm-resolved-during-publish-window",
705
705
  "type": "log_pattern",
706
- "value": "Lockfile entry for any @tanstack/* package resolved within 2026-05-11T19:20Z..2026-05-11T19:26Z (the malicious publish window)",
706
+ "value": "Within the repo-lockfiles artifact: any @tanstack/* entry resolved within 2026-05-11T19:20Z..2026-05-11T19:26Z (the malicious publish window)",
707
707
  "description": "CVE-2026-45321 timing match — any @tanstack/* package whose lockfile-recorded resolution timestamp falls inside the 6-minute attacker publish window is suspect even if the payload markers were since cleaned.",
708
708
  "confidence": "high",
709
709
  "deterministic": false,
@@ -712,7 +712,7 @@
712
712
  {
713
713
  "id": "agent-persistence-claude-session-start-hook",
714
714
  "type": "file_path",
715
- "value": ".claude/settings.json contains hooks.SessionStart referencing .vscode/setup.mjs OR any non-blamejs-installed script",
715
+ "value": "Within the agent-persistence-claude-settings artifact: .claude/settings.json contains hooks.SessionStart referencing .vscode/setup.mjs OR any non-blamejs-installed script",
716
716
  "description": "CVE-2026-45321 persistence vector — worm installs a SessionStart hook to re-arm on next Claude Code launch. Any SessionStart hook running an in-repo .mjs that the operator didn't author is suspect.",
717
717
  "confidence": "deterministic",
718
718
  "deterministic": true,
@@ -721,7 +721,7 @@
721
721
  {
722
722
  "id": "agent-persistence-vscode-folder-open-task",
723
723
  "type": "file_path",
724
- "value": ".vscode/tasks.json contains a runOptions.runOn=folderOpen task pointing at .vscode/setup.mjs or similar",
724
+ "value": "Within the agent-persistence-vscode-tasks artifact: .vscode/tasks.json contains a runOptions.runOn=folderOpen task pointing at .vscode/setup.mjs or similar",
725
725
  "description": "CVE-2026-45321 persistence vector — folder-open hook re-arms on every VS Code re-open of the directory.",
726
726
  "confidence": "deterministic",
727
727
  "deterministic": true,
@@ -739,7 +739,7 @@
739
739
  {
740
740
  "id": "ci-cache-poisoning-co-residency",
741
741
  "type": "log_pattern",
742
- "value": "Repo .github/workflows/ contains BOTH (a) a workflow with `on: pull_request_target` AND (b) any workflow with `permissions: id-token: write` AND (c) any actions/cache step shared between the two",
742
+ "value": "Within the github-workflows artifact: the .github/workflows/ set contains BOTH (a) a workflow with `on: pull_request_target` AND (b) any workflow with `permissions: id-token: write` AND (c) any actions/cache step shared between the two",
743
743
  "description": "Architectural pre-condition for CVE-2026-45321-style chained-primitives attacks. Even without the payload, this co-residency means any successful fork-PR exploit can poison the cache that the publish workflow restores. Mitigation: separate cache namespaces, or remove pull_request_target.",
744
744
  "confidence": "deterministic",
745
745
  "deterministic": true,
@@ -748,7 +748,7 @@
748
748
  {
749
749
  "id": "npm-registry-no-cooldown",
750
750
  "type": "file_path",
751
- "value": ".npmrc and ~/.npmrc both lack `before=` or `minimumReleaseAge=` settings, AND project consumes any npm package",
751
+ "value": "Within the npmrc-cooldown-policy artifact: .npmrc and ~/.npmrc both lack `before=` or `minimumReleaseAge=` settings, AND the project consumes any npm package (any repo-lockfiles entry of class npm/yarn/pnpm exists)",
752
752
  "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.",
753
753
  "confidence": "high",
754
754
  "deterministic": false
@@ -376,7 +376,7 @@
376
376
  {
377
377
  "id": "aws-access-key-id",
378
378
  "type": "log_pattern",
379
- "value": "AKIA[0-9A-Z]{16}",
379
+ "value": "Within the secret-regex-scan-text-files artifact, bounded by the repo-tree scope and applied to env-files, auth-config-files, and iac-credential-bearers content: regex AKIA[0-9A-Z]{16}",
380
380
  "description": "AWS Access Key ID. Long-lived IAM user credential. Scraper-bot priority target.",
381
381
  "confidence": "deterministic",
382
382
  "deterministic": true,
@@ -448,7 +448,7 @@
448
448
  {
449
449
  "id": "ssh-private-key-block",
450
450
  "type": "log_pattern",
451
- "value": "-----BEGIN ((RSA|EC|DSA|OPENSSH|ENCRYPTED) )?PRIVATE KEY-----",
451
+ "value": "Across the union of secret-regex-scan-text-files (text-file content) and ssh-private-keys (file inventory) artifacts: regex `-----BEGIN ((RSA|EC|DSA|OPENSSH|ENCRYPTED) )?PRIVATE KEY-----` matches, OR the ssh-private-keys artifact lists any private-key file under the repo tree (committed key material is always a finding regardless of regex hit on the surrounding text)",
452
452
  "description": "Inline SSH/PEM private key material in a text file.",
453
453
  "confidence": "deterministic",
454
454
  "deterministic": true,
@@ -475,7 +475,7 @@
475
475
  {
476
476
  "id": "world-writable-env-file",
477
477
  "type": "file_path",
478
- "value": ".env / .env.* / .envrc with mode 0666 or 0664 (group/world writable)",
478
+ "value": "Within the world-writable-secret-files artifact, restricted to entries from the env-files artifact: any .env / .env.* / .envrc with mode 0666 or 0664 (group/world writable)",
479
479
  "description": "Env file writable by group or world. Tampering primitive.",
480
480
  "confidence": "deterministic",
481
481
  "deterministic": true,
@@ -484,7 +484,7 @@
484
484
  {
485
485
  "id": "ssh-key-bad-perms",
486
486
  "type": "file_path",
487
- "value": "~/.ssh/id_* file with mode != 0600",
487
+ "value": "Within the world-writable-secret-files artifact, restricted to entries from the ssh-private-keys artifact and ~/.ssh/id_* paths: any private-key file with mode != 0600",
488
488
  "description": "SSH private key with permissive permissions. ssh-agent refuses to load; user often chmods to 0644 or 0666 'to make it work'.",
489
489
  "confidence": "deterministic",
490
490
  "deterministic": true,