@blamejs/exceptd-skills 0.10.0 → 0.10.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -9,11 +9,17 @@
9
9
  "version": "1.0.0",
10
10
  "date": "2026-05-11",
11
11
  "summary": "Initial seven-phase runtime inventory playbook. Walks listening sockets, sudo rules, SUID/SGID binaries, cron/systemd timers, and process tree on a live Linux host. Cross-references findings against ATLAS T1078/T1543/T1546/T1574 lineage and the catalogued kernel LPE chain. Designed as the live-host corroborator of the kernel playbook — kernel.json answers 'is the running kernel vulnerable?', runtime.json answers 'and what is the attacker actually going to find when they land here?'.",
12
- "framework_gaps_updated": ["nist-800-53-CM-7", "nist-800-53-AC-6", "iso-27001-2022-A.8.2", "nis2-art21-2d"]
12
+ "framework_gaps_updated": [
13
+ "nist-800-53-CM-7",
14
+ "nist-800-53-AC-6",
15
+ "iso-27001-2022-A.8.2",
16
+ "nis2-art21-2d"
17
+ ]
13
18
  }
14
19
  ],
15
20
  "owner": "@blamejs/platform-security",
16
21
  "air_gap_mode": false,
22
+ "scope": "system",
17
23
  "preconditions": [
18
24
  {
19
25
  "id": "linux-platform",
@@ -50,24 +56,44 @@
50
56
  }
51
57
  ]
52
58
  },
53
-
54
59
  "domain": {
55
60
  "name": "Linux runtime attack-surface inventory",
56
61
  "attack_class": "kernel-lpe",
57
62
  "atlas_refs": [],
58
- "attack_refs": ["T1078", "T1543", "T1546", "T1574", "T1068", "T1548.003"],
63
+ "attack_refs": [
64
+ "T1078",
65
+ "T1543",
66
+ "T1546",
67
+ "T1574",
68
+ "T1068",
69
+ "T1548.003"
70
+ ],
59
71
  "cve_refs": [],
60
- "cwe_refs": ["CWE-269", "CWE-732", "CWE-250", "CWE-426"],
61
- "d3fend_refs": ["D3-PA", "D3-SCA", "D3-SFA"],
72
+ "cwe_refs": [
73
+ "CWE-269",
74
+ "CWE-732",
75
+ "CWE-250",
76
+ "CWE-426"
77
+ ],
78
+ "d3fend_refs": [
79
+ "D3-PA",
80
+ "D3-SCA",
81
+ "D3-SFA"
82
+ ],
62
83
  "frameworks_in_scope": [
63
- "nist-800-53", "nist-csf-2", "iso-27001-2022",
64
- "soc2", "pci-dss-4", "nis2", "dora",
65
- "uk-caf", "au-ism", "au-essential-8"
84
+ "nist-800-53",
85
+ "nist-csf-2",
86
+ "iso-27001-2022",
87
+ "soc2",
88
+ "pci-dss-4",
89
+ "nis2",
90
+ "dora",
91
+ "uk-caf",
92
+ "au-ism",
93
+ "au-essential-8"
66
94
  ]
67
95
  },
68
-
69
96
  "phases": {
70
-
71
97
  "govern": {
72
98
  "jurisdiction_obligations": [
73
99
  {
@@ -76,7 +102,11 @@
76
102
  "obligation": "notify_regulator",
77
103
  "window_hours": 24,
78
104
  "clock_starts": "detect_confirmed",
79
- "evidence_required": ["affected_host_inventory", "lateral_movement_path_assessment", "interim_mitigation_record"]
105
+ "evidence_required": [
106
+ "affected_host_inventory",
107
+ "lateral_movement_path_assessment",
108
+ "interim_mitigation_record"
109
+ ]
80
110
  },
81
111
  {
82
112
  "jurisdiction": "EU",
@@ -84,7 +114,10 @@
84
114
  "obligation": "notify_regulator",
85
115
  "window_hours": 4,
86
116
  "clock_starts": "detect_confirmed",
87
- "evidence_required": ["initial_notification", "ict_third_party_dependencies"]
117
+ "evidence_required": [
118
+ "initial_notification",
119
+ "ict_third_party_dependencies"
120
+ ]
88
121
  },
89
122
  {
90
123
  "jurisdiction": "AU",
@@ -92,7 +125,10 @@
92
125
  "obligation": "notify_regulator",
93
126
  "window_hours": 72,
94
127
  "clock_starts": "validate_complete",
95
- "evidence_required": ["materiality_assessment", "remediation_completed_evidence"]
128
+ "evidence_required": [
129
+ "materiality_assessment",
130
+ "remediation_completed_evidence"
131
+ ]
96
132
  }
97
133
  ],
98
134
  "theater_fingerprints": [
@@ -100,19 +136,29 @@
100
136
  "pattern_id": "least-privilege-as-paper-policy",
101
137
  "claim": "Org has a documented least-privilege policy → AC-6 / A.8.2 satisfied.",
102
138
  "fast_detection_test": "Run `sudo -l -n` on a sample of service accounts and `find / -perm -4000 -user root` on representative production hosts. Count SUID binaries that exist beyond the distro baseline AND count sudoers entries with NOPASSWD wildcards. Any non-zero result with a 'least privilege' attestation is theater.",
103
- "implicated_controls": ["nist-800-53-AC-6", "iso-27001-2022-A.8.2", "nis2-art21-2i"]
139
+ "implicated_controls": [
140
+ "nist-800-53-AC-6",
141
+ "iso-27001-2022-A.8.2",
142
+ "nis2-art21-2i"
143
+ ]
104
144
  },
105
145
  {
106
146
  "pattern_id": "edr-as-runtime-visibility",
107
147
  "claim": "We have EDR deployed → runtime attack surface is monitored (CM-7, A.8.2).",
108
148
  "fast_detection_test": "Ask the EDR vendor for a single SUID-creation alert from the last 90 days. Ask for a single sudoers-modification alert. Most EDRs do not alert on the static attack surface — they alert on execution. Static-surface theater.",
109
- "implicated_controls": ["nist-800-53-CM-7", "iso-27001-2022-A.8.7"]
149
+ "implicated_controls": [
150
+ "nist-800-53-CM-7",
151
+ "iso-27001-2022-A.8.7"
152
+ ]
110
153
  },
111
154
  {
112
155
  "pattern_id": "cron-as-someone-elses-problem",
113
156
  "claim": "Scheduled jobs are reviewed quarterly per change-management policy.",
114
157
  "fast_detection_test": "Diff the current /etc/cron.d + /etc/systemd/system/*.timer inventory against the last quarterly review record. Any new entry not in the review = drift. If the org cannot produce the quarterly review file, that is itself the theater verdict.",
115
- "implicated_controls": ["nist-800-53-CM-3", "iso-27001-2022-A.8.32"]
158
+ "implicated_controls": [
159
+ "nist-800-53-CM-3",
160
+ "iso-27001-2022-A.8.32"
161
+ ]
116
162
  }
117
163
  ],
118
164
  "framework_context": {
@@ -145,9 +191,15 @@
145
191
  }
146
192
  ]
147
193
  },
148
- "skill_preload": ["kernel-lpe-triage", "attack-surface-pentest", "incident-response-playbook", "framework-gap-analysis", "compliance-theater", "policy-exception-gen"]
194
+ "skill_preload": [
195
+ "kernel-lpe-triage",
196
+ "attack-surface-pentest",
197
+ "incident-response-playbook",
198
+ "framework-gap-analysis",
199
+ "compliance-theater",
200
+ "policy-exception-gen"
201
+ ]
149
202
  },
150
-
151
203
  "direct": {
152
204
  "threat_context": "Post-foothold reconnaissance is the highest-signal attacker behavior of 2025-2026. Confirmed in IR engagements: attackers who establish initial access (phishing, vuln chain, supply chain) execute a standard enumeration sweep within 60-180 seconds — listening sockets, sudo rules, SUID binaries, cron/systemd timers, process tree — to identify the privilege-escalation path. CVE-2026-31431 'Copy Fail' (KEV, 2026-03-15) and the unprivileged-userns LPE class are not exploitable in isolation; they are chained to runtime primitives this playbook inventories. ATLAS T1078 (Valid Accounts) and ATT&CK T1543 (Create or Modify System Process), T1546 (Event Triggered Execution), T1574 (Hijack Execution Flow) are the named persistence primitives an attacker plants once they have a foothold. Defenders who only patch CVEs without inventorying these primitives are patching the door while leaving the windows open.",
153
205
  "rwep_threshold": {
@@ -157,12 +209,38 @@
157
209
  },
158
210
  "framework_lag_declaration": "NIST CM-7 + AC-6, ISO A.8.2 + A.8.18, and NIS2 Art.21(2)(i) treat least-privilege and least-functionality as policy outcomes reviewable annually. They do not require programmatic enumeration of the specific primitives (sudoers NOPASSWD, non-baseline SUID, world-writable cron, host-mounted systemd services, listening sockets on non-loopback) that attackers use to convert foothold into root. A host can be CM-7/AC-6 compliant on paper while presenting dozens of LPE primitives to a landed attacker. Gap = ~21 days between drift and policy review at typical orgs; for fast-moving environments (containerized + GitOps-deployed), drift accumulates faster than annual review can catch.",
159
211
  "skill_chain": [
160
- { "skill": "attack-surface-pentest", "purpose": "Enumerate listening sockets, sudo rules, SUID/SGID binaries, cron/timer entries, process tree. Map each to ATT&CK persistence/PrivEsc TTPs.", "required": true },
161
- { "skill": "kernel-lpe-triage", "purpose": "Cross-reference enumerated primitives with the kernel LPE catalog to identify which primitives the running kernel could weaponize.", "required": true },
162
- { "skill": "incident-response-playbook", "purpose": "If any deterministic finding (rogue cron, attacker-shaped SUID, unknown systemd timer) fires, hand off to IR-playbook for containment + chain-of-custody.", "skip_if": "detect.indicators.fired.deterministic == false", "required": false },
163
- { "skill": "framework-gap-analysis", "purpose": "Map each finding to which framework control claims to cover it and where the gap is.", "required": true },
164
- { "skill": "compliance-theater", "purpose": "Run the theater test on the org's least-privilege/least-functionality attestation.", "required": true },
165
- { "skill": "policy-exception-gen", "purpose": "Generate auditor-ready exception language for primitives that cannot be removed within the compliance window.", "skip_if": "close.exception_generation.trigger_condition == false", "required": false }
212
+ {
213
+ "skill": "attack-surface-pentest",
214
+ "purpose": "Enumerate listening sockets, sudo rules, SUID/SGID binaries, cron/timer entries, process tree. Map each to ATT&CK persistence/PrivEsc TTPs.",
215
+ "required": true
216
+ },
217
+ {
218
+ "skill": "kernel-lpe-triage",
219
+ "purpose": "Cross-reference enumerated primitives with the kernel LPE catalog to identify which primitives the running kernel could weaponize.",
220
+ "required": true
221
+ },
222
+ {
223
+ "skill": "incident-response-playbook",
224
+ "purpose": "If any deterministic finding (rogue cron, attacker-shaped SUID, unknown systemd timer) fires, hand off to IR-playbook for containment + chain-of-custody.",
225
+ "skip_if": "detect.indicators.fired.deterministic == false",
226
+ "required": false
227
+ },
228
+ {
229
+ "skill": "framework-gap-analysis",
230
+ "purpose": "Map each finding to which framework control claims to cover it and where the gap is.",
231
+ "required": true
232
+ },
233
+ {
234
+ "skill": "compliance-theater",
235
+ "purpose": "Run the theater test on the org's least-privilege/least-functionality attestation.",
236
+ "required": true
237
+ },
238
+ {
239
+ "skill": "policy-exception-gen",
240
+ "purpose": "Generate auditor-ready exception language for primitives that cannot be removed within the compliance window.",
241
+ "skip_if": "close.exception_generation.trigger_condition == false",
242
+ "required": false
243
+ }
166
244
  ],
167
245
  "token_budget": {
168
246
  "estimated_total": 20000,
@@ -177,7 +255,6 @@
177
255
  }
178
256
  }
179
257
  },
180
-
181
258
  "look": {
182
259
  "artifacts": [
183
260
  {
@@ -287,16 +364,43 @@
287
364
  }
288
365
  ],
289
366
  "fallback_if_unavailable": [
290
- { "artifact_id": "listening-sockets", "fallback_action": "use_compensating_artifact", "confidence_impact": "low" },
291
- { "artifact_id": "sudo-rules", "fallback_action": "use_compensating_artifact", "confidence_impact": "medium" },
292
- { "artifact_id": "suid-binaries", "fallback_action": "use_compensating_artifact", "confidence_impact": "low" },
293
- { "artifact_id": "cron-entries", "fallback_action": "mark_inconclusive", "confidence_impact": "medium" },
294
- { "artifact_id": "systemd-timers", "fallback_action": "mark_inconclusive", "confidence_impact": "medium" },
295
- { "artifact_id": "process-tree", "fallback_action": "escalate_to_human", "confidence_impact": "high" },
296
- { "artifact_id": "passwd-shadow-baseline", "fallback_action": "escalate_to_human", "confidence_impact": "high" }
367
+ {
368
+ "artifact_id": "listening-sockets",
369
+ "fallback_action": "use_compensating_artifact",
370
+ "confidence_impact": "low"
371
+ },
372
+ {
373
+ "artifact_id": "sudo-rules",
374
+ "fallback_action": "use_compensating_artifact",
375
+ "confidence_impact": "medium"
376
+ },
377
+ {
378
+ "artifact_id": "suid-binaries",
379
+ "fallback_action": "use_compensating_artifact",
380
+ "confidence_impact": "low"
381
+ },
382
+ {
383
+ "artifact_id": "cron-entries",
384
+ "fallback_action": "mark_inconclusive",
385
+ "confidence_impact": "medium"
386
+ },
387
+ {
388
+ "artifact_id": "systemd-timers",
389
+ "fallback_action": "mark_inconclusive",
390
+ "confidence_impact": "medium"
391
+ },
392
+ {
393
+ "artifact_id": "process-tree",
394
+ "fallback_action": "escalate_to_human",
395
+ "confidence_impact": "high"
396
+ },
397
+ {
398
+ "artifact_id": "passwd-shadow-baseline",
399
+ "fallback_action": "escalate_to_human",
400
+ "confidence_impact": "high"
401
+ }
297
402
  ]
298
403
  },
299
-
300
404
  "detect": {
301
405
  "indicators": [
302
406
  {
@@ -391,26 +495,85 @@
391
495
  "not_detected": "All required artifacts captured AND no deterministic indicators fired AND no more than one high-confidence indicator with a confirmed benign distinguishing test."
392
496
  }
393
497
  },
394
-
395
498
  "analyze": {
396
499
  "rwep_inputs": [
397
- { "signal_id": "non-baseline-suid", "rwep_factor": "active_exploitation", "weight": 15, "notes": "If the SUID maps to a gtfobins-listed primitive, weaponization is one shell command away — full weight." },
398
- { "signal_id": "non-baseline-suid", "rwep_factor": "public_poc", "weight": 10, "notes": "Gtfobins itself is the public PoC corpus for the named SUID primitive." },
399
- { "signal_id": "sudoers-nopasswd-wildcard", "rwep_factor": "active_exploitation", "weight": 25, "notes": "NOPASSWD wildcard is direct privilege escalation; treat as exploitation-already-confirmed." },
400
- { "signal_id": "duplicate-uid-zero", "rwep_factor": "active_exploitation", "weight": 30, "notes": "Duplicate root account is post-compromise persistence — treat as incident-already-occurred." },
401
- { "signal_id": "listening-socket-unknown-bind", "rwep_factor": "blast_radius", "weight": 10, "notes": "Each externally-bound unknown listener adds to blast radius." },
402
- { "signal_id": "cron-or-timer-outside-policy", "rwep_factor": "active_exploitation", "weight": 20, "notes": "Unrecognized scheduled task with attacker-shape path (/tmp, /dev/shm) = persistence indicator." },
403
- { "signal_id": "world-writable-in-trusted-path", "rwep_factor": "ai_weaponization", "weight": 10, "notes": "AI-assisted attackers exploit these reliably; the primitive is trivial to find with grep." },
404
- { "signal_id": "orphan-privileged-process", "rwep_factor": "active_exploitation", "weight": 25, "notes": "Implant-shaped process running. Treat as IR trigger." }
500
+ {
501
+ "signal_id": "non-baseline-suid",
502
+ "rwep_factor": "active_exploitation",
503
+ "weight": 15,
504
+ "notes": "If the SUID maps to a gtfobins-listed primitive, weaponization is one shell command away full weight."
505
+ },
506
+ {
507
+ "signal_id": "non-baseline-suid",
508
+ "rwep_factor": "public_poc",
509
+ "weight": 10,
510
+ "notes": "Gtfobins itself is the public PoC corpus for the named SUID primitive."
511
+ },
512
+ {
513
+ "signal_id": "sudoers-nopasswd-wildcard",
514
+ "rwep_factor": "active_exploitation",
515
+ "weight": 25,
516
+ "notes": "NOPASSWD wildcard is direct privilege escalation; treat as exploitation-already-confirmed."
517
+ },
518
+ {
519
+ "signal_id": "duplicate-uid-zero",
520
+ "rwep_factor": "active_exploitation",
521
+ "weight": 30,
522
+ "notes": "Duplicate root account is post-compromise persistence — treat as incident-already-occurred."
523
+ },
524
+ {
525
+ "signal_id": "listening-socket-unknown-bind",
526
+ "rwep_factor": "blast_radius",
527
+ "weight": 10,
528
+ "notes": "Each externally-bound unknown listener adds to blast radius."
529
+ },
530
+ {
531
+ "signal_id": "cron-or-timer-outside-policy",
532
+ "rwep_factor": "active_exploitation",
533
+ "weight": 20,
534
+ "notes": "Unrecognized scheduled task with attacker-shape path (/tmp, /dev/shm) = persistence indicator."
535
+ },
536
+ {
537
+ "signal_id": "world-writable-in-trusted-path",
538
+ "rwep_factor": "ai_weaponization",
539
+ "weight": 10,
540
+ "notes": "AI-assisted attackers exploit these reliably; the primitive is trivial to find with grep."
541
+ },
542
+ {
543
+ "signal_id": "orphan-privileged-process",
544
+ "rwep_factor": "active_exploitation",
545
+ "weight": 25,
546
+ "notes": "Implant-shaped process running. Treat as IR trigger."
547
+ }
405
548
  ],
406
549
  "blast_radius_model": {
407
550
  "scope_question": "Given the inventoried runtime primitives, what is the realistic post-foothold pivot capability from this host?",
408
551
  "scoring_rubric": [
409
- { "condition": "No deterministic indicators fired AND no non-baseline SUID AND no NOPASSWD entries beyond bounded automation account", "blast_radius_score": 1, "description": "Foothold buys the attacker a non-privileged shell with no obvious LPE path. Must chain a kernel CVE or 0-day." },
410
- { "condition": "One non-baseline SUID OR one unknown external listener fired, on a single-tenant host", "blast_radius_score": 2, "description": "One credible LPE primitive present; lateral pivot still requires separate exploit chain." },
411
- { "condition": "NOPASSWD wildcard or non-baseline SUID present AND host mounts shared filesystems OR has SSH key agent forwarding", "blast_radius_score": 3, "description": "Root → credential/keystore theft → adjacent hosts." },
412
- { "condition": "Deterministic indicator fired AND host is k8s node OR runs Vault/SSM agent OR has cloud-IMDS access with privileged IAM", "blast_radius_score": 4, "description": "Root cluster admin or cloud account compromise via inventoried primitives alone, no kernel CVE chain needed." },
413
- { "condition": "Multiple deterministic indicators OR orphan-privileged-process fired AND host has cross-account trust OR runs identity-broker / bastion role", "blast_radius_score": 5, "description": "Active compromise already shaped on the host. Identity boundary collapse imminent or in progress." }
552
+ {
553
+ "condition": "No deterministic indicators fired AND no non-baseline SUID AND no NOPASSWD entries beyond bounded automation account",
554
+ "blast_radius_score": 1,
555
+ "description": "Foothold buys the attacker a non-privileged shell with no obvious LPE path. Must chain a kernel CVE or 0-day."
556
+ },
557
+ {
558
+ "condition": "One non-baseline SUID OR one unknown external listener fired, on a single-tenant host",
559
+ "blast_radius_score": 2,
560
+ "description": "One credible LPE primitive present; lateral pivot still requires separate exploit chain."
561
+ },
562
+ {
563
+ "condition": "NOPASSWD wildcard or non-baseline SUID present AND host mounts shared filesystems OR has SSH key agent forwarding",
564
+ "blast_radius_score": 3,
565
+ "description": "Root → credential/keystore theft → adjacent hosts."
566
+ },
567
+ {
568
+ "condition": "Deterministic indicator fired AND host is k8s node OR runs Vault/SSM agent OR has cloud-IMDS access with privileged IAM",
569
+ "blast_radius_score": 4,
570
+ "description": "Root → cluster admin or cloud account compromise via inventoried primitives alone, no kernel CVE chain needed."
571
+ },
572
+ {
573
+ "condition": "Multiple deterministic indicators OR orphan-privileged-process fired AND host has cross-account trust OR runs identity-broker / bastion role",
574
+ "blast_radius_score": 5,
575
+ "description": "Active compromise already shaped on the host. Identity boundary collapse imminent or in progress."
576
+ }
414
577
  ]
415
578
  },
416
579
  "compliance_theater_check": {
@@ -450,53 +613,94 @@
450
613
  }
451
614
  ],
452
615
  "escalation_criteria": [
453
- { "condition": "rwep >= 90 AND deterministic_indicator_fired == true", "action": "page_on_call" },
454
- { "condition": "blast_radius_score >= 4", "action": "trigger_playbook", "target_playbook": "cred-stores" },
455
- { "condition": "orphan-privileged-process fired OR duplicate-uid-zero fired", "action": "trigger_playbook", "target_playbook": "kernel" },
456
- { "condition": "compliance_theater_check.verdict == 'theater' AND jurisdiction_obligations contains 'EU'", "action": "notify_legal" }
616
+ {
617
+ "condition": "rwep >= 90 AND deterministic_indicator_fired == true",
618
+ "action": "page_on_call"
619
+ },
620
+ {
621
+ "condition": "blast_radius_score >= 4",
622
+ "action": "trigger_playbook",
623
+ "target_playbook": "cred-stores"
624
+ },
625
+ {
626
+ "condition": "orphan-privileged-process fired OR duplicate-uid-zero fired",
627
+ "action": "trigger_playbook",
628
+ "target_playbook": "kernel"
629
+ },
630
+ {
631
+ "condition": "compliance_theater_check.verdict == 'theater' AND jurisdiction_obligations contains 'EU'",
632
+ "action": "notify_legal"
633
+ }
457
634
  ]
458
635
  },
459
-
460
636
  "validate": {
461
637
  "remediation_paths": [
462
638
  {
463
639
  "id": "remove-non-baseline-suid",
464
640
  "description": "Strip SUID bit from non-baseline binaries that are not vendor-owned. Document the change; update /var/lib/exceptd/suid-baseline.txt.",
465
- "preconditions": ["non_baseline_suid_count > 0", "ops_authorization_for_chmod == true"],
641
+ "preconditions": [
642
+ "non_baseline_suid_count > 0",
643
+ "ops_authorization_for_chmod == true"
644
+ ],
466
645
  "priority": 1,
467
- "compensating_controls": ["suid-baseline-tracked", "edr-alerts-on-suid-creation"],
646
+ "compensating_controls": [
647
+ "suid-baseline-tracked",
648
+ "edr-alerts-on-suid-creation"
649
+ ],
468
650
  "estimated_time_hours": 1
469
651
  },
470
652
  {
471
653
  "id": "bound-sudo-nopasswd",
472
654
  "description": "Replace NOPASSWD: ALL or NOPASSWD: /path/* entries with bounded command-specific entries (NOPASSWD: /usr/bin/systemctl restart $servicename pattern).",
473
- "preconditions": ["sudoers_nopasswd_wildcard_count > 0", "automation_account_owner_authorization == true"],
655
+ "preconditions": [
656
+ "sudoers_nopasswd_wildcard_count > 0",
657
+ "automation_account_owner_authorization == true"
658
+ ],
474
659
  "priority": 1,
475
- "compensating_controls": ["sudoers-change-recorded", "automation-account-inventory-updated"],
660
+ "compensating_controls": [
661
+ "sudoers-change-recorded",
662
+ "automation-account-inventory-updated"
663
+ ],
476
664
  "estimated_time_hours": 2
477
665
  },
478
666
  {
479
667
  "id": "investigate-implant",
480
668
  "description": "Hand off to IR playbook for any finding matching implant shape (duplicate-uid-zero, orphan-privileged-process, cron-or-timer with attacker-path executable). Do not delete on the live host — preserve for forensics.",
481
- "preconditions": ["deterministic_implant_indicator_fired == true"],
669
+ "preconditions": [
670
+ "deterministic_implant_indicator_fired == true"
671
+ ],
482
672
  "priority": 1,
483
- "compensating_controls": ["host-isolated-from-network", "memory-snapshot-captured-pre-removal"],
673
+ "compensating_controls": [
674
+ "host-isolated-from-network",
675
+ "memory-snapshot-captured-pre-removal"
676
+ ],
484
677
  "estimated_time_hours": 8
485
678
  },
486
679
  {
487
680
  "id": "scope-listening-services",
488
681
  "description": "Re-bind unknown 0.0.0.0 listeners to loopback OR to a documented internal-only interface. Add to documented service inventory if intentional; uninstall if not.",
489
- "preconditions": ["unknown_external_listener_count > 0", "service_owner_identified == true"],
682
+ "preconditions": [
683
+ "unknown_external_listener_count > 0",
684
+ "service_owner_identified == true"
685
+ ],
490
686
  "priority": 2,
491
- "compensating_controls": ["host-firewall-rule-added", "service-inventory-updated"],
687
+ "compensating_controls": [
688
+ "host-firewall-rule-added",
689
+ "service-inventory-updated"
690
+ ],
492
691
  "estimated_time_hours": 2
493
692
  },
494
693
  {
495
694
  "id": "policy-exception",
496
695
  "description": "If a finding cannot be remediated within the compliance window, generate an auditor-ready exception with bounded compensating controls.",
497
- "preconditions": ["remediation_paths[1..4] blocked OR time_to_remediate > obligation_window"],
696
+ "preconditions": [
697
+ "remediation_paths[1..4] blocked OR time_to_remediate > obligation_window"
698
+ ],
498
699
  "priority": 4,
499
- "compensating_controls": ["enhanced-edr-monitoring-on-affected-paths", "monthly-residual-risk-review"],
700
+ "compensating_controls": [
701
+ "enhanced-edr-monitoring-on-affected-paths",
702
+ "monthly-residual-risk-review"
703
+ ],
500
704
  "estimated_time_hours": 8
501
705
  }
502
706
  ],
@@ -542,46 +746,84 @@
542
746
  "risk": "Even after remediation, the runtime attack surface accumulates drift faster than scheduled review. Any non-routine deploy can introduce a non-baseline SUID, an unintended NOPASSWD entry, or a new listener that the inventory misses until the next cadence run.",
543
747
  "why_remains": "Drift is structural: every package install, ops automation change, or developer ad-hoc fix can change the surface. The compensating control is cadence + EDR + change-management discipline, not absence of drift.",
544
748
  "acceptance_level": "manager",
545
- "compensating_controls_in_place": ["quarterly-runtime-inventory", "edr-suid-creation-alerting", "change-management-on-sudoers", "documented-service-inventory"]
749
+ "compensating_controls_in_place": [
750
+ "quarterly-runtime-inventory",
751
+ "edr-suid-creation-alerting",
752
+ "change-management-on-sudoers",
753
+ "documented-service-inventory"
754
+ ]
546
755
  },
547
756
  "evidence_requirements": [
548
757
  {
549
758
  "evidence_type": "scan_report",
550
759
  "description": "Full inventory output (listeners, sudo rules, SUID list, cron/timer list, process tree, world-writable list) with timestamps and host identity.",
551
760
  "retention_period": "1_year",
552
- "framework_satisfied": ["nist-800-53-CM-7", "nist-800-53-AC-6", "iso-27001-2022-A.8.2"]
761
+ "framework_satisfied": [
762
+ "nist-800-53-CM-7",
763
+ "nist-800-53-AC-6",
764
+ "iso-27001-2022-A.8.2"
765
+ ]
553
766
  },
554
767
  {
555
768
  "evidence_type": "config_diff",
556
769
  "description": "Diff of /etc/sudoers + /etc/sudoers.d/* before and after remediation; SUID baseline before and after.",
557
770
  "retention_period": "7_years",
558
- "framework_satisfied": ["nist-800-53-CM-3", "iso-27001-2022-A.8.32"]
771
+ "framework_satisfied": [
772
+ "nist-800-53-CM-3",
773
+ "iso-27001-2022-A.8.32"
774
+ ]
559
775
  },
560
776
  {
561
777
  "evidence_type": "ticket_reference",
562
778
  "description": "Change-management ticket references for each sudoers / SUID / listener modification, with approver and approval timestamp.",
563
779
  "retention_period": "7_years",
564
- "framework_satisfied": ["soc2-cc8.1", "iso-27001-2022-A.8.32"]
780
+ "framework_satisfied": [
781
+ "soc2-cc8.1",
782
+ "iso-27001-2022-A.8.32"
783
+ ]
565
784
  },
566
785
  {
567
786
  "evidence_type": "attestation",
568
787
  "description": "Signed exceptd attestation: host identity, scan timestamp, indicator firing counts, RWEP at detection, RWEP post-remediation.",
569
788
  "retention_period": "7_years",
570
- "framework_satisfied": ["nist-800-53-CA-7", "iso-27001-2022-A.5.36", "nis2-art21-2c"]
789
+ "framework_satisfied": [
790
+ "nist-800-53-CA-7",
791
+ "iso-27001-2022-A.5.36",
792
+ "nis2-art21-2c"
793
+ ]
571
794
  }
572
795
  ],
573
796
  "regression_trigger": [
574
- { "condition": "post_major_deploy", "interval": "on_event" },
575
- { "condition": "monthly", "interval": "30d" },
576
- { "condition": "new_cve_in_class == true", "interval": "on_event" },
577
- { "condition": "ir_incident_on_host == true", "interval": "on_event" }
797
+ {
798
+ "condition": "post_major_deploy",
799
+ "interval": "on_event"
800
+ },
801
+ {
802
+ "condition": "monthly",
803
+ "interval": "30d"
804
+ },
805
+ {
806
+ "condition": "new_cve_in_class == true",
807
+ "interval": "on_event"
808
+ },
809
+ {
810
+ "condition": "ir_incident_on_host == true",
811
+ "interval": "on_event"
812
+ }
578
813
  ]
579
814
  },
580
-
581
815
  "close": {
582
816
  "evidence_package": {
583
817
  "bundle_format": "json",
584
- "contents": ["scan_report", "config_diff", "ticket_reference", "attestation", "framework_gap_mapping", "compliance_theater_verdict", "residual_risk_statement"],
818
+ "contents": [
819
+ "scan_report",
820
+ "config_diff",
821
+ "ticket_reference",
822
+ "attestation",
823
+ "framework_gap_mapping",
824
+ "compliance_theater_verdict",
825
+ "residual_risk_statement"
826
+ ],
585
827
  "destination": "local_only",
586
828
  "signed": true
587
829
  },
@@ -593,21 +835,33 @@
593
835
  "framework_gap": "NIST + ISO + NIS2 vulnerability + access-control frameworks do not name the persistence-vector inventory as required evidence. Frameworks lag the attacker's standard 60-180 second post-foothold enumeration by an entire annual review cycle.",
594
836
  "new_control_requirement": "Mandate quarterly programmatic enumeration of the runtime persistence surface (sudoers NOPASSWD, SUID baseline diff, listener vs service inventory, cron/timer vs scheduled-task register, UID 0 duplicates, world-writable trusted paths) with documented baseline + drift review."
595
837
  },
596
- "feeds_back_to_skills": ["attack-surface-pentest", "framework-gap-analysis", "compliance-theater", "incident-response-playbook"]
838
+ "feeds_back_to_skills": [
839
+ "attack-surface-pentest",
840
+ "framework-gap-analysis",
841
+ "compliance-theater",
842
+ "incident-response-playbook"
843
+ ]
597
844
  },
598
845
  "notification_actions": [
599
846
  {
600
847
  "obligation_ref": "EU/NIS2 Art.23 24h",
601
848
  "deadline": "computed_at_runtime",
602
849
  "recipient": "internal_legal",
603
- "evidence_attached": ["affected_host_inventory", "lateral_movement_path_assessment", "interim_mitigation_record"],
850
+ "evidence_attached": [
851
+ "affected_host_inventory",
852
+ "lateral_movement_path_assessment",
853
+ "interim_mitigation_record"
854
+ ],
604
855
  "draft_notification": "NIS2 Art.23 24-hour early-warning notification: Runtime attack-surface inventory on ${affected_host_count} host(s) revealed deterministic compromise indicators including ${indicator_summary}. Affected host(s) isolated pending IR. Interim mitigation: ${interim_mitigation}. Full assessment to follow within 72 hours per Art.23(4)."
605
856
  },
606
857
  {
607
858
  "obligation_ref": "EU/DORA Art.19 4h",
608
859
  "deadline": "computed_at_runtime",
609
860
  "recipient": "internal_legal",
610
- "evidence_attached": ["initial_notification", "ict_third_party_dependencies"],
861
+ "evidence_attached": [
862
+ "initial_notification",
863
+ "ict_third_party_dependencies"
864
+ ],
611
865
  "draft_notification": "DORA Art.19 initial notification: Major ICT-related incident — runtime compromise indicators detected on financial-entity host(s). Indicators: ${indicator_summary}. ICT third-party dependencies affected: ${ict_dependencies}. Full classification + impact assessment to follow within statutory windows."
612
866
  }
613
867
  ],
@@ -616,7 +870,12 @@
616
870
  "exception_template": {
617
871
  "scope": "Runtime primitives ${primitive_inventory} on ${affected_host_count} host(s); remediation paths 1-3 blocked or pending vendor coordination.",
618
872
  "duration": "until_vendor_patch",
619
- "compensating_controls": ["edr-monitoring-on-affected-primitive", "enhanced-audit-logging-on-affected-binary", "host-firewall-rule-added", "change-management-freeze-on-affected-paths"],
873
+ "compensating_controls": [
874
+ "edr-monitoring-on-affected-primitive",
875
+ "enhanced-audit-logging-on-affected-binary",
876
+ "host-firewall-rule-added",
877
+ "change-management-freeze-on-affected-paths"
878
+ ],
620
879
  "risk_acceptance_owner": "manager",
621
880
  "auditor_ready_language": "Pursuant to ${framework_id} ${control_id}, the organization documents a time-bound risk acceptance for runtime attack-surface primitive(s) ${primitive_inventory} on ${affected_host_count} host(s). Primitive class: ${primitive_class}. Compensating controls in place: ${compensating_controls}. Residual RWEP post-compensation: ${rwep_post_compensation}. Risk accepted by ${manager_name} on ${acceptance_date}. Time-bound until ${duration_expiry}. Detection coverage during the exception window is provided by ${detection_controls}. The exception will be re-evaluated on (a) vendor patch publication, (b) the listed expiry date, OR (c) a new exploitation indicator firing on the affected primitive — whichever is first."
622
881
  }
@@ -628,22 +887,27 @@
628
887
  }
629
888
  }
630
889
  },
631
-
632
890
  "directives": [
633
891
  {
634
892
  "id": "full-runtime-inventory",
635
893
  "title": "Full Linux runtime attack-surface inventory — listeners, sudo, SUID, cron/timers, process tree",
636
- "applies_to": { "always": true }
894
+ "applies_to": {
895
+ "always": true
896
+ }
637
897
  },
638
898
  {
639
899
  "id": "post-foothold-imitation",
640
900
  "title": "Targeted directive — run the attacker's standard 60-180s post-foothold enumeration sweep",
641
- "applies_to": { "attack_technique": "T1078" }
901
+ "applies_to": {
902
+ "attack_technique": "T1078"
903
+ }
642
904
  },
643
905
  {
644
906
  "id": "persistence-surface",
645
907
  "title": "Persistence-vector inventory — cron/systemd timer + sudoers + UID 0 duplicates",
646
- "applies_to": { "attack_technique": "T1543" }
908
+ "applies_to": {
909
+ "attack_technique": "T1543"
910
+ }
647
911
  }
648
912
  ]
649
913
  }