@blamejs/exceptd-skills 0.18.12 → 0.18.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +20 -0
- package/bin/exceptd.js +26 -0
- package/data/_indexes/_meta.json +2 -2
- package/data/playbooks/ai-api.json +2 -2
- package/data/playbooks/ai-discovered-cve-triage.json +1 -1
- package/data/playbooks/audit-log-integrity.json +3 -3
- package/data/playbooks/cicd-pipeline-compromise.json +1 -1
- package/data/playbooks/citation-hygiene.json +2 -2
- package/data/playbooks/containers.json +2 -2
- package/data/playbooks/cred-stores.json +1 -1
- package/data/playbooks/crypto-codebase.json +1 -1
- package/data/playbooks/crypto.json +1 -1
- package/data/playbooks/decompression-dos.json +3 -3
- package/data/playbooks/framework.json +1 -1
- package/data/playbooks/hardening.json +1 -1
- package/data/playbooks/identity-sso-compromise.json +1 -1
- package/data/playbooks/kernel.json +2 -2
- package/data/playbooks/library-author.json +1 -1
- package/data/playbooks/llm-tool-use-exfil.json +1 -1
- package/data/playbooks/log-injection-telemetry.json +3 -3
- package/data/playbooks/mail-server-hardening.json +3 -3
- package/data/playbooks/mcp.json +2 -2
- package/data/playbooks/multitenancy-isolation.json +3 -3
- package/data/playbooks/network-trust.json +3 -3
- package/data/playbooks/post-quantum-migration.json +1 -1
- package/data/playbooks/privacy-consent-ops.json +3 -3
- package/data/playbooks/runtime.json +2 -2
- package/data/playbooks/sbom.json +1 -1
- package/data/playbooks/secrets.json +1 -1
- package/data/playbooks/self-update-integrity.json +3 -3
- package/data/playbooks/supply-chain-recovery.json +2 -2
- package/data/playbooks/vc-wallet-trust.json +5 -5
- package/data/playbooks/webhook-callback-abuse.json +1 -1
- package/lib/auto-discovery.js +10 -1
- package/lib/cve-regression-watcher.js +5 -1
- package/lib/job-queue.js +9 -2
- package/lib/lint-skills.js +34 -5
- package/lib/playbook-runner.js +51 -4
- package/lib/prefetch.js +15 -7
- package/lib/schemas/skill-frontmatter.schema.json +2 -2
- package/lib/source-ghsa.js +8 -2
- package/lib/source-osv.js +19 -3
- package/lib/ttp-mapper.js +15 -0
- package/lib/upstream-check.js +17 -3
- package/lib/validate-cve-catalog.js +16 -4
- package/lib/validate-package.js +9 -2
- package/lib/validate-playbooks.js +112 -10
- package/lib/validate-vendor.js +11 -5
- package/lib/xml-tokenizer.js +36 -8
- package/manifest.json +53 -53
- package/package.json +1 -1
- package/sbom.cdx.json +117 -117
- package/sources/validators/cve-validator.js +7 -1
- package/sources/validators/rfc-validator.js +21 -3
- package/sources/validators/version-pin-validator.js +39 -2
- package/vendor/blamejs/_PROVENANCE.json +3 -2
- package/vendor/blamejs/worker-pool.js +6 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.18.14 — 2026-06-22
|
|
4
|
+
|
|
5
|
+
Severity escalations, downstream-playbook chaining, and remediation-path preconditions now fire as authored across the playbook catalog. A number of these conditions had been written as free-text English or in a shorthand the engine does not evaluate, so they returned false for every input and silently never triggered — a raise-severity rule, a `feeds_into` chain into a deeper playbook, or a remediation precondition that looked active but never fired. Every such condition is now expressed in the engine's condition language and verified to evaluate against the indicators it gates on.
|
|
6
|
+
|
|
7
|
+
The playbook validator now runs each escalation, `feeds_into`, and remediation precondition through the real evaluator and rejects any condition it cannot parse, so one that would be dead at runtime fails validation instead of shipping.
|
|
8
|
+
|
|
9
|
+
`ci --format sarif` and `ci --format openvex` now emit the requested bundle for every scanned playbook. Previously only a playbook whose declared primary format already matched the request contributed a document, so the aggregated output was frequently an empty array.
|
|
10
|
+
|
|
11
|
+
`evidence_hash` is no longer perturbed by the chosen output format, so attesting and reattesting the same evidence with a different `--format` yields the same hash; a supplied VEX disposition still changes the hash, because it changes which CVEs are in scope.
|
|
12
|
+
|
|
13
|
+
Remediation-path preconditions can now reference the engine-computed finding — RWEP, severity, matched CVEs, blast-radius score, and compliance-theater verdict — so a precondition gated on one of those is evaluated rather than treated as unmet. The containers playbook chains into the SBOM playbook when container image layers are present.
|
|
14
|
+
|
|
15
|
+
## 0.18.13 — 2026-06-22
|
|
16
|
+
|
|
17
|
+
A correctness + robustness pass across the upstream data parsers, the validators, and the prefetch/feed paths.
|
|
18
|
+
|
|
19
|
+
The OSV advisory importer keeps the HIGHEST CVSS vector and score when a record carries multiple same-version severity entries (e.g. an NVD base score alongside a CNA/vendor score), instead of whichever appeared first in the array — a 9.8 critical no longer imports as a 5.3 medium purely because of upstream array order, which previously also flipped the derived KEV-pending / active-exploitation / severity-word fields. The RSS/Atom feed tokenizer strips HTML in a single linear pass, so a malformed or hostile feed body with many unclosed `<` can no longer stall the refresh worker (the previous regex was quadratic on attacker-controlled text). An Atom `<link>` carrying element text is now selected by its `rel` the same way the attribute form is, so a non-`alternate` link cannot override the canonical `alternate`. `refresh --advisory <ghsa-id>` validates the full `GHSA-xxxx-xxxx-xxxx` token shape and URL-encodes it before building the request path.
|
|
20
|
+
|
|
21
|
+
The playbook validator range-checks a partial `phase_overrides.direct.rwep_threshold` override and rejects an impossible calendar date (`2026-02-30`); the CVE-catalog validator reports an absent reference catalog as unvalidatable for ALL five reference families instead of flagging every `atlas_ref`/`cwe_ref` as unresolved; the RFC validator skips non-IETF references (CSAF, ISO) rather than reporting them as permanent drift; the version-pin validator no longer probes the two upstreams that publish no GitHub releases (reported as tracked elsewhere); the vendor inventory cross-check covers `.cjs`/`.mjs`/`.json`, not only `.js`; the package size-budget gate fails closed when `npm pack` omits the size field; and the disputed-CVE check reports the real local status. The skill linter flags a wrong-typed enum value and rejects an impossible `last_threat_review`, and the `d3fend_refs` frontmatter pattern accepts the `D3A-`/`D3F-` id families. `upstream-check` reports a clear error rather than `ok:true` with an undefined version when a fixture lacks dist-tags, and a non-parseable publish date yields a clear value instead of `NaN`. The prefetch index no longer resurrects entries a concurrent run pruned, `ttp-mapper` ignores inherited object keys, and the EPSS lookup returns not-found for an absent CVE instead of the first row.
|
|
22
|
+
|
|
3
23
|
## 0.18.12 — 2026-06-22
|
|
4
24
|
|
|
5
25
|
A correctness pass across the CLI, the engine, scoring, the collectors, framework-gap reporting, signature verification, and the CWE-chain index.
|
package/bin/exceptd.js
CHANGED
|
@@ -9166,6 +9166,22 @@ function cmdCi(runner, args, runOpts, pretty) {
|
|
|
9166
9166
|
let clockStartedFail = false;
|
|
9167
9167
|
let clockStartedReasons = [];
|
|
9168
9168
|
|
|
9169
|
+
// Thread the requested bundle output format into each per-playbook run so
|
|
9170
|
+
// close() actually BUILDS it. `ci --format sarif|openvex|csaf` reads each
|
|
9171
|
+
// result's evidence_package.bundles_by_format[fmt] below; the runner only
|
|
9172
|
+
// builds the playbook's declared PRIMARY bundle_format unless the operator
|
|
9173
|
+
// seeds signals._bundle_formats. Without this, any playbook whose primary
|
|
9174
|
+
// format differs from the request emitted no bundle for that format and the
|
|
9175
|
+
// aggregated `ci --format sarif/openvex` array dropped it (.filter(Boolean)),
|
|
9176
|
+
// so the output was a silent empty array. Mapping mirrors the read at the
|
|
9177
|
+
// emit site: csaf → csaf-2.0; sarif/openvex pass through. (_bundle_formats is
|
|
9178
|
+
// a `_`-prefixed render directive, so it is excluded from evidence_hash and
|
|
9179
|
+
// does not perturb attest/reattest.)
|
|
9180
|
+
let ciFormatRaw = args.format;
|
|
9181
|
+
if (Array.isArray(ciFormatRaw)) ciFormatRaw = ciFormatRaw[0];
|
|
9182
|
+
const ciBundleFormat = (ciFormatRaw === 'csaf' || ciFormatRaw === 'csaf-2.0') ? 'csaf-2.0'
|
|
9183
|
+
: (ciFormatRaw === 'sarif' || ciFormatRaw === 'openvex') ? ciFormatRaw : null;
|
|
9184
|
+
|
|
9169
9185
|
for (const id of ids) {
|
|
9170
9186
|
// defense-in-depth — validate id even though the catalog-iter
|
|
9171
9187
|
// upstream is trusted. A corrupt catalog returning a malformed id would
|
|
@@ -9186,6 +9202,16 @@ function cmdCi(runner, args, runOpts, pretty) {
|
|
|
9186
9202
|
continue;
|
|
9187
9203
|
}
|
|
9188
9204
|
const submission = bundle[id] || {};
|
|
9205
|
+
if (ciBundleFormat) {
|
|
9206
|
+
// Clone signals before injecting so the shared evidence bundle is not
|
|
9207
|
+
// mutated; merge with any operator-supplied _bundle_formats.
|
|
9208
|
+
const existing = Array.isArray(submission.signals && submission.signals._bundle_formats)
|
|
9209
|
+
? submission.signals._bundle_formats : [];
|
|
9210
|
+
submission.signals = {
|
|
9211
|
+
...(submission.signals || {}),
|
|
9212
|
+
_bundle_formats: existing.includes(ciBundleFormat) ? existing : [...existing, ciBundleFormat],
|
|
9213
|
+
};
|
|
9214
|
+
}
|
|
9189
9215
|
const perOpts = { ...runOpts, session_id: sessionId };
|
|
9190
9216
|
if (submission.precondition_checks) perOpts.precondition_checks = submission.precondition_checks;
|
|
9191
9217
|
let result;
|
package/data/_indexes/_meta.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schema_version": "1.1.0",
|
|
3
|
-
"generated_at": "2026-06-
|
|
3
|
+
"generated_at": "2026-06-22T14:16:42.035Z",
|
|
4
4
|
"generator": "scripts/build-indexes.js",
|
|
5
5
|
"source_count": 64,
|
|
6
6
|
"source_hashes": {
|
|
7
|
-
"manifest.json": "
|
|
7
|
+
"manifest.json": "be5406117ede866ec4dc653cf15f9555f8fa58c254fc601800e4bacb07ddb609",
|
|
8
8
|
"README.md": "e7b854e7db9a364a1b368b5084b4f0c2a8282f0459ce39800ac1d1dabdc06074",
|
|
9
9
|
"data/atlas-ttps.json": "5bc59e23d6c2defa54168de161a0825299b9cc4a49c6b26df2dae70b4f42eedf",
|
|
10
10
|
"data/attack-techniques.json": "53c6f248760eecb11a0354f74ab467a5814e95075a686b9b3bf18c34e2f7435e",
|
|
@@ -749,7 +749,7 @@
|
|
|
749
749
|
"action": "page_on_call"
|
|
750
750
|
},
|
|
751
751
|
{
|
|
752
|
-
"condition": "
|
|
752
|
+
"condition": "(cleartext-api-key-in-dotfile == true OR long-lived-aws-keys == true OR gcp-service-account-json == true OR kubeconfig-with-static-token == true) AND blast_radius_score >= 4",
|
|
753
753
|
"action": "page_on_call"
|
|
754
754
|
},
|
|
755
755
|
{
|
|
@@ -849,7 +849,7 @@
|
|
|
849
849
|
"id": "policy-exception",
|
|
850
850
|
"description": "Where business-critical interactive use makes egress proxying or process allowlisting infeasible, generate a defensible policy exception with compensating controls (rate quota per service account, vendor-side abuse alerting integration, weekly dotfile re-audit).",
|
|
851
851
|
"preconditions": [
|
|
852
|
-
"
|
|
852
|
+
"prior_remediations_blocked == true",
|
|
853
853
|
"ciso_acceptance_obtainable == true"
|
|
854
854
|
],
|
|
855
855
|
"priority": 5,
|
|
@@ -857,7 +857,7 @@
|
|
|
857
857
|
"id": "policy-exception",
|
|
858
858
|
"description": "For assets that cannot reach the AI-discovered-tier SLA within the cycle: generate auditor-ready policy exception with compensating controls (live patch, network isolation, module unload, monitoring), time-bound risk acceptance, and remediation milestones.",
|
|
859
859
|
"preconditions": [
|
|
860
|
-
"
|
|
860
|
+
"prior_remediations_blocked == true",
|
|
861
861
|
"ciso_acceptance_obtainable == true"
|
|
862
862
|
],
|
|
863
863
|
"priority": 6,
|
|
@@ -448,11 +448,11 @@
|
|
|
448
448
|
],
|
|
449
449
|
"escalation_criteria": [
|
|
450
450
|
{
|
|
451
|
-
"condition": "
|
|
451
|
+
"condition": "audit-log-deletable-by-writing-identity == true AND (audit-hash-chain-not-verified == true OR audit-log-not-signed-or-key-colocated == true)",
|
|
452
452
|
"action": "raise_severity"
|
|
453
453
|
},
|
|
454
454
|
{
|
|
455
|
-
"condition": "
|
|
455
|
+
"condition": "legal-hold-not-blocking-purge == true",
|
|
456
456
|
"action": "trigger_playbook"
|
|
457
457
|
}
|
|
458
458
|
]
|
|
@@ -463,7 +463,7 @@
|
|
|
463
463
|
"id": "verify-chain-and-sign-off-host",
|
|
464
464
|
"description": "Verify the audit hash chain on every read/replay/export and fail closed on a break; sign chain checkpoints with a key held by a separate identity / KMS / HSM, not the log-writing process.",
|
|
465
465
|
"preconditions": [
|
|
466
|
-
"
|
|
466
|
+
"operator_controls_audit_subsystem == true"
|
|
467
467
|
],
|
|
468
468
|
"priority": 1,
|
|
469
469
|
"for_signals": [
|
|
@@ -743,7 +743,7 @@
|
|
|
743
743
|
"id": "policy-exception",
|
|
744
744
|
"description": "Generate auditor-ready policy exception when faster paths are blocked.",
|
|
745
745
|
"preconditions": [
|
|
746
|
-
"
|
|
746
|
+
"prior_remediations_blocked == true",
|
|
747
747
|
"ciso_acceptance_obtainable == true"
|
|
748
748
|
],
|
|
749
749
|
"priority": 6,
|
|
@@ -542,7 +542,7 @@
|
|
|
542
542
|
"target_playbook": "framework"
|
|
543
543
|
},
|
|
544
544
|
{
|
|
545
|
-
"condition": "rejected-or-disputed-cve
|
|
545
|
+
"condition": "rejected-or-disputed-cve == true AND cited-cve-active-exploitation-confirmed == true",
|
|
546
546
|
"action": "raise_severity"
|
|
547
547
|
}
|
|
548
548
|
]
|
|
@@ -609,7 +609,7 @@
|
|
|
609
609
|
"id": "policy-exception",
|
|
610
610
|
"description": "If a citation cannot be resolved within the review window (e.g. an embargoed advisory not yet public, an RFC pending publication): generate an auditor-ready policy exception recording the pending citation, the verification deadline, and the interim caveat added to the documentation.",
|
|
611
611
|
"preconditions": [
|
|
612
|
-
"
|
|
612
|
+
"prior_remediations_blocked == true AND external_dependency == true"
|
|
613
613
|
],
|
|
614
614
|
"priority": 5,
|
|
615
615
|
"compensating_controls": [
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
},
|
|
44
44
|
{
|
|
45
45
|
"playbook_id": "sbom",
|
|
46
|
-
"condition": "container-image-layers
|
|
46
|
+
"condition": "container-image-layers > 0"
|
|
47
47
|
}
|
|
48
48
|
]
|
|
49
49
|
},
|
|
@@ -795,7 +795,7 @@
|
|
|
795
795
|
"action": "page_on_call"
|
|
796
796
|
},
|
|
797
797
|
{
|
|
798
|
-
"condition": "k8s-cluster-admin-binding
|
|
798
|
+
"condition": "k8s-cluster-admin-binding == true AND target-namespace-outside-infra-allowlist == true",
|
|
799
799
|
"action": "raise_severity"
|
|
800
800
|
},
|
|
801
801
|
{
|
|
@@ -818,7 +818,7 @@
|
|
|
818
818
|
"id": "fix-credentials-perms",
|
|
819
819
|
"description": "chmod 0600 on all credential files; chmod 0700 on ~/.config/gcloud/, ~/.aws/, ~/.ssh/.",
|
|
820
820
|
"preconditions": [
|
|
821
|
-
"file_owner_is_current_user"
|
|
821
|
+
"file_owner_is_current_user == true"
|
|
822
822
|
],
|
|
823
823
|
"priority": 2,
|
|
824
824
|
"for_signals": [
|
|
@@ -1093,7 +1093,7 @@
|
|
|
1093
1093
|
"id": "policy-exception",
|
|
1094
1094
|
"description": "If a deprecated primitive cannot be removed in a minor version due to API-stability promise: generate auditor-ready policy exception. Time-bound until next major version with explicit migration roadmap, deprecation warning emitted at runtime, parallel new API published, downstream-consumer migration guide.",
|
|
1095
1095
|
"preconditions": [
|
|
1096
|
-
"
|
|
1096
|
+
"prior_remediations_blocked == true AND api_stability == true",
|
|
1097
1097
|
"next_major_version_window <= 12_months",
|
|
1098
1098
|
"ciso_or_maintainer_acceptance_obtainable == true"
|
|
1099
1099
|
],
|
|
@@ -800,7 +800,7 @@
|
|
|
800
800
|
"id": "policy-exception",
|
|
801
801
|
"description": "If a specific asset cannot reach hybrid PQC in this cycle (legacy hardware, embedded HSM without PQC firmware, vendor SaaS): generate auditor-ready policy exception with crypto-agility roadmap.",
|
|
802
802
|
"preconditions": [
|
|
803
|
-
"
|
|
803
|
+
"prior_remediations_blocked == true",
|
|
804
804
|
"ciso_acceptance_obtainable == true"
|
|
805
805
|
],
|
|
806
806
|
"priority": 6,
|
|
@@ -429,11 +429,11 @@
|
|
|
429
429
|
],
|
|
430
430
|
"escalation_criteria": [
|
|
431
431
|
{
|
|
432
|
-
"condition": "
|
|
432
|
+
"condition": "archive-decompression-unbounded == true OR length-field-unbounded-allocation == true OR nested-archive-bomb-uncapped == true OR xml-entity-expansion-enabled == true OR redos-catastrophic-backtracking == true OR recursive-parse-no-depth-limit == true",
|
|
433
433
|
"action": "raise_severity"
|
|
434
434
|
},
|
|
435
435
|
{
|
|
436
|
-
"condition": "
|
|
436
|
+
"condition": "zip-slip-path-traversal == true",
|
|
437
437
|
"action": "trigger_playbook"
|
|
438
438
|
}
|
|
439
439
|
]
|
|
@@ -444,7 +444,7 @@
|
|
|
444
444
|
"id": "cap-decompression",
|
|
445
445
|
"description": "Enforce a total decompressed-output size ceiling AND a per-entry compression-ratio guard, plus a cumulative cap and recursion limit for nested archives; fail closed when exceeded.",
|
|
446
446
|
"preconditions": [
|
|
447
|
-
"
|
|
447
|
+
"operator_controls_decompression_path == true"
|
|
448
448
|
],
|
|
449
449
|
"priority": 1,
|
|
450
450
|
"for_signals": [
|
|
@@ -801,7 +801,7 @@
|
|
|
801
801
|
"id": "board-level-acknowledgement",
|
|
802
802
|
"description": "Where multiple framework-gap declarations cannot be closed within compliance windows: escalate to board-level acknowledgement of the GRC posture with documented framework-lag declaration and accepted residual risk.",
|
|
803
803
|
"preconditions": [
|
|
804
|
-
"
|
|
804
|
+
"prior_remediations_cannot_close_in_window == true",
|
|
805
805
|
"board_acceptance_obtainable == true"
|
|
806
806
|
],
|
|
807
807
|
"priority": 6,
|
|
@@ -719,7 +719,7 @@
|
|
|
719
719
|
"target_playbook": "kernel"
|
|
720
720
|
},
|
|
721
721
|
{
|
|
722
|
-
"condition": "
|
|
722
|
+
"condition": "selinux-not-enforcing == true AND apparmor-no-enforcing-profiles == true AND blast_radius_score >= 3",
|
|
723
723
|
"action": "raise_severity"
|
|
724
724
|
},
|
|
725
725
|
{
|
|
@@ -745,7 +745,7 @@
|
|
|
745
745
|
"id": "policy-exception",
|
|
746
746
|
"description": "Generate auditor-ready policy exception when faster paths are blocked.",
|
|
747
747
|
"preconditions": [
|
|
748
|
-
"
|
|
748
|
+
"prior_remediations_blocked == true",
|
|
749
749
|
"ciso_acceptance_obtainable == true"
|
|
750
750
|
],
|
|
751
751
|
"priority": 5,
|
|
@@ -612,7 +612,7 @@
|
|
|
612
612
|
"id": "hardening-compensation",
|
|
613
613
|
"description": "When reboot impossible within compliance window: tighten hardening flags (disable unpriv-userns, disable unpriv-bpf, set kptr_restrict=2, raise yama.ptrace_scope to 2) to break the exploit's primitive without patching.",
|
|
614
614
|
"preconditions": [
|
|
615
|
-
"matched_cve.vector matches userns|bpf|ptrace|kptr",
|
|
615
|
+
"any matched_cve.vector matches 'userns|bpf|ptrace|kptr'",
|
|
616
616
|
"ops_authorization_for_sysctl_changes == true"
|
|
617
617
|
],
|
|
618
618
|
"priority": 3,
|
|
@@ -627,7 +627,7 @@
|
|
|
627
627
|
"id": "policy-exception",
|
|
628
628
|
"description": "Generate an auditor-ready policy exception via policy-exception-gen documenting that all faster remediation paths are blocked, with compensating controls and time-bound risk acceptance.",
|
|
629
629
|
"preconditions": [
|
|
630
|
-
"
|
|
630
|
+
"prior_remediations_blocked == true",
|
|
631
631
|
"ciso_acceptance_obtainable == true"
|
|
632
632
|
],
|
|
633
633
|
"priority": 4,
|
|
@@ -1389,7 +1389,7 @@
|
|
|
1389
1389
|
"id": "policy-exception",
|
|
1390
1390
|
"description": "Where a publisher-posture gap cannot be remediated within the compliance window — typical case: API stability promise prevents removing a deprecated transitive dep before next major version; OR registry doesn't yet support Trusted Publisher; OR a Class II conformity assessment is in progress — generate an auditor-ready policy exception via policy-exception-gen with compensating controls and time-bound sunset date.",
|
|
1391
1391
|
"preconditions": [
|
|
1392
|
-
"
|
|
1392
|
+
"prior_remediations_blocked == true",
|
|
1393
1393
|
"ciso_or_product_owner_acceptance_obtainable == true"
|
|
1394
1394
|
],
|
|
1395
1395
|
"priority": 10,
|
|
@@ -725,7 +725,7 @@
|
|
|
725
725
|
"id": "policy-exception",
|
|
726
726
|
"description": "Generate auditor-ready policy exception when faster paths are blocked.",
|
|
727
727
|
"preconditions": [
|
|
728
|
-
"
|
|
728
|
+
"prior_remediations_blocked == true",
|
|
729
729
|
"ciso_acceptance_obtainable == true"
|
|
730
730
|
],
|
|
731
731
|
"priority": 5,
|
|
@@ -430,11 +430,11 @@
|
|
|
430
430
|
],
|
|
431
431
|
"escalation_criteria": [
|
|
432
432
|
{
|
|
433
|
-
"condition": "
|
|
433
|
+
"condition": "secrets-or-pii-logged-without-redaction == true OR webhook-log-sink-ssrf-unguarded == true",
|
|
434
434
|
"action": "raise_severity"
|
|
435
435
|
},
|
|
436
436
|
{
|
|
437
|
-
"condition": "
|
|
437
|
+
"condition": "crlf-log-injection-unsanitized == true",
|
|
438
438
|
"action": "trigger_playbook"
|
|
439
439
|
}
|
|
440
440
|
]
|
|
@@ -445,7 +445,7 @@
|
|
|
445
445
|
"id": "neutralize-and-redact",
|
|
446
446
|
"description": "Neutralize CR/LF + control characters in interpolated values on every sink (or move to a structured-only format), and run a redaction pass that strips secrets/PII before any sink.",
|
|
447
447
|
"preconditions": [
|
|
448
|
-
"
|
|
448
|
+
"operator_controls_logging_path == true"
|
|
449
449
|
],
|
|
450
450
|
"priority": 1,
|
|
451
451
|
"for_signals": [
|
|
@@ -508,11 +508,11 @@
|
|
|
508
508
|
],
|
|
509
509
|
"escalation_criteria": [
|
|
510
510
|
{
|
|
511
|
-
"condition": "
|
|
511
|
+
"condition": "smtp-smuggling-end-of-data-accepted == true OR inbound-open-relay == true",
|
|
512
512
|
"action": "raise_severity"
|
|
513
513
|
},
|
|
514
514
|
{
|
|
515
|
-
"condition": "
|
|
515
|
+
"condition": "sieve-redirect-uncapped == true",
|
|
516
516
|
"action": "trigger_playbook"
|
|
517
517
|
}
|
|
518
518
|
]
|
|
@@ -523,7 +523,7 @@
|
|
|
523
523
|
"id": "enforce-standard-end-of-data",
|
|
524
524
|
"description": "Reject non-standard end-of-data sequences on the inbound SMTP listener (and upgrade the MTA to the smuggling-fixed release); require canonical <CR><LF>.<CR><LF>.",
|
|
525
525
|
"preconditions": [
|
|
526
|
-
"
|
|
526
|
+
"operator_controls_inbound_mta == true"
|
|
527
527
|
],
|
|
528
528
|
"priority": 1,
|
|
529
529
|
"for_signals": [
|
package/data/playbooks/mcp.json
CHANGED
|
@@ -860,7 +860,7 @@
|
|
|
860
860
|
"action": "notify_legal"
|
|
861
861
|
},
|
|
862
862
|
{
|
|
863
|
-
"condition": "
|
|
863
|
+
"condition": "unsigned-mcp-manifest == true AND cloud-credentials-detected == true",
|
|
864
864
|
"action": "trigger_playbook",
|
|
865
865
|
"target_playbook": "ai-api"
|
|
866
866
|
}
|
|
@@ -925,7 +925,7 @@
|
|
|
925
925
|
"id": "policy-exception",
|
|
926
926
|
"description": "Generate auditor-ready policy exception via policy-exception-gen if a business-critical MCP server cannot meet signing / allowlist / integrity-pin requirements within compliance window.",
|
|
927
927
|
"preconditions": [
|
|
928
|
-
"
|
|
928
|
+
"prior_remediations_blocked == true",
|
|
929
929
|
"ciso_acceptance_obtainable == true"
|
|
930
930
|
],
|
|
931
931
|
"priority": 5,
|
|
@@ -467,11 +467,11 @@
|
|
|
467
467
|
],
|
|
468
468
|
"escalation_criteria": [
|
|
469
469
|
{
|
|
470
|
-
"condition": "
|
|
470
|
+
"condition": "tenant-id-trusted-from-client == true OR query-not-scoped-by-tenant == true OR row-policy-bypassable-by-role-context == true OR cross-tenant-cache-or-queue-key-collision == true",
|
|
471
471
|
"action": "raise_severity"
|
|
472
472
|
},
|
|
473
473
|
{
|
|
474
|
-
"condition": "
|
|
474
|
+
"condition": "http2-rapid-reset-uncapped == true OR no-per-tenant-rate-or-byte-quota == true OR unbounded-resource-allocation-per-request == true",
|
|
475
475
|
"action": "trigger_playbook"
|
|
476
476
|
}
|
|
477
477
|
]
|
|
@@ -482,7 +482,7 @@
|
|
|
482
482
|
"id": "bind-tenant-and-enforce-rls",
|
|
483
483
|
"description": "Derive the tenant id from the authenticated principal (never trust a client-supplied id), and enforce tenant scoping at the data layer via row-level security under a NON-bypass request role so a forgotten predicate cannot leak.",
|
|
484
484
|
"preconditions": [
|
|
485
|
-
"
|
|
485
|
+
"operator_controls_data_layer == true"
|
|
486
486
|
],
|
|
487
487
|
"priority": 1,
|
|
488
488
|
"for_signals": [
|
|
@@ -455,11 +455,11 @@
|
|
|
455
455
|
],
|
|
456
456
|
"escalation_criteria": [
|
|
457
457
|
{
|
|
458
|
-
"condition": "
|
|
458
|
+
"condition": "dnssec-validation-not-enforced == true AND (dane-tlsa-not-checked == true OR mtls-ca-not-pinned == true)",
|
|
459
459
|
"action": "raise_severity"
|
|
460
460
|
},
|
|
461
461
|
{
|
|
462
|
-
"condition": "
|
|
462
|
+
"condition": "unauthenticated-ntp-no-nts == true",
|
|
463
463
|
"action": "trigger_playbook"
|
|
464
464
|
}
|
|
465
465
|
]
|
|
@@ -470,7 +470,7 @@
|
|
|
470
470
|
"id": "enforce-dnssec-and-rebinding-guard",
|
|
471
471
|
"description": "Validate DNSSEC end-to-end (or trust a validating upstream over DoT/DoH), prefer signed answers, and pin the resolved IP for the connection lifetime while refusing private/link-local/metadata addresses.",
|
|
472
472
|
"preconditions": [
|
|
473
|
-
"
|
|
473
|
+
"operator_controls_resolver_path == true"
|
|
474
474
|
],
|
|
475
475
|
"priority": 1,
|
|
476
476
|
"for_signals": [
|
|
@@ -939,7 +939,7 @@
|
|
|
939
939
|
"id": "policy-exception",
|
|
940
940
|
"description": "For any asset that cannot reach hybrid PQC posture within the migration cycle: generate auditor-ready policy exception with crypto-agility roadmap + compensating controls + time-bound risk acceptance + alternative-vendor or end-of-life plan.",
|
|
941
941
|
"preconditions": [
|
|
942
|
-
"
|
|
942
|
+
"prior_remediations_blocked == true",
|
|
943
943
|
"ciso_acceptance_obtainable == true"
|
|
944
944
|
],
|
|
945
945
|
"priority": 7,
|
|
@@ -422,11 +422,11 @@
|
|
|
422
422
|
],
|
|
423
423
|
"escalation_criteria": [
|
|
424
424
|
{
|
|
425
|
-
"condition": "
|
|
425
|
+
"condition": "sanctions-screening-homoglyph-evasion == true OR sanctions-screening-alias-transliteration-gap == true",
|
|
426
426
|
"action": "raise_severity"
|
|
427
427
|
},
|
|
428
428
|
{
|
|
429
|
-
"condition": "
|
|
429
|
+
"condition": "dsr-erasure-no-completion-proof == true",
|
|
430
430
|
"action": "trigger_playbook"
|
|
431
431
|
}
|
|
432
432
|
]
|
|
@@ -437,7 +437,7 @@
|
|
|
437
437
|
"id": "normalize-and-fuzzy-screen",
|
|
438
438
|
"description": "Normalize names to a canonical confusable-folded skeleton (NFKC + Unicode confusable folding via the vendored codepoint-class) and apply the list's aliases + transliteration + bounded edit-distance fuzzy match before deciding.",
|
|
439
439
|
"preconditions": [
|
|
440
|
-
"
|
|
440
|
+
"operator_performs_sanctions_screening == true"
|
|
441
441
|
],
|
|
442
442
|
"priority": 1,
|
|
443
443
|
"for_signals": [
|
|
@@ -665,7 +665,7 @@
|
|
|
665
665
|
"target_playbook": "cred-stores"
|
|
666
666
|
},
|
|
667
667
|
{
|
|
668
|
-
"condition": "orphan-privileged-process
|
|
668
|
+
"condition": "orphan-privileged-process == true OR duplicate-uid-zero == true",
|
|
669
669
|
"action": "trigger_playbook",
|
|
670
670
|
"target_playbook": "kernel"
|
|
671
671
|
},
|
|
@@ -740,7 +740,7 @@
|
|
|
740
740
|
"id": "policy-exception",
|
|
741
741
|
"description": "If a finding cannot be remediated within the compliance window, generate an auditor-ready exception with bounded compensating controls.",
|
|
742
742
|
"preconditions": [
|
|
743
|
-
"
|
|
743
|
+
"prior_remediations_blocked == true OR time_to_remediate > obligation_window"
|
|
744
744
|
],
|
|
745
745
|
"priority": 4,
|
|
746
746
|
"compensating_controls": [
|
package/data/playbooks/sbom.json
CHANGED
|
@@ -1367,7 +1367,7 @@
|
|
|
1367
1367
|
"id": "policy-exception",
|
|
1368
1368
|
"description": "Where a matched CVE cannot be remediated within compliance window (vendor pending, blocker dependency, architectural impossibility): generate auditor-ready policy exception via policy-exception-gen.",
|
|
1369
1369
|
"preconditions": [
|
|
1370
|
-
"
|
|
1370
|
+
"prior_remediations_blocked == true",
|
|
1371
1371
|
"ciso_acceptance_obtainable == true"
|
|
1372
1372
|
],
|
|
1373
1373
|
"priority": 8,
|
|
@@ -779,7 +779,7 @@
|
|
|
779
779
|
"id": "fix-file-permissions",
|
|
780
780
|
"description": "For world-writable .env / .ssh / auth-config files: chmod 0600 (private keys) or 0640 (env files). For SSH key with bad perms: chmod 0600 and re-load via ssh-add.",
|
|
781
781
|
"preconditions": [
|
|
782
|
-
"file_owner_is_current_user OR has_sudo == true"
|
|
782
|
+
"file_owner_is_current_user == true OR has_sudo == true"
|
|
783
783
|
],
|
|
784
784
|
"priority": 2,
|
|
785
785
|
"for_signals": [
|
|
@@ -444,11 +444,11 @@
|
|
|
444
444
|
],
|
|
445
445
|
"escalation_criteria": [
|
|
446
446
|
{
|
|
447
|
-
"condition": "
|
|
447
|
+
"condition": "self-update-no-signature-verification == true OR self-update-key-not-pinned == true",
|
|
448
448
|
"action": "raise_severity"
|
|
449
449
|
},
|
|
450
450
|
{
|
|
451
|
-
"condition": "
|
|
451
|
+
"condition": "update-applied-without-verifier-gate == true",
|
|
452
452
|
"action": "trigger_playbook"
|
|
453
453
|
}
|
|
454
454
|
]
|
|
@@ -459,7 +459,7 @@
|
|
|
459
459
|
"id": "verify-signature-before-apply",
|
|
460
460
|
"description": "Verify an artifact signature against an out-of-band-pinned root key BEFORE swapping the update in, and fail closed on any verification error — never trust a server-provided hash alone.",
|
|
461
461
|
"preconditions": [
|
|
462
|
-
"
|
|
462
|
+
"operator_controls_update_client == true"
|
|
463
463
|
],
|
|
464
464
|
"priority": 1,
|
|
465
465
|
"for_signals": [
|
|
@@ -874,7 +874,7 @@
|
|
|
874
874
|
"target_playbook": "mcp"
|
|
875
875
|
},
|
|
876
876
|
{
|
|
877
|
-
"condition": "
|
|
877
|
+
"condition": "credential-class-exfil-includes-sso-admin == true",
|
|
878
878
|
"action": "trigger_playbook",
|
|
879
879
|
"target_playbook": "idp-incident"
|
|
880
880
|
},
|
|
@@ -995,7 +995,7 @@
|
|
|
995
995
|
"id": "policy-exception",
|
|
996
996
|
"description": "For recovery primitives that cannot be completed within the jurisdiction's window: generate auditor-ready policy exception with compensating controls, time-bound risk acceptance, and remediation milestones. Typical blockers: legacy host without re-imaging window, vendor refuses to rotate a shared maintainer credential, downstream-consumer notification depends on third-party advisory pipeline outside operator control.",
|
|
997
997
|
"preconditions": [
|
|
998
|
-
"
|
|
998
|
+
"prior_remediations_blocked == true",
|
|
999
999
|
"ciso_acceptance_obtainable == true"
|
|
1000
1000
|
],
|
|
1001
1001
|
"priority": 7,
|
|
@@ -528,11 +528,11 @@
|
|
|
528
528
|
],
|
|
529
529
|
"escalation_criteria": [
|
|
530
530
|
{
|
|
531
|
-
"condition": "
|
|
531
|
+
"condition": "issuer-key-not-pinned-to-trust-anchor == true OR presentation-no-nonce-audience-binding == true",
|
|
532
532
|
"action": "raise_severity"
|
|
533
533
|
},
|
|
534
534
|
{
|
|
535
|
-
"condition": "
|
|
535
|
+
"condition": "credential-revocation-status-not-checked == true",
|
|
536
536
|
"action": "trigger_playbook"
|
|
537
537
|
}
|
|
538
538
|
]
|
|
@@ -543,7 +543,7 @@
|
|
|
543
543
|
"id": "pin-issuer-trust-anchors",
|
|
544
544
|
"description": "Replace open issuerKeyResolver acceptance with an issuer allowlist / x5c-or-federation chain validated to a configured trust anchor; reject issuer keys that do not chain to it.",
|
|
545
545
|
"preconditions": [
|
|
546
|
-
"
|
|
546
|
+
"verifier_controls_trusted_issuers == true"
|
|
547
547
|
],
|
|
548
548
|
"priority": 1,
|
|
549
549
|
"for_signals": [
|
|
@@ -557,7 +557,7 @@
|
|
|
557
557
|
"id": "enforce-revocation-on-accept",
|
|
558
558
|
"description": "Resolve the status_list on the accept path and reject on a set status bit; treat a status fetch failure as fail-closed (not \"valid\").",
|
|
559
559
|
"preconditions": [
|
|
560
|
-
"
|
|
560
|
+
"credentials_carry_status_mechanism == true"
|
|
561
561
|
],
|
|
562
562
|
"priority": 1,
|
|
563
563
|
"for_signals": [
|
|
@@ -568,7 +568,7 @@
|
|
|
568
568
|
"id": "bind-presentations-to-nonce-audience",
|
|
569
569
|
"description": "Issue a fresh per-request nonce, require a Key-Binding JWT echoing that nonce + the verifier audience, and verify device-auth for mdoc; reject unbound presentations.",
|
|
570
570
|
"preconditions": [
|
|
571
|
-
"
|
|
571
|
+
"verifier_controls_request_challenge == true"
|
|
572
572
|
],
|
|
573
573
|
"priority": 1,
|
|
574
574
|
"for_signals": [
|
|
@@ -694,7 +694,7 @@
|
|
|
694
694
|
"id": "policy-exception",
|
|
695
695
|
"description": "Generate an auditor-ready policy exception when faster paths are blocked (legacy receiver cannot be patched within window, provider does not offer state-parameter enforcement, etc.) with compensating controls and time-bound risk acceptance.",
|
|
696
696
|
"preconditions": [
|
|
697
|
-
"
|
|
697
|
+
"prior_remediations_blocked == true",
|
|
698
698
|
"ciso_acceptance_obtainable == true"
|
|
699
699
|
],
|
|
700
700
|
"priority": 4,
|