@blamejs/exceptd-skills 0.9.5 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +45 -0
- package/CHANGELOG.md +66 -0
- package/README.md +30 -5
- package/bin/exceptd.js +400 -1
- package/data/_indexes/_meta.json +2 -2
- package/data/playbooks/ai-api.json +763 -0
- package/data/playbooks/containers.json +766 -0
- package/data/playbooks/cred-stores.json +715 -0
- package/data/playbooks/crypto.json +726 -0
- package/data/playbooks/framework.json +725 -0
- package/data/playbooks/hardening.json +672 -0
- package/data/playbooks/kernel.json +549 -0
- package/data/playbooks/mcp.json +727 -0
- package/data/playbooks/runtime.json +649 -0
- package/data/playbooks/sbom.json +893 -0
- package/data/playbooks/secrets.json +690 -0
- package/lib/cross-ref-api.js +224 -0
- package/lib/playbook-runner.js +826 -0
- package/lib/schemas/playbook.schema.json +652 -0
- package/manifest-snapshot.json +1 -1
- package/manifest.json +39 -39
- package/orchestrator/scanner.js +23 -1
- package/package.json +1 -1
- package/sbom.cdx.json +6 -6
|
@@ -0,0 +1,672 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_meta": {
|
|
3
|
+
"id": "hardening",
|
|
4
|
+
"version": "1.0.0",
|
|
5
|
+
"last_threat_review": "2026-05-11",
|
|
6
|
+
"threat_currency_score": 95,
|
|
7
|
+
"changelog": [
|
|
8
|
+
{
|
|
9
|
+
"version": "1.0.0",
|
|
10
|
+
"date": "2026-05-11",
|
|
11
|
+
"summary": "Initial seven-phase Linux hardening posture playbook. Inventories kernel hardening flags (/proc/sys/kernel/*, /proc/cmdline), CPU mitigation status (/sys/devices/system/cpu/vulnerabilities), sysctl posture, sshd_config, sudoers structure, PAM stack, and MAC posture (SELinux/AppArmor). This is the posture corroborator that the kernel playbook references — kernel.json answers 'is the running kernel in a vulnerable affected_versions range?', hardening.json answers 'and even if it is, do the hardening flags actually permit the exploit's primitive?'.",
|
|
12
|
+
"framework_gaps_updated": ["nist-800-53-CM-6", "nist-800-53-CM-7", "iso-27001-2022-A.8.9", "cmmc-cm-l2-3.4.2", "au-essential-8-application-hardening"]
|
|
13
|
+
}
|
|
14
|
+
],
|
|
15
|
+
"owner": "@blamejs/platform-security",
|
|
16
|
+
"air_gap_mode": false,
|
|
17
|
+
"preconditions": [
|
|
18
|
+
{
|
|
19
|
+
"id": "linux-platform",
|
|
20
|
+
"description": "Hardening flags inventoried here are Linux-specific (/proc/sys/kernel/*, SELinux/AppArmor). macOS/Windows hosts skip with platform-unsupported.",
|
|
21
|
+
"check": "host.platform == 'linux'",
|
|
22
|
+
"on_fail": "halt"
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
"id": "proc-readable",
|
|
26
|
+
"description": "Agent must have read access to /proc and /sys. Hardened containers with masked /proc cannot be evaluated; defer to container playbook.",
|
|
27
|
+
"check": "agent_can_read('/proc/sys/kernel/kptr_restrict') == true",
|
|
28
|
+
"on_fail": "warn"
|
|
29
|
+
}
|
|
30
|
+
],
|
|
31
|
+
"mutex": [],
|
|
32
|
+
"feeds_into": [
|
|
33
|
+
{
|
|
34
|
+
"playbook_id": "kernel",
|
|
35
|
+
"condition": "always"
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"playbook_id": "runtime",
|
|
39
|
+
"condition": "finding.severity >= 'high'"
|
|
40
|
+
}
|
|
41
|
+
]
|
|
42
|
+
},
|
|
43
|
+
|
|
44
|
+
"domain": {
|
|
45
|
+
"name": "Linux kernel + system hardening posture",
|
|
46
|
+
"attack_class": "kernel-lpe",
|
|
47
|
+
"atlas_refs": [],
|
|
48
|
+
"attack_refs": ["T1068", "T1611", "T1556", "T1098"],
|
|
49
|
+
"cve_refs": ["CVE-2026-31431", "CVE-2026-43284", "CVE-2026-43500"],
|
|
50
|
+
"cwe_refs": ["CWE-732", "CWE-269", "CWE-426", "CWE-1188"],
|
|
51
|
+
"d3fend_refs": ["D3-KBPI", "D3-PA", "D3-EI"],
|
|
52
|
+
"frameworks_in_scope": [
|
|
53
|
+
"nist-800-53", "nist-csf-2", "iso-27001-2022",
|
|
54
|
+
"soc2", "pci-dss-4", "nis2", "dora",
|
|
55
|
+
"uk-caf", "au-ism", "au-essential-8", "cmmc"
|
|
56
|
+
]
|
|
57
|
+
},
|
|
58
|
+
|
|
59
|
+
"phases": {
|
|
60
|
+
|
|
61
|
+
"govern": {
|
|
62
|
+
"jurisdiction_obligations": [
|
|
63
|
+
{
|
|
64
|
+
"jurisdiction": "EU",
|
|
65
|
+
"regulation": "NIS2 Art.21",
|
|
66
|
+
"obligation": "patch_critical",
|
|
67
|
+
"window_hours": 720,
|
|
68
|
+
"clock_starts": "analyze_complete",
|
|
69
|
+
"evidence_required": ["hardening_baseline_documented", "drift_remediation_record"]
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
"jurisdiction": "AU",
|
|
73
|
+
"regulation": "Essential 8 Application Hardening",
|
|
74
|
+
"obligation": "patch_critical",
|
|
75
|
+
"window_hours": 720,
|
|
76
|
+
"clock_starts": "validate_complete",
|
|
77
|
+
"evidence_required": ["hardening_baseline_documented", "drift_remediation_record"]
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
"jurisdiction": "US",
|
|
81
|
+
"regulation": "CMMC 2.0 CM.L2-3.4.2",
|
|
82
|
+
"obligation": "patch_critical",
|
|
83
|
+
"window_hours": 720,
|
|
84
|
+
"clock_starts": "validate_complete",
|
|
85
|
+
"evidence_required": ["baseline_configuration_document", "ssp_section_update"]
|
|
86
|
+
}
|
|
87
|
+
],
|
|
88
|
+
"theater_fingerprints": [
|
|
89
|
+
{
|
|
90
|
+
"pattern_id": "cis-benchmark-as-state",
|
|
91
|
+
"claim": "We follow the CIS Benchmark for $distro → hardening complete.",
|
|
92
|
+
"fast_detection_test": "Run the CIS Benchmark scanner today and diff against the last attested benchmark run. Drift between attested run and today is the theater margin. If the org cannot produce a benchmark run within the last 90 days OR the diff shows > 5 controls regressed, the attestation is theater.",
|
|
93
|
+
"implicated_controls": ["nist-800-53-CM-6", "iso-27001-2022-A.8.9", "cmmc-cm-l2-3.4.1"]
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
"pattern_id": "selinux-permissive-as-enabled",
|
|
97
|
+
"claim": "SELinux is enabled.",
|
|
98
|
+
"fast_detection_test": "Run `getenforce`. 'Enforcing' is real; 'Permissive' is logs-only — the MAC policy is loaded but not blocking. Treat Permissive as the same posture as Disabled for blast-radius purposes; the audit attestation often does not distinguish.",
|
|
99
|
+
"implicated_controls": ["nist-800-53-AC-3", "iso-27001-2022-A.8.3"]
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
"pattern_id": "kptr-restrict-zero-with-kaslr-attested",
|
|
103
|
+
"claim": "KASLR is enabled, kernel address randomization mitigates kernel LPE primitives.",
|
|
104
|
+
"fast_detection_test": "Check `cat /proc/sys/kernel/kptr_restrict`. If 0, /proc/kallsyms is world-readable and KASLR is effectively defeated for any local attacker. KASLR-enabled with kptr_restrict=0 is the classic kernel-hardening theater shape.",
|
|
105
|
+
"implicated_controls": ["nist-800-53-SC-30", "iso-27001-2022-A.8.31"]
|
|
106
|
+
}
|
|
107
|
+
],
|
|
108
|
+
"framework_context": {
|
|
109
|
+
"gap_summary": "Hardening frameworks (CIS Benchmarks, DISA STIGs, NIST 800-53 CM-6, ISO 27001 A.8.9, Australian Essential 8 application hardening) treat baseline as a documented-target state. They do not require continuous diff against the live host. The actual attacker primitive — unprivileged userns + unprivileged BPF + KASLR-effectively-disabled (kptr_restrict=0) + SELinux Permissive — is each individually a single sysctl value that drifts on package install / kernel-parameter change / vendor RPM update. Frameworks attest to baseline at audit time; they do not attest between audits. Real-world: hardening drift between annual audits is the dominant kernel-LPE enabler.",
|
|
110
|
+
"lag_score": 21,
|
|
111
|
+
"per_framework_gaps": [
|
|
112
|
+
{
|
|
113
|
+
"framework": "nist-800-53",
|
|
114
|
+
"control_id": "CM-6",
|
|
115
|
+
"designed_for": "Configuration settings — baselines documented and deviations managed.",
|
|
116
|
+
"insufficient_because": "Requires baseline documentation and deviation management process; does not require continuous attestation. Permits long drift windows between formal reviews. Combined with infrequent audit cadence, drift between attested state and live state can exceed compliance windows."
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
"framework": "nist-800-53",
|
|
120
|
+
"control_id": "CM-7(5)",
|
|
121
|
+
"designed_for": "Whitelisting-style authorized software / functionality enforcement.",
|
|
122
|
+
"insufficient_because": "Names application-layer least functionality, not kernel-layer hardening flag enforcement. Does not contemplate sysctl drift as a CM-7 issue."
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
"framework": "iso-27001-2022",
|
|
126
|
+
"control_id": "A.8.9",
|
|
127
|
+
"designed_for": "Configuration management — secure configuration of systems including hardware and software.",
|
|
128
|
+
"insufficient_because": "Same as CM-6 — baseline + change management satisfies the auditor without requiring continuous attestation of the specific kernel hardening flags that determine LPE exploitability."
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
"framework": "au-essential-8",
|
|
132
|
+
"control_id": "Application Hardening / OS Hardening",
|
|
133
|
+
"designed_for": "Hardening application + OS with documented baseline.",
|
|
134
|
+
"insufficient_because": "Maturity Level 1-3 are progressive but each accepts attestation evidence at the time of assessment. No real-time drift requirement at any maturity level."
|
|
135
|
+
}
|
|
136
|
+
]
|
|
137
|
+
},
|
|
138
|
+
"skill_preload": ["kernel-lpe-triage", "security-maturity-tiers", "framework-gap-analysis", "compliance-theater", "policy-exception-gen"]
|
|
139
|
+
},
|
|
140
|
+
|
|
141
|
+
"direct": {
|
|
142
|
+
"threat_context": "Kernel LPE class of 2026 is exquisitely sensitive to hardening posture. CVE-2026-31431 'Copy Fail' (KEV 2026-03-15) requires unprivileged user namespaces to be enabled — `kernel.unprivileged_userns_clone = 1` is the gating flag. Distros differ on the default: Debian 12 ships it 0, Ubuntu 24.04 ships it 1, RHEL 9 ships it 0 unless explicitly enabled. Similarly, CVE-2026-43284 / CVE-2026-43500 chain through unprivileged BPF primitives — `kernel.unprivileged_bpf_disabled = 0` is the gating flag. SELinux in Enforcing mode breaks the standard exploitation chain for several LPE classes; SELinux in Permissive provides no mitigation, only logging. MAC posture is therefore decisive for blast-radius scoring even when kernel version is technically vulnerable. The combination matters: vulnerable kernel + permissive MAC + relaxed hardening flags = exploitable; vulnerable kernel + enforcing MAC + tight hardening flags = primitive broken even pre-patch.",
|
|
143
|
+
"rwep_threshold": {
|
|
144
|
+
"escalate": 85,
|
|
145
|
+
"monitor": 65,
|
|
146
|
+
"close": 30
|
|
147
|
+
},
|
|
148
|
+
"framework_lag_declaration": "NIST CM-6, ISO A.8.9, Essential 8 OS Hardening, CMMC CM.L2-3.4.1/2 all permit baseline + change-management evidence without requiring continuous attestation of the specific kernel hardening flags (kptr_restrict, unprivileged_userns_clone, unprivileged_bpf_disabled, yama.ptrace_scope, dmesg_restrict, kernel.lockdown, MAC enforcement mode) that determine whether a vulnerable kernel is actually exploitable. Gap = ~21 days at typical orgs between drift event and review. For environments using GitOps-deployed kernel parameters, drift can occur faster than monitoring catches.",
|
|
149
|
+
"skill_chain": [
|
|
150
|
+
{ "skill": "kernel-lpe-triage", "purpose": "Identify which hardening flags gate exploitation of catalogued LPE CVEs; map flag state to per-CVE exploitability.", "required": true },
|
|
151
|
+
{ "skill": "security-maturity-tiers", "purpose": "Score current hardening posture against tier model; identify gaps to next tier.", "required": true },
|
|
152
|
+
{ "skill": "framework-gap-analysis", "purpose": "Map hardening drift findings to which CM-6 / A.8.9 / Essential 8 controls were attested-but-drifted.", "required": true },
|
|
153
|
+
{ "skill": "compliance-theater", "purpose": "Run the theater test on the org's CIS/STIG/Essential 8 attestation.", "required": true },
|
|
154
|
+
{ "skill": "policy-exception-gen", "purpose": "Generate auditor-ready exception language for hardening flags that cannot be tightened (e.g. unprivileged_userns_clone needed for legitimate container workloads).", "skip_if": "close.exception_generation.trigger_condition == false", "required": false }
|
|
155
|
+
],
|
|
156
|
+
"token_budget": {
|
|
157
|
+
"estimated_total": 19000,
|
|
158
|
+
"breakdown": {
|
|
159
|
+
"govern": 2400,
|
|
160
|
+
"direct": 1600,
|
|
161
|
+
"look": 2000,
|
|
162
|
+
"detect": 2800,
|
|
163
|
+
"analyze": 4200,
|
|
164
|
+
"validate": 3600,
|
|
165
|
+
"close": 2400
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
},
|
|
169
|
+
|
|
170
|
+
"look": {
|
|
171
|
+
"artifacts": [
|
|
172
|
+
{
|
|
173
|
+
"id": "sysctl-kernel-hardening",
|
|
174
|
+
"type": "config_file",
|
|
175
|
+
"source": "sysctl -a 2>/dev/null | grep -E '^(kernel\\.(kptr_restrict|unprivileged_userns_clone|unprivileged_bpf_disabled|yama\\.ptrace_scope|dmesg_restrict|kexec_load_disabled|modules_disabled|sysrq|panic_on_oops|randomize_va_space|core_uses_pid|perf_event_paranoid)|net\\.ipv4\\.(conf\\.all\\.(rp_filter|accept_source_route|send_redirects)|tcp_syncookies)|fs\\.(protected_(hardlinks|symlinks|fifos|regular)|suid_dumpable))'",
|
|
176
|
+
"description": "Core kernel + network + filesystem hardening sysctl flags. These are the primitives gating most catalogued kernel LPE classes.",
|
|
177
|
+
"required": true,
|
|
178
|
+
"air_gap_alternative": "Read /proc/sys/* hierarchy directly (e.g. cat /proc/sys/kernel/kptr_restrict)."
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
"id": "kernel-cmdline",
|
|
182
|
+
"type": "config_file",
|
|
183
|
+
"source": "cat /proc/cmdline",
|
|
184
|
+
"description": "Boot-time kernel parameters. nokaslr, init_on_alloc=0, slab_nomerge, vsyscall, mitigations=off — each materially changes exploitability.",
|
|
185
|
+
"required": true
|
|
186
|
+
},
|
|
187
|
+
{
|
|
188
|
+
"id": "cpu-vulnerabilities",
|
|
189
|
+
"type": "config_file",
|
|
190
|
+
"source": "for f in /sys/devices/system/cpu/vulnerabilities/*; do echo \"$f: $(cat $f)\"; done",
|
|
191
|
+
"description": "Distro-reported CPU mitigation status per known vulnerability class (Spectre v1/v2, Meltdown, MDS, L1TF, Retbleed, Downfall, GDS, RFDS, Reptar).",
|
|
192
|
+
"required": true,
|
|
193
|
+
"air_gap_alternative": "If sysfs unavailable, parse `dmesg | grep -i 'vulnerability\\|mitigation'`."
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
"id": "kernel-lockdown",
|
|
197
|
+
"type": "config_file",
|
|
198
|
+
"source": "cat /sys/kernel/security/lockdown 2>/dev/null",
|
|
199
|
+
"description": "Kernel lockdown mode (none / integrity / confidentiality). Integrity mode blocks several kernel-modification LPE primitives; confidentiality also blocks /dev/mem-style reads.",
|
|
200
|
+
"required": false,
|
|
201
|
+
"air_gap_alternative": "Check /proc/cmdline for `lockdown=` parameter."
|
|
202
|
+
},
|
|
203
|
+
{
|
|
204
|
+
"id": "selinux-state",
|
|
205
|
+
"type": "config_file",
|
|
206
|
+
"source": "getenforce 2>/dev/null; sestatus 2>/dev/null",
|
|
207
|
+
"description": "SELinux mode: Enforcing | Permissive | Disabled. Critical for MAC posture scoring.",
|
|
208
|
+
"required": false,
|
|
209
|
+
"air_gap_alternative": "cat /sys/fs/selinux/enforce → 1 means Enforcing, 0 Permissive; absence means Disabled or AppArmor."
|
|
210
|
+
},
|
|
211
|
+
{
|
|
212
|
+
"id": "apparmor-state",
|
|
213
|
+
"type": "config_file",
|
|
214
|
+
"source": "aa-status 2>/dev/null; cat /sys/kernel/security/apparmor/profiles 2>/dev/null",
|
|
215
|
+
"description": "AppArmor profile load + enforce status. Profiles in 'complain' mode are equivalent to SELinux Permissive — logs-only.",
|
|
216
|
+
"required": false
|
|
217
|
+
},
|
|
218
|
+
{
|
|
219
|
+
"id": "sshd-config",
|
|
220
|
+
"type": "config_file",
|
|
221
|
+
"source": "sshd -T 2>/dev/null || cat /etc/ssh/sshd_config",
|
|
222
|
+
"description": "Effective sshd configuration. PermitRootLogin, PasswordAuthentication, KbdInteractiveAuthentication, MaxAuthTries, AllowUsers/AllowGroups, kex algorithms, ciphers, MACs.",
|
|
223
|
+
"required": true
|
|
224
|
+
},
|
|
225
|
+
{
|
|
226
|
+
"id": "sudoers-structure",
|
|
227
|
+
"type": "config_file",
|
|
228
|
+
"source": "cat /etc/sudoers; ls -la /etc/sudoers.d/; for f in /etc/sudoers.d/*; do echo \"--- $f ---\"; cat $f; done",
|
|
229
|
+
"description": "Sudoers configuration. Defaults requiretty / use_pty / lecture / log_input / log_output / passwd_timeout values; per-user/group rules.",
|
|
230
|
+
"required": true
|
|
231
|
+
},
|
|
232
|
+
{
|
|
233
|
+
"id": "pam-stack",
|
|
234
|
+
"type": "config_file",
|
|
235
|
+
"source": "ls /etc/pam.d/; cat /etc/pam.d/system-auth /etc/pam.d/common-auth /etc/pam.d/common-password 2>/dev/null",
|
|
236
|
+
"description": "PAM authentication stack. pam_unix minlen / remember / sha512 / nullok presence, pam_faillock / pam_tally2 presence, pam_pwquality settings.",
|
|
237
|
+
"required": false
|
|
238
|
+
},
|
|
239
|
+
{
|
|
240
|
+
"id": "audit-rules",
|
|
241
|
+
"type": "config_file",
|
|
242
|
+
"source": "auditctl -l 2>/dev/null; cat /etc/audit/audit.rules /etc/audit/rules.d/*.rules 2>/dev/null",
|
|
243
|
+
"description": "Linux audit subsystem rules. Required to corroborate that hardening + drift detection has audit coverage.",
|
|
244
|
+
"required": false
|
|
245
|
+
},
|
|
246
|
+
{
|
|
247
|
+
"id": "umask-defaults",
|
|
248
|
+
"type": "config_file",
|
|
249
|
+
"source": "grep -h '^UMASK\\|^umask' /etc/login.defs /etc/profile /etc/bash.bashrc /etc/profile.d/*.sh 2>/dev/null",
|
|
250
|
+
"description": "Default umask. 022 is permissive default; 027 or 077 is hardened. Matters for world-readable secrets and credential files.",
|
|
251
|
+
"required": false
|
|
252
|
+
}
|
|
253
|
+
],
|
|
254
|
+
"collection_scope": {
|
|
255
|
+
"time_window": "current",
|
|
256
|
+
"asset_scope": "local_host",
|
|
257
|
+
"depth": "deep",
|
|
258
|
+
"sampling": "single-host point-in-time snapshot; this is the corroborator for kernel.json so re-collect on every kernel playbook regression trigger plus monthly"
|
|
259
|
+
},
|
|
260
|
+
"environment_assumptions": [
|
|
261
|
+
{
|
|
262
|
+
"assumption": "host.platform == 'linux'",
|
|
263
|
+
"if_false": "Skip playbook with visibility_gap=platform_unsupported."
|
|
264
|
+
},
|
|
265
|
+
{
|
|
266
|
+
"assumption": "agent can read /proc/sys/kernel/*, /sys/devices/system/cpu/vulnerabilities/*, /sys/kernel/security/*",
|
|
267
|
+
"if_false": "Containerized environment with masked /proc/sys. Mark sysctl + lockdown artifacts inconclusive; explicitly note that the container playbook governs the actual hardening posture for this workload."
|
|
268
|
+
},
|
|
269
|
+
{
|
|
270
|
+
"assumption": "host has either SELinux or AppArmor (not neither)",
|
|
271
|
+
"if_false": "No MAC layer present. Treat as deterministic blast-radius amplifier; mark mac_posture=none."
|
|
272
|
+
},
|
|
273
|
+
{
|
|
274
|
+
"assumption": "sshd is the host's primary remote access daemon",
|
|
275
|
+
"if_false": "Non-standard remote-access path (e.g. console-only bastion, mosh-only, identity-aware proxy). Mark sshd-config artifact as out-of-scope and note the alternative path."
|
|
276
|
+
}
|
|
277
|
+
],
|
|
278
|
+
"fallback_if_unavailable": [
|
|
279
|
+
{ "artifact_id": "sysctl-kernel-hardening", "fallback_action": "escalate_to_human", "confidence_impact": "high" },
|
|
280
|
+
{ "artifact_id": "kernel-cmdline", "fallback_action": "use_compensating_artifact", "confidence_impact": "low" },
|
|
281
|
+
{ "artifact_id": "cpu-vulnerabilities", "fallback_action": "mark_inconclusive", "confidence_impact": "low" },
|
|
282
|
+
{ "artifact_id": "kernel-lockdown", "fallback_action": "mark_inconclusive", "confidence_impact": "medium" },
|
|
283
|
+
{ "artifact_id": "selinux-state", "fallback_action": "use_compensating_artifact", "confidence_impact": "medium" },
|
|
284
|
+
{ "artifact_id": "apparmor-state", "fallback_action": "use_compensating_artifact", "confidence_impact": "medium" },
|
|
285
|
+
{ "artifact_id": "sshd-config", "fallback_action": "use_compensating_artifact", "confidence_impact": "medium" },
|
|
286
|
+
{ "artifact_id": "audit-rules", "fallback_action": "mark_inconclusive", "confidence_impact": "low" }
|
|
287
|
+
]
|
|
288
|
+
},
|
|
289
|
+
|
|
290
|
+
"detect": {
|
|
291
|
+
"indicators": [
|
|
292
|
+
{
|
|
293
|
+
"id": "kptr-restrict-disabled",
|
|
294
|
+
"type": "behavioral_signal",
|
|
295
|
+
"value": "kernel.kptr_restrict == 0",
|
|
296
|
+
"description": "/proc/kallsyms is world-readable; KASLR is effectively defeated for any local user. Decisive for kernel LPE exploitability.",
|
|
297
|
+
"confidence": "deterministic",
|
|
298
|
+
"deterministic": true,
|
|
299
|
+
"attack_ref": "T1068"
|
|
300
|
+
},
|
|
301
|
+
{
|
|
302
|
+
"id": "unprivileged-userns-enabled",
|
|
303
|
+
"type": "behavioral_signal",
|
|
304
|
+
"value": "kernel.unprivileged_userns_clone == 1",
|
|
305
|
+
"description": "Unprivileged user namespaces enabled. Required primitive for CVE-2026-31431 and userns-class LPEs.",
|
|
306
|
+
"confidence": "deterministic",
|
|
307
|
+
"deterministic": true,
|
|
308
|
+
"attack_ref": "T1611"
|
|
309
|
+
},
|
|
310
|
+
{
|
|
311
|
+
"id": "unprivileged-bpf-allowed",
|
|
312
|
+
"type": "behavioral_signal",
|
|
313
|
+
"value": "kernel.unprivileged_bpf_disabled == 0",
|
|
314
|
+
"description": "Unprivileged BPF allowed. Required primitive for BPF-class LPEs.",
|
|
315
|
+
"confidence": "deterministic",
|
|
316
|
+
"deterministic": true,
|
|
317
|
+
"attack_ref": "T1068"
|
|
318
|
+
},
|
|
319
|
+
{
|
|
320
|
+
"id": "yama-ptrace-permissive",
|
|
321
|
+
"type": "behavioral_signal",
|
|
322
|
+
"value": "kernel.yama.ptrace_scope == 0",
|
|
323
|
+
"description": "Yama ptrace_scope=0 allows any process to ptrace any same-UID process. Credential-theft + privilege-pivot primitive.",
|
|
324
|
+
"confidence": "deterministic",
|
|
325
|
+
"deterministic": true,
|
|
326
|
+
"attack_ref": "T1212"
|
|
327
|
+
},
|
|
328
|
+
{
|
|
329
|
+
"id": "kaslr-disabled-at-boot",
|
|
330
|
+
"type": "log_pattern",
|
|
331
|
+
"value": "/proc/cmdline contains 'nokaslr' OR 'kaslr=off'",
|
|
332
|
+
"description": "Boot-time KASLR disabled. Makes catalogued kernel LPEs deterministic.",
|
|
333
|
+
"confidence": "deterministic",
|
|
334
|
+
"deterministic": true,
|
|
335
|
+
"attack_ref": "T1068"
|
|
336
|
+
},
|
|
337
|
+
{
|
|
338
|
+
"id": "mitigations-off",
|
|
339
|
+
"type": "log_pattern",
|
|
340
|
+
"value": "/proc/cmdline contains 'mitigations=off'",
|
|
341
|
+
"description": "Boot-time CPU mitigations disabled. Spectre/Meltdown/MDS/Retbleed/Downfall class becomes exploitable.",
|
|
342
|
+
"confidence": "deterministic",
|
|
343
|
+
"deterministic": true,
|
|
344
|
+
"attack_ref": "T1068"
|
|
345
|
+
},
|
|
346
|
+
{
|
|
347
|
+
"id": "selinux-not-enforcing",
|
|
348
|
+
"type": "behavioral_signal",
|
|
349
|
+
"value": "getenforce != 'Enforcing' AND aa-status reports no enforcing profiles",
|
|
350
|
+
"description": "No MAC enforcement. Several catalogued LPEs that would be blocked by an Enforcing MAC layer are open.",
|
|
351
|
+
"confidence": "high",
|
|
352
|
+
"deterministic": false
|
|
353
|
+
},
|
|
354
|
+
{
|
|
355
|
+
"id": "sshd-permitrootlogin-yes",
|
|
356
|
+
"type": "log_pattern",
|
|
357
|
+
"value": "sshd_config effective: PermitRootLogin yes (or 'without-password' on legacy)",
|
|
358
|
+
"description": "Direct root SSH login enabled. Eliminates the privilege-escalation step.",
|
|
359
|
+
"confidence": "deterministic",
|
|
360
|
+
"deterministic": true,
|
|
361
|
+
"attack_ref": "T1078.003"
|
|
362
|
+
},
|
|
363
|
+
{
|
|
364
|
+
"id": "sshd-password-auth-enabled",
|
|
365
|
+
"type": "log_pattern",
|
|
366
|
+
"value": "sshd_config effective: PasswordAuthentication yes AND no MFA via PAM",
|
|
367
|
+
"description": "Password-only SSH authentication. Credential-spray primitive.",
|
|
368
|
+
"confidence": "high",
|
|
369
|
+
"deterministic": false,
|
|
370
|
+
"attack_ref": "T1110.001"
|
|
371
|
+
},
|
|
372
|
+
{
|
|
373
|
+
"id": "core-pid-dumpable",
|
|
374
|
+
"type": "behavioral_signal",
|
|
375
|
+
"value": "fs.suid_dumpable >= 1",
|
|
376
|
+
"description": "SUID binaries can produce core dumps. Credential leakage primitive (cores can contain decrypted secrets in memory).",
|
|
377
|
+
"confidence": "high",
|
|
378
|
+
"deterministic": false
|
|
379
|
+
}
|
|
380
|
+
],
|
|
381
|
+
"false_positive_profile": [
|
|
382
|
+
{
|
|
383
|
+
"indicator_id": "unprivileged-userns-enabled",
|
|
384
|
+
"benign_pattern": "Host runs rootless container workloads (Podman, Docker rootless, K8s with userns remapping). Distro default on Ubuntu 24.04 is enabled by design.",
|
|
385
|
+
"distinguishing_test": "Check whether the host runs unprivileged container workloads (process tree shows podman/docker rootless OR k8s kubelet with userns-mode). If yes, the flag is intentional; emit a 'hardening-by-design-trade-off' finding and require that compensating controls (MAC profile enforced on container runtime, kernel up to date on userns-class CVEs) are in place. If no userns workload is present, the flag is gratuitous attack surface."
|
|
386
|
+
},
|
|
387
|
+
{
|
|
388
|
+
"indicator_id": "unprivileged-bpf-allowed",
|
|
389
|
+
"benign_pattern": "Host runs observability tooling that requires unprivileged BPF (perf monitoring, eBPF-based APM agents).",
|
|
390
|
+
"distinguishing_test": "Resolve whether any process has BPF maps open via `bpftool prog list` or `lsof | grep bpf`. If no unprivileged BPF user exists, the flag is gratuitous. If unprivileged BPF is in active use, emit a hardening-trade-off finding and require BPF LSM enforcement as compensating control."
|
|
391
|
+
},
|
|
392
|
+
{
|
|
393
|
+
"indicator_id": "sshd-password-auth-enabled",
|
|
394
|
+
"benign_pattern": "Bastion host configured for emergency-break-glass operator access with TOTP/U2F via PAM as secondary factor.",
|
|
395
|
+
"distinguishing_test": "Check PAM stack on /etc/pam.d/sshd for pam_google_authenticator, pam_u2f, pam_oath, or pam_duo. If MFA module is present and required (auth required, not auth sufficient), downgrade to medium and emit a 'password+MFA' finding rather than 'password-only'."
|
|
396
|
+
},
|
|
397
|
+
{
|
|
398
|
+
"indicator_id": "selinux-not-enforcing",
|
|
399
|
+
"benign_pattern": "Host runs AppArmor instead of SELinux (Ubuntu/Debian default).",
|
|
400
|
+
"distinguishing_test": "Check `aa-status` for enforcing profiles. If AppArmor reports enforcing profiles covering the workload's processes, the MAC layer IS active and SELinux absence is benign. If both SELinux is non-enforcing AND AppArmor has no enforcing profiles, the host has no MAC enforcement."
|
|
401
|
+
}
|
|
402
|
+
],
|
|
403
|
+
"minimum_signal": {
|
|
404
|
+
"detected": "At least one deterministic hardening-drift indicator fires (kptr-restrict-disabled, kaslr-disabled-at-boot, mitigations-off, sshd-permitrootlogin-yes) OR two or more high-confidence indicators fire AND the kernel playbook reports kver-in-affected-range for any catalogued LPE.",
|
|
405
|
+
"inconclusive": "/proc/sys read access masked or partial (container, hardened OS); cannot evaluate the gating flags. Distinguish 'hardening unknown' from 'hardening present' explicitly.",
|
|
406
|
+
"not_detected": "All required sysctl flags collected AND posture matches Essential 8 ML3 or CIS Level 2 baseline AND MAC layer is Enforcing AND no boot-time mitigation overrides are set."
|
|
407
|
+
}
|
|
408
|
+
},
|
|
409
|
+
|
|
410
|
+
"analyze": {
|
|
411
|
+
"rwep_inputs": [
|
|
412
|
+
{ "signal_id": "kptr-restrict-disabled", "rwep_factor": "blast_radius", "weight": 15, "notes": "Decisive for kernel LPE exploitability; multiplies impact of any matched kernel CVE." },
|
|
413
|
+
{ "signal_id": "unprivileged-userns-enabled", "rwep_factor": "active_exploitation", "weight": 20, "notes": "Gates CVE-2026-31431 exploitability; full weight when paired with vulnerable kernel." },
|
|
414
|
+
{ "signal_id": "unprivileged-bpf-allowed", "rwep_factor": "active_exploitation", "weight": 15, "notes": "Gates BPF-class LPE exploitability." },
|
|
415
|
+
{ "signal_id": "yama-ptrace-permissive", "rwep_factor": "blast_radius", "weight": 10, "notes": "Credential-theft primitive; blast radius amplifier rather than direct LPE." },
|
|
416
|
+
{ "signal_id": "kaslr-disabled-at-boot", "rwep_factor": "active_exploitation", "weight": 25, "notes": "Makes kernel LPEs deterministic; full weight." },
|
|
417
|
+
{ "signal_id": "mitigations-off", "rwep_factor": "active_exploitation", "weight": 20, "notes": "Re-opens CPU side-channel LPE classes; full weight." },
|
|
418
|
+
{ "signal_id": "selinux-not-enforcing", "rwep_factor": "blast_radius", "weight": 10, "notes": "Removes a layer that would otherwise break the exploitation chain for several LPEs." },
|
|
419
|
+
{ "signal_id": "sshd-permitrootlogin-yes", "rwep_factor": "blast_radius", "weight": 15, "notes": "Removes the LPE step entirely if credential is obtained." }
|
|
420
|
+
],
|
|
421
|
+
"blast_radius_model": {
|
|
422
|
+
"scope_question": "Given the inventoried hardening posture, what is the realistic delta between 'kernel CVE matched' and 'kernel CVE actually exploitable on this host'?",
|
|
423
|
+
"scoring_rubric": [
|
|
424
|
+
{ "condition": "All deterministic hardening flags hardened (kptr_restrict=2, unprivileged_userns_clone=0 or under MAC, unprivileged_bpf_disabled=1, KASLR enabled, mitigations=auto, MAC Enforcing, lockdown=integrity or confidentiality)", "blast_radius_score": 1, "description": "Hardening posture closes most catalogued LPE primitives. Vulnerable kernel does not mean exploitable host." },
|
|
425
|
+
{ "condition": "One deterministic hardening flag drifted from baseline (e.g. unprivileged_userns_clone=1 due to container workload, MAC compensating) OR MAC layer compensates for drift", "blast_radius_score": 2, "description": "Trade-off posture. Drift is intentional and compensated; documented." },
|
|
426
|
+
{ "condition": "Two or more deterministic hardening flags drifted AND no MAC compensation OR MAC in Permissive mode", "blast_radius_score": 3, "description": "Drift not compensated. Vulnerable kernel + this posture = exploitable in principle." },
|
|
427
|
+
{ "condition": "Deterministic drift AND kernel playbook reports matched LPE with active_exploitation=confirmed AND no live-patch", "blast_radius_score": 4, "description": "Operational exposure. Exploitation chain is complete given foothold." },
|
|
428
|
+
{ "condition": "Deterministic drift AND host is k8s control-plane OR identity broker OR has cross-account trust", "blast_radius_score": 5, "description": "Drift on a host whose compromise is org-wide. Identity boundary collapse risk." }
|
|
429
|
+
]
|
|
430
|
+
},
|
|
431
|
+
"compliance_theater_check": {
|
|
432
|
+
"claim": "Org follows CIS Benchmark / DISA STIG / Essential 8 OS Hardening for $distro; CM-6 / A.8.9 baseline configured.",
|
|
433
|
+
"audit_evidence": "CIS Benchmark scan output dated within the last audit cycle; documented baseline configuration; change-management records for any deviations.",
|
|
434
|
+
"reality_test": "Run a fresh CIS Benchmark scan (or `oscap` against the appropriate SCAP profile) today on the host AND compare to: (a) the most recent attested benchmark run, (b) the documented deviation list. Compute the count of controls that have regressed since the attestation date. Any regression count > 0 on the deterministic hardening flags (kptr_restrict, unprivileged_userns_clone, unprivileged_bpf_disabled, KASLR, MAC mode) is automatic theater regardless of overall pass percentage. Additionally test whether `getenforce` returns 'Enforcing' (not 'Permissive') and whether AppArmor profiles are 'enforce' (not 'complain').",
|
|
435
|
+
"theater_verdict_if_gap": "Attested hardening baseline diverges from live posture on at least one flag that gates kernel LPE exploitability. Either (a) re-harden the host to match attestation, (b) re-attest the baseline to match live state AND document compensating MAC/live-patch coverage, OR (c) generate a policy exception with bounded duration + named compensating controls."
|
|
436
|
+
},
|
|
437
|
+
"framework_gap_mapping": [
|
|
438
|
+
{
|
|
439
|
+
"finding_id": "hardening-drift",
|
|
440
|
+
"framework": "nist-800-53",
|
|
441
|
+
"claimed_control": "CM-6 — Configuration Settings",
|
|
442
|
+
"actual_gap": "Permits baseline + change-management without continuous drift monitoring on the specific kernel hardening flags that determine LPE exploitability.",
|
|
443
|
+
"required_control": "Add a CM-6 sub-control requiring monthly programmatic verification of named kernel hardening flags (sysctl + cmdline + MAC mode) against documented baseline."
|
|
444
|
+
},
|
|
445
|
+
{
|
|
446
|
+
"finding_id": "hardening-drift",
|
|
447
|
+
"framework": "iso-27001-2022",
|
|
448
|
+
"claimed_control": "A.8.9 — Configuration Management",
|
|
449
|
+
"actual_gap": "Baseline + change-management evidence accepted. Does not require continuous attestation of named flags.",
|
|
450
|
+
"required_control": "Statement of Applicability footnote requiring monthly programmatic baseline diff for kernel hardening flags."
|
|
451
|
+
},
|
|
452
|
+
{
|
|
453
|
+
"finding_id": "hardening-drift",
|
|
454
|
+
"framework": "au-essential-8",
|
|
455
|
+
"claimed_control": "OS Hardening / Application Hardening",
|
|
456
|
+
"actual_gap": "Maturity Level scoring is point-in-time; drift between assessments is not surfaced.",
|
|
457
|
+
"required_control": "Add a continuous-attestation criterion at ML3 requiring monthly programmatic baseline diff."
|
|
458
|
+
},
|
|
459
|
+
{
|
|
460
|
+
"finding_id": "hardening-drift",
|
|
461
|
+
"framework": "cmmc",
|
|
462
|
+
"claimed_control": "CM.L2-3.4.2 — Establish and enforce security configuration settings",
|
|
463
|
+
"actual_gap": "Same as CM-6 lineage — process-shaped, not state-shaped.",
|
|
464
|
+
"required_control": "L2 assessment requires monthly programmatic baseline diff evidence for kernel hardening flags as part of the SSP-attached configuration baseline."
|
|
465
|
+
}
|
|
466
|
+
],
|
|
467
|
+
"escalation_criteria": [
|
|
468
|
+
{ "condition": "deterministic_hardening_drift == true AND kernel.playbook.reports_matched_lpe == true", "action": "trigger_playbook", "target_playbook": "kernel" },
|
|
469
|
+
{ "condition": "selinux_disabled AND apparmor_no_enforcing_profiles AND blast_radius_score >= 3", "action": "raise_severity" },
|
|
470
|
+
{ "condition": "sshd_permitrootlogin_yes == true", "action": "page_on_call" },
|
|
471
|
+
{ "condition": "compliance_theater_check.verdict == 'theater' AND jurisdiction_obligations contains 'EU'", "action": "notify_legal" }
|
|
472
|
+
]
|
|
473
|
+
},
|
|
474
|
+
|
|
475
|
+
"validate": {
|
|
476
|
+
"remediation_paths": [
|
|
477
|
+
{
|
|
478
|
+
"id": "tighten-sysctl",
|
|
479
|
+
"description": "Apply hardened sysctl values: kptr_restrict=2, unprivileged_userns_clone=0 (or compensate with MAC), unprivileged_bpf_disabled=1, yama.ptrace_scope=2, fs.suid_dumpable=0, dmesg_restrict=1. Persist via /etc/sysctl.d/99-exceptd-hardening.conf.",
|
|
480
|
+
"preconditions": ["no_workload_requires_relaxed_flag == true OR mac_compensation_in_place == true", "ops_authorization_for_sysctl_changes == true"],
|
|
481
|
+
"priority": 1,
|
|
482
|
+
"compensating_controls": ["change-management-ticket", "regression-test-suite-passed"],
|
|
483
|
+
"estimated_time_hours": 2
|
|
484
|
+
},
|
|
485
|
+
{
|
|
486
|
+
"id": "tighten-kernel-cmdline",
|
|
487
|
+
"description": "Remove `nokaslr` / `kaslr=off` / `mitigations=off` from /etc/default/grub or equivalent bootloader config; reboot to apply. Optionally add `lockdown=integrity` for kernels >= 5.4.",
|
|
488
|
+
"preconditions": ["vendor_supports_lockdown == true OR removing_existing_override == true", "reboot_window_within_72h == true"],
|
|
489
|
+
"priority": 2,
|
|
490
|
+
"compensating_controls": ["change-management-ticket", "post-boot-cmdline-verification"],
|
|
491
|
+
"estimated_time_hours": 4
|
|
492
|
+
},
|
|
493
|
+
{
|
|
494
|
+
"id": "enable-mac-enforcing",
|
|
495
|
+
"description": "Move SELinux from Permissive to Enforcing (after audit log review for would-have-denials) OR move AppArmor profiles from 'complain' to 'enforce'.",
|
|
496
|
+
"preconditions": ["audit_log_review_complete == true", "workload_compatible_with_enforcing == true"],
|
|
497
|
+
"priority": 1,
|
|
498
|
+
"compensating_controls": ["audit-log-baseline-captured", "regression-test-suite-passed"],
|
|
499
|
+
"estimated_time_hours": 4
|
|
500
|
+
},
|
|
501
|
+
{
|
|
502
|
+
"id": "tighten-sshd",
|
|
503
|
+
"description": "Set PermitRootLogin no, PasswordAuthentication no (or require MFA via PAM), MaxAuthTries 3, restrict via AllowUsers/AllowGroups. Test from a second session before logging out.",
|
|
504
|
+
"preconditions": ["non_root_admin_account_exists == true", "ssh_key_or_mfa_already_deployed == true"],
|
|
505
|
+
"priority": 1,
|
|
506
|
+
"compensating_controls": ["second-session-verified", "break-glass-console-access-confirmed"],
|
|
507
|
+
"estimated_time_hours": 1
|
|
508
|
+
},
|
|
509
|
+
{
|
|
510
|
+
"id": "policy-exception",
|
|
511
|
+
"description": "If a hardening flag cannot be tightened due to workload requirements (e.g. unprivileged_userns_clone needed for rootless containers), generate an auditor-ready exception with named compensating controls.",
|
|
512
|
+
"preconditions": ["workload_requires_relaxed_flag == true", "mac_or_alternative_compensation_documented == true"],
|
|
513
|
+
"priority": 4,
|
|
514
|
+
"compensating_controls": ["mac-profile-tightened", "enhanced-audit-on-affected-syscall-path", "ciso-acceptance-on-residual-risk"],
|
|
515
|
+
"estimated_time_hours": 8
|
|
516
|
+
}
|
|
517
|
+
],
|
|
518
|
+
"validation_tests": [
|
|
519
|
+
{
|
|
520
|
+
"id": "sysctl-values-applied",
|
|
521
|
+
"test": "Run `sysctl kernel.kptr_restrict kernel.unprivileged_userns_clone kernel.unprivileged_bpf_disabled kernel.yama.ptrace_scope fs.suid_dumpable` and compare to hardened baseline.",
|
|
522
|
+
"expected_result": "All values match hardened baseline.",
|
|
523
|
+
"test_type": "functional"
|
|
524
|
+
},
|
|
525
|
+
{
|
|
526
|
+
"id": "cmdline-no-overrides",
|
|
527
|
+
"test": "cat /proc/cmdline. Confirm no 'nokaslr', 'kaslr=off', 'mitigations=off', 'no_vsyscall', or other mitigation-disabling parameters.",
|
|
528
|
+
"expected_result": "Boot-time kernel parameters free of mitigation overrides.",
|
|
529
|
+
"test_type": "negative"
|
|
530
|
+
},
|
|
531
|
+
{
|
|
532
|
+
"id": "mac-enforcing",
|
|
533
|
+
"test": "Run `getenforce` (expect 'Enforcing') OR `aa-status` (expect at least the workload's processes covered by enforcing profiles).",
|
|
534
|
+
"expected_result": "MAC layer in Enforcing mode covering workload.",
|
|
535
|
+
"test_type": "functional"
|
|
536
|
+
},
|
|
537
|
+
{
|
|
538
|
+
"id": "sshd-effective-config",
|
|
539
|
+
"test": "Run `sshd -T` and grep for PermitRootLogin, PasswordAuthentication. Run a from-elsewhere `ssh -o PreferredAuthentications=password root@host` and confirm refusal.",
|
|
540
|
+
"expected_result": "Root SSH login refused; password-only auth path refused or MFA-gated.",
|
|
541
|
+
"test_type": "negative"
|
|
542
|
+
},
|
|
543
|
+
{
|
|
544
|
+
"id": "exploit-primitive-blocked",
|
|
545
|
+
"test": "For each catalogued kernel LPE with a hardening-flag dependency: run the safe-mode primitive-trigger step (no payload) and confirm it returns EPERM.",
|
|
546
|
+
"expected_result": "Primitive trigger fails on the hardened host; succeeds on a known-unhardened reference host.",
|
|
547
|
+
"test_type": "exploit_replay"
|
|
548
|
+
},
|
|
549
|
+
{
|
|
550
|
+
"id": "no-workload-regression",
|
|
551
|
+
"test": "Run the host's standard application test suite. Confirm no regression in workloads after sysctl + MAC + sshd hardening.",
|
|
552
|
+
"expected_result": "All workload regression tests pass.",
|
|
553
|
+
"test_type": "regression"
|
|
554
|
+
}
|
|
555
|
+
],
|
|
556
|
+
"residual_risk_statement": {
|
|
557
|
+
"risk": "Hardened posture still permits a kernel LPE that does not depend on any of the inventoried gating flags. New LPEs may emerge whose primitive is unrelated to userns/BPF/ptrace/kptr.",
|
|
558
|
+
"why_remains": "Hardening flags are a moving target — new CVEs name new primitives, and a host hardened against today's catalog may be exposed to tomorrow's. The compensating control is regression cadence + new-CVE-in-class trigger, not absolute hardening.",
|
|
559
|
+
"acceptance_level": "manager",
|
|
560
|
+
"compensating_controls_in_place": ["mac-enforcing", "monthly-hardening-diff-cadence", "edr-on-syscall-anomalies", "kernel-playbook-tied-to-this-baseline"]
|
|
561
|
+
},
|
|
562
|
+
"evidence_requirements": [
|
|
563
|
+
{
|
|
564
|
+
"evidence_type": "scan_report",
|
|
565
|
+
"description": "Full sysctl + cmdline + MAC + sshd_config + lockdown inventory output with timestamps and host identity.",
|
|
566
|
+
"retention_period": "1_year",
|
|
567
|
+
"framework_satisfied": ["nist-800-53-CM-6", "iso-27001-2022-A.8.9", "cmmc-cm-l2-3.4.2", "au-essential-8-os-hardening"]
|
|
568
|
+
},
|
|
569
|
+
{
|
|
570
|
+
"evidence_type": "config_diff",
|
|
571
|
+
"description": "Pre/post diff of sysctl values + /etc/default/grub + sshd_config showing remediation applied.",
|
|
572
|
+
"retention_period": "7_years",
|
|
573
|
+
"framework_satisfied": ["nist-800-53-CM-3", "iso-27001-2022-A.8.32"]
|
|
574
|
+
},
|
|
575
|
+
{
|
|
576
|
+
"evidence_type": "exploit_replay_negative",
|
|
577
|
+
"description": "Safe-mode primitive-trigger replays for each catalogued kernel LPE with hardening-flag dependency, showing post-remediation EPERM.",
|
|
578
|
+
"retention_period": "1_year",
|
|
579
|
+
"framework_satisfied": ["soc2-cc7.1", "iso-27001-2022-A.8.8"]
|
|
580
|
+
},
|
|
581
|
+
{
|
|
582
|
+
"evidence_type": "attestation",
|
|
583
|
+
"description": "Signed exceptd attestation: hardening baseline hash, scan timestamp, drift count, RWEP at detection, RWEP post-remediation.",
|
|
584
|
+
"retention_period": "7_years",
|
|
585
|
+
"framework_satisfied": ["nist-800-53-CA-7", "iso-27001-2022-A.5.36", "nis2-art21-2c"]
|
|
586
|
+
}
|
|
587
|
+
],
|
|
588
|
+
"regression_trigger": [
|
|
589
|
+
{ "condition": "new_cve_in_class == true", "interval": "on_event" },
|
|
590
|
+
{ "condition": "kernel_upgrade == true", "interval": "on_event" },
|
|
591
|
+
{ "condition": "monthly", "interval": "30d" },
|
|
592
|
+
{ "condition": "post_major_deploy", "interval": "on_event" },
|
|
593
|
+
{ "condition": "post_distro_release_upgrade", "interval": "on_event" }
|
|
594
|
+
]
|
|
595
|
+
},
|
|
596
|
+
|
|
597
|
+
"close": {
|
|
598
|
+
"evidence_package": {
|
|
599
|
+
"bundle_format": "csaf-2.0",
|
|
600
|
+
"contents": ["scan_report", "config_diff", "exploit_replay_negative", "attestation", "framework_gap_mapping", "compliance_theater_verdict", "residual_risk_statement"],
|
|
601
|
+
"destination": "local_only",
|
|
602
|
+
"signed": true
|
|
603
|
+
},
|
|
604
|
+
"learning_loop": {
|
|
605
|
+
"enabled": true,
|
|
606
|
+
"lesson_template": {
|
|
607
|
+
"attack_vector": "Kernel LPE chain through $hardening_gate_flag (unprivileged_userns_clone / unprivileged_bpf_disabled / kptr_restrict=0 / KASLR off / MAC Permissive / sshd root login).",
|
|
608
|
+
"control_gap": "Hardening baseline controls (CM-6, A.8.9, Essential 8 OS Hardening, CMMC CM.L2-3.4.2) accept baseline + change management as evidence and do not require continuous attestation of the specific flags that gate kernel LPE exploitability.",
|
|
609
|
+
"framework_gap": "Baseline-attestation cadence (annual to quarterly) is structurally slower than drift cadence (per-package-install, per-kernel-parameter-change). Frameworks lag drift by ~21 days at typical orgs.",
|
|
610
|
+
"new_control_requirement": "Monthly programmatic verification of named kernel hardening flags (sysctl + cmdline + MAC + sshd effective config) against documented baseline. Drift triggers automatic regeneration of the kernel-LPE playbook scope."
|
|
611
|
+
},
|
|
612
|
+
"feeds_back_to_skills": ["kernel-lpe-triage", "security-maturity-tiers", "framework-gap-analysis", "compliance-theater"]
|
|
613
|
+
},
|
|
614
|
+
"notification_actions": [
|
|
615
|
+
{
|
|
616
|
+
"obligation_ref": "EU/NIS2 Art.21 720h",
|
|
617
|
+
"deadline": "computed_at_runtime",
|
|
618
|
+
"recipient": "internal_legal",
|
|
619
|
+
"evidence_attached": ["hardening_baseline_documented", "drift_remediation_record"],
|
|
620
|
+
"draft_notification": "NIS2 Art.21 critical-vulnerability handling record: Hardening drift identified on ${affected_host_count} host(s) gating exploitability of catalogued kernel LPE(s) ${matched_cve_ids}. Drift count: ${drift_count}. Compensating controls in place: ${compensating_controls}. Remediation completed by ${remediation_date}. Evidence: hardening baseline + drift remediation record attached."
|
|
621
|
+
},
|
|
622
|
+
{
|
|
623
|
+
"obligation_ref": "AU/Essential 8 Application Hardening 720h",
|
|
624
|
+
"deadline": "computed_at_runtime",
|
|
625
|
+
"recipient": "internal_legal",
|
|
626
|
+
"evidence_attached": ["hardening_baseline_documented", "drift_remediation_record"],
|
|
627
|
+
"draft_notification": "Essential 8 OS Hardening evidence package: Hardening baseline verification on ${affected_host_count} host(s). Maturity Level claimed: ${ml_claimed}. Maturity Level supported by evidence: ${ml_evidence}. Drift remediation record: ${remediation_summary}."
|
|
628
|
+
},
|
|
629
|
+
{
|
|
630
|
+
"obligation_ref": "US/CMMC 2.0 CM.L2-3.4.2 720h",
|
|
631
|
+
"deadline": "computed_at_runtime",
|
|
632
|
+
"recipient": "internal_legal",
|
|
633
|
+
"evidence_attached": ["baseline_configuration_document", "ssp_section_update"],
|
|
634
|
+
"draft_notification": "CMMC CM.L2-3.4.2 baseline configuration update: Hardening baseline diff on ${affected_host_count} host(s). SSP section to update: ${ssp_section}. Drift remediation record attached. Continuous-monitoring evidence retained for assessor review."
|
|
635
|
+
}
|
|
636
|
+
],
|
|
637
|
+
"exception_generation": {
|
|
638
|
+
"trigger_condition": "workload_requires_relaxed_flag == true AND mac_or_alternative_compensation_documented == true",
|
|
639
|
+
"exception_template": {
|
|
640
|
+
"scope": "Hardening flag(s) ${flag_list} relaxed on ${affected_host_count} host(s) due to documented workload requirement (${workload_class}).",
|
|
641
|
+
"duration": "until_next_audit",
|
|
642
|
+
"compensating_controls": ["mac-profile-tightened-on-affected-syscall", "enhanced-audit-on-affected-path", "edr-anomaly-detection-on-affected-primitive", "monthly-residual-risk-review"],
|
|
643
|
+
"risk_acceptance_owner": "manager",
|
|
644
|
+
"auditor_ready_language": "Pursuant to ${framework_id} ${control_id}, the organization documents a time-bound risk acceptance for hardening flag(s) ${flag_list} on ${affected_host_count} host(s). Workload requirement: ${workload_requirement_narrative}. Compensating controls in place: ${compensating_controls}. Residual exposure post-compensation: only those kernel LPEs whose primitive specifically requires the relaxed flag AND whose mitigation path does not exist in MAC policy. Risk accepted by ${manager_name} on ${acceptance_date}. Time-bound until ${duration_expiry}. Detection coverage during the exception window is provided by ${detection_controls}. Re-evaluation triggers: (a) workload no longer requires the relaxed flag, (b) listed expiry date, (c) new exploitation indicator firing on the affected primitive — whichever is first."
|
|
645
|
+
}
|
|
646
|
+
},
|
|
647
|
+
"regression_schedule": {
|
|
648
|
+
"next_run": "computed_at_runtime",
|
|
649
|
+
"trigger": "both",
|
|
650
|
+
"notify_on_skip": true
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
},
|
|
654
|
+
|
|
655
|
+
"directives": [
|
|
656
|
+
{
|
|
657
|
+
"id": "full-hardening-posture",
|
|
658
|
+
"title": "Full hardening posture inventory — sysctl, cmdline, MAC, sshd, sudoers, PAM",
|
|
659
|
+
"applies_to": { "always": true }
|
|
660
|
+
},
|
|
661
|
+
{
|
|
662
|
+
"id": "kernel-lpe-gating-flags",
|
|
663
|
+
"title": "Targeted directive — flags that gate catalogued kernel LPE exploitability",
|
|
664
|
+
"applies_to": { "attack_technique": "T1068" }
|
|
665
|
+
},
|
|
666
|
+
{
|
|
667
|
+
"id": "userns-gating-flag",
|
|
668
|
+
"title": "Targeted directive — unprivileged_userns_clone state for CVE-2026-31431",
|
|
669
|
+
"applies_to": { "cve": "CVE-2026-31431" }
|
|
670
|
+
}
|
|
671
|
+
]
|
|
672
|
+
}
|