@blamejs/exceptd-skills 0.10.0 → 0.10.1

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,18 @@
9
9
  "version": "1.0.0",
10
10
  "date": "2026-05-11",
11
11
  "summary": "Initial seven-phase repo-scoped secret-exfiltration playbook. Walks the current repository to depth 6 (excluding node_modules, .git/objects, dist, build) for secret-shape regexes (AWS, GCP, GitHub, Slack, Stripe, JWT, SSH private keys, OpenAI, Anthropic), world-writable .env / .ssh files, and IaC files with embedded credentials. Closes the GRC loop with DLP framework-gap mapping + auditor-ready exception generation.",
12
- "framework_gaps_updated": ["nist-800-53-SC-28", "iso-27001-2022-A.8.24", "gdpr-art-32", "pci-dss-4-req-3", "soc2-cc6.1"]
12
+ "framework_gaps_updated": [
13
+ "nist-800-53-SC-28",
14
+ "iso-27001-2022-A.8.24",
15
+ "gdpr-art-32",
16
+ "pci-dss-4-req-3",
17
+ "soc2-cc6.1"
18
+ ]
13
19
  }
14
20
  ],
15
21
  "owner": "@blamejs/grc",
16
22
  "air_gap_mode": true,
23
+ "scope": "code",
17
24
  "preconditions": [
18
25
  {
19
26
  "id": "repo-context",
@@ -36,23 +43,41 @@
36
43
  }
37
44
  ]
38
45
  },
39
-
40
46
  "domain": {
41
47
  "name": "Repository-scoped secret exfiltration risk",
42
48
  "attack_class": "dlp-exfiltration",
43
- "atlas_refs": ["AML.T0055"],
44
- "attack_refs": ["T1552.001", "T1552.004", "T1552.005", "T1078.004"],
49
+ "atlas_refs": [
50
+ "AML.T0055"
51
+ ],
52
+ "attack_refs": [
53
+ "T1552.001",
54
+ "T1552.004",
55
+ "T1552.005",
56
+ "T1078.004"
57
+ ],
45
58
  "cve_refs": [],
46
- "cwe_refs": ["CWE-798", "CWE-200", "CWE-312", "CWE-732"],
47
- "d3fend_refs": ["D3-CAA", "D3-FCR"],
59
+ "cwe_refs": [
60
+ "CWE-798",
61
+ "CWE-200",
62
+ "CWE-312",
63
+ "CWE-732"
64
+ ],
65
+ "d3fend_refs": [
66
+ "D3-CAA",
67
+ "D3-FCR"
68
+ ],
48
69
  "frameworks_in_scope": [
49
- "nist-800-53", "iso-27001-2022", "soc2", "pci-dss-4",
50
- "nis2", "dora", "uk-caf", "hipaa"
70
+ "nist-800-53",
71
+ "iso-27001-2022",
72
+ "soc2",
73
+ "pci-dss-4",
74
+ "nis2",
75
+ "dora",
76
+ "uk-caf",
77
+ "hipaa"
51
78
  ]
52
79
  },
53
-
54
80
  "phases": {
55
-
56
81
  "govern": {
57
82
  "jurisdiction_obligations": [
58
83
  {
@@ -61,7 +86,11 @@
61
86
  "obligation": "notify_regulator",
62
87
  "window_hours": 72,
63
88
  "clock_starts": "detect_confirmed",
64
- "evidence_required": ["secret_inventory", "data_subject_impact_assessment", "containment_record"]
89
+ "evidence_required": [
90
+ "secret_inventory",
91
+ "data_subject_impact_assessment",
92
+ "containment_record"
93
+ ]
65
94
  },
66
95
  {
67
96
  "jurisdiction": "EU",
@@ -69,7 +98,10 @@
69
98
  "obligation": "notify_affected_individuals",
70
99
  "window_hours": 72,
71
100
  "clock_starts": "analyze_complete",
72
- "evidence_required": ["data_subject_categories_affected", "containment_record"]
101
+ "evidence_required": [
102
+ "data_subject_categories_affected",
103
+ "containment_record"
104
+ ]
73
105
  },
74
106
  {
75
107
  "jurisdiction": "EU",
@@ -77,7 +109,11 @@
77
109
  "obligation": "notify_regulator",
78
110
  "window_hours": 24,
79
111
  "clock_starts": "detect_confirmed",
80
- "evidence_required": ["secret_inventory", "exposure_window_estimate", "rotation_status"]
112
+ "evidence_required": [
113
+ "secret_inventory",
114
+ "exposure_window_estimate",
115
+ "rotation_status"
116
+ ]
81
117
  },
82
118
  {
83
119
  "jurisdiction": "UK",
@@ -85,7 +121,10 @@
85
121
  "obligation": "notify_regulator",
86
122
  "window_hours": 72,
87
123
  "clock_starts": "detect_confirmed",
88
- "evidence_required": ["secret_inventory", "data_subject_impact_assessment"]
124
+ "evidence_required": [
125
+ "secret_inventory",
126
+ "data_subject_impact_assessment"
127
+ ]
89
128
  },
90
129
  {
91
130
  "jurisdiction": "US-CA",
@@ -93,7 +132,10 @@
93
132
  "obligation": "notify_affected_individuals",
94
133
  "window_hours": 1440,
95
134
  "clock_starts": "analyze_complete",
96
- "evidence_required": ["california_resident_records_affected", "containment_record"]
135
+ "evidence_required": [
136
+ "california_resident_records_affected",
137
+ "containment_record"
138
+ ]
97
139
  }
98
140
  ],
99
141
  "theater_fingerprints": [
@@ -101,19 +143,30 @@
101
143
  "pattern_id": "gitleaks-in-ci-as-prevention",
102
144
  "claim": "gitleaks / trufflehog runs in CI → no secrets in repo.",
103
145
  "fast_detection_test": "Run a current scan against the repo HEAD and against the working tree (uncommitted files). CI catches committed-and-pushed secrets only. Uncommitted .env files, files in .gitignore, secrets in build artifacts under dist/, and IaC files staged-but-not-committed are all outside CI scope. Find any non-empty .env, .env.local, .npmrc, .pypirc, or terraform.tfvars in the working tree to verify.",
104
- "implicated_controls": ["nist-800-53-SA-11", "soc2-cc7.1", "iso-27001-2022-A.8.28"]
146
+ "implicated_controls": [
147
+ "nist-800-53-SA-11",
148
+ "soc2-cc7.1",
149
+ "iso-27001-2022-A.8.28"
150
+ ]
105
151
  },
106
152
  {
107
153
  "pattern_id": "vault-attested-but-bypassed",
108
154
  "claim": "We use Vault / Secrets Manager / KMS — no static credentials.",
109
155
  "fast_detection_test": "Grep the working tree for AWS_ACCESS_KEY_ID, GOOGLE_APPLICATION_CREDENTIALS pointing to a JSON file, ANTHROPIC_API_KEY, OPENAI_API_KEY, GITHUB_TOKEN literals. Vault-attested orgs commonly bypass for 'just this one dev workflow' or 'CI bootstrap secrets'. Any non-templated secret in the working tree is theater regardless of Vault posture.",
110
- "implicated_controls": ["nist-800-53-SC-12", "iso-27001-2022-A.8.24", "pci-dss-4-req-3"]
156
+ "implicated_controls": [
157
+ "nist-800-53-SC-12",
158
+ "iso-27001-2022-A.8.24",
159
+ "pci-dss-4-req-3"
160
+ ]
111
161
  },
112
162
  {
113
163
  "pattern_id": "pre-commit-hook-as-control",
114
164
  "claim": "Pre-commit hooks catch secrets before commit.",
115
165
  "fast_detection_test": "Check whether the repo's .pre-commit-config.yaml / lefthook.yml / husky config actually invokes a secret-scan tool AND whether the team has ever bypassed via --no-verify (visible in git log for repos with verified commits or in the reflog). Pre-commit is bypassable; pre-receive (server-side) is not. If only pre-commit exists, the control is advisory.",
116
- "implicated_controls": ["soc2-cc7.1", "iso-27001-2022-A.8.28"]
166
+ "implicated_controls": [
167
+ "soc2-cc7.1",
168
+ "iso-27001-2022-A.8.28"
169
+ ]
117
170
  }
118
171
  ],
119
172
  "framework_context": {
@@ -152,9 +205,13 @@
152
205
  }
153
206
  ]
154
207
  },
155
- "skill_preload": ["dlp-gap-analysis", "framework-gap-analysis", "compliance-theater", "policy-exception-gen"]
208
+ "skill_preload": [
209
+ "dlp-gap-analysis",
210
+ "framework-gap-analysis",
211
+ "compliance-theater",
212
+ "policy-exception-gen"
213
+ ]
156
214
  },
157
-
158
215
  "direct": {
159
216
  "threat_context": "Secret-in-repo is the #1 cause of cloud account compromise in 2025-2026 IR data. AI-coding-assistant adoption has accelerated the rate: AI assistants generate boilerplate that embeds API keys directly (Anthropic's own published guidance warns against this). GitGuardian Q1 2026 report: ~7.2M secrets leaked to public GitHub in Q1 alone, with OpenAI and Anthropic API keys representing the fastest-growing leak categories. Attack pattern: scraper bots monitor GitHub firehose for committed secrets within minutes of push; AWS keys are exploited within ~5 minutes of public exposure, often before the developer notices the commit. Working-tree scan (this playbook) catches the pre-commit window AND uncommitted secrets that CI scanners miss entirely (build artifacts, .env files in .gitignore, IaC tfvars files, .npmrc auth tokens).",
160
217
  "rwep_threshold": {
@@ -164,10 +221,27 @@
164
221
  },
165
222
  "framework_lag_declaration": "GDPR Art.32, ISO A.8.24, PCI-DSS Req.3, SOC 2 CC6.1 collectively cover encryption + key management + access control in production storage backends. None of them name 'secret in source artifact' as a distinct exposure category, despite this being the dominant 2025-2026 cloud-compromise vector. NIS2 Art.21(2)(j) names cryptography but not development-workflow exposure. Gap = ~30 days between developer commit and framework's quarterly access-review cadence; in practice, scraper bots exploit faster than any framework cadence.",
166
223
  "skill_chain": [
167
- { "skill": "dlp-gap-analysis", "purpose": "Inventory secret-shape findings in the working tree; assess exposure window; map to provider-specific rotation procedures.", "required": true },
168
- { "skill": "framework-gap-analysis", "purpose": "Map findings to which framework controls claim to address secret protection and where the gap is.", "required": true },
169
- { "skill": "compliance-theater", "purpose": "Run the theater test on the org's secret-scanning attestation (CI gitleaks + Vault posture).", "required": true },
170
- { "skill": "policy-exception-gen", "purpose": "Generate auditor-ready exception language for secrets that cannot be rotated immediately (e.g. requires coordinated multi-system rotation).", "skip_if": "close.exception_generation.trigger_condition == false", "required": false }
224
+ {
225
+ "skill": "dlp-gap-analysis",
226
+ "purpose": "Inventory secret-shape findings in the working tree; assess exposure window; map to provider-specific rotation procedures.",
227
+ "required": true
228
+ },
229
+ {
230
+ "skill": "framework-gap-analysis",
231
+ "purpose": "Map findings to which framework controls claim to address secret protection and where the gap is.",
232
+ "required": true
233
+ },
234
+ {
235
+ "skill": "compliance-theater",
236
+ "purpose": "Run the theater test on the org's secret-scanning attestation (CI gitleaks + Vault posture).",
237
+ "required": true
238
+ },
239
+ {
240
+ "skill": "policy-exception-gen",
241
+ "purpose": "Generate auditor-ready exception language for secrets that cannot be rotated immediately (e.g. requires coordinated multi-system rotation).",
242
+ "skip_if": "close.exception_generation.trigger_condition == false",
243
+ "required": false
244
+ }
171
245
  ],
172
246
  "token_budget": {
173
247
  "estimated_total": 19000,
@@ -182,7 +256,6 @@
182
256
  }
183
257
  }
184
258
  },
185
-
186
259
  "look": {
187
260
  "artifacts": [
188
261
  {
@@ -261,16 +334,43 @@
261
334
  }
262
335
  ],
263
336
  "fallback_if_unavailable": [
264
- { "artifact_id": "repo-tree", "fallback_action": "escalate_to_human", "confidence_impact": "high" },
265
- { "artifact_id": "env-files", "fallback_action": "mark_inconclusive", "confidence_impact": "medium" },
266
- { "artifact_id": "auth-config-files", "fallback_action": "mark_inconclusive", "confidence_impact": "medium" },
267
- { "artifact_id": "ssh-private-keys", "fallback_action": "mark_inconclusive", "confidence_impact": "high" },
268
- { "artifact_id": "iac-credential-bearers", "fallback_action": "mark_inconclusive", "confidence_impact": "medium" },
269
- { "artifact_id": "secret-regex-scan-text-files", "fallback_action": "escalate_to_human", "confidence_impact": "high" },
270
- { "artifact_id": "world-writable-secret-files", "fallback_action": "mark_inconclusive", "confidence_impact": "medium" }
337
+ {
338
+ "artifact_id": "repo-tree",
339
+ "fallback_action": "escalate_to_human",
340
+ "confidence_impact": "high"
341
+ },
342
+ {
343
+ "artifact_id": "env-files",
344
+ "fallback_action": "mark_inconclusive",
345
+ "confidence_impact": "medium"
346
+ },
347
+ {
348
+ "artifact_id": "auth-config-files",
349
+ "fallback_action": "mark_inconclusive",
350
+ "confidence_impact": "medium"
351
+ },
352
+ {
353
+ "artifact_id": "ssh-private-keys",
354
+ "fallback_action": "mark_inconclusive",
355
+ "confidence_impact": "high"
356
+ },
357
+ {
358
+ "artifact_id": "iac-credential-bearers",
359
+ "fallback_action": "mark_inconclusive",
360
+ "confidence_impact": "medium"
361
+ },
362
+ {
363
+ "artifact_id": "secret-regex-scan-text-files",
364
+ "fallback_action": "escalate_to_human",
365
+ "confidence_impact": "high"
366
+ },
367
+ {
368
+ "artifact_id": "world-writable-secret-files",
369
+ "fallback_action": "mark_inconclusive",
370
+ "confidence_impact": "medium"
371
+ }
271
372
  ]
272
373
  },
273
-
274
374
  "detect": {
275
375
  "indicators": [
276
376
  {
@@ -424,27 +524,91 @@
424
524
  "not_detected": "Full repo walk completed AND zero deterministic patterns matched AND no high-confidence patterns matched AND no world-writable secret files AND .ssh keys (if present) have mode 0600."
425
525
  }
426
526
  },
427
-
428
527
  "analyze": {
429
528
  "rwep_inputs": [
430
- { "signal_id": "aws-access-key-id", "rwep_factor": "active_exploitation", "weight": 30, "notes": "Scraper bots monetize within minutes of public exposure. Treat as exploitation-imminent." },
431
- { "signal_id": "aws-access-key-id", "rwep_factor": "ai_weaponization", "weight": 10, "notes": "AI-powered scrapers triage and weaponize at scale." },
432
- { "signal_id": "gcp-service-account-json", "rwep_factor": "active_exploitation", "weight": 30, "notes": "Same as AWS." },
433
- { "signal_id": "github-personal-access-token", "rwep_factor": "active_exploitation", "weight": 25, "notes": "PAT exposure = repo + CI compromise + supply chain pivot." },
434
- { "signal_id": "openai-api-key", "rwep_factor": "active_exploitation", "weight": 20, "notes": "Spend abuse is automatic; AI account compromise extends to fine-tunes / files / projects in account." },
435
- { "signal_id": "anthropic-api-key", "rwep_factor": "active_exploitation", "weight": 20, "notes": "Same as OpenAI." },
436
- { "signal_id": "ssh-private-key-block", "rwep_factor": "blast_radius", "weight": 20, "notes": "Inline private key = lateral movement primitive." },
437
- { "signal_id": "world-writable-env-file", "rwep_factor": "blast_radius", "weight": 15, "notes": "Tampering primitive on dev workstation; supply-chain implications if CI pulls from same path." },
438
- { "signal_id": "ssh-key-bad-perms", "rwep_factor": "blast_radius", "weight": 10, "notes": "Permission flaw enables credential theft by any local user." }
529
+ {
530
+ "signal_id": "aws-access-key-id",
531
+ "rwep_factor": "active_exploitation",
532
+ "weight": 30,
533
+ "notes": "Scraper bots monetize within minutes of public exposure. Treat as exploitation-imminent."
534
+ },
535
+ {
536
+ "signal_id": "aws-access-key-id",
537
+ "rwep_factor": "ai_weaponization",
538
+ "weight": 10,
539
+ "notes": "AI-powered scrapers triage and weaponize at scale."
540
+ },
541
+ {
542
+ "signal_id": "gcp-service-account-json",
543
+ "rwep_factor": "active_exploitation",
544
+ "weight": 30,
545
+ "notes": "Same as AWS."
546
+ },
547
+ {
548
+ "signal_id": "github-personal-access-token",
549
+ "rwep_factor": "active_exploitation",
550
+ "weight": 25,
551
+ "notes": "PAT exposure = repo + CI compromise + supply chain pivot."
552
+ },
553
+ {
554
+ "signal_id": "openai-api-key",
555
+ "rwep_factor": "active_exploitation",
556
+ "weight": 20,
557
+ "notes": "Spend abuse is automatic; AI account compromise extends to fine-tunes / files / projects in account."
558
+ },
559
+ {
560
+ "signal_id": "anthropic-api-key",
561
+ "rwep_factor": "active_exploitation",
562
+ "weight": 20,
563
+ "notes": "Same as OpenAI."
564
+ },
565
+ {
566
+ "signal_id": "ssh-private-key-block",
567
+ "rwep_factor": "blast_radius",
568
+ "weight": 20,
569
+ "notes": "Inline private key = lateral movement primitive."
570
+ },
571
+ {
572
+ "signal_id": "world-writable-env-file",
573
+ "rwep_factor": "blast_radius",
574
+ "weight": 15,
575
+ "notes": "Tampering primitive on dev workstation; supply-chain implications if CI pulls from same path."
576
+ },
577
+ {
578
+ "signal_id": "ssh-key-bad-perms",
579
+ "rwep_factor": "blast_radius",
580
+ "weight": 10,
581
+ "notes": "Permission flaw enables credential theft by any local user."
582
+ }
439
583
  ],
440
584
  "blast_radius_model": {
441
585
  "scope_question": "Given the secret(s) found in the working tree, what is the blast radius if this repo (or its working copy) is read by an unauthorized party?",
442
586
  "scoring_rubric": [
443
- { "condition": "Single test/expired/example credential matched with FP distinguishing test passing", "blast_radius_score": 1, "description": "False-positive shaped match; no live exposure." },
444
- { "condition": "Single non-production credential (test env, sandbox account) confirmed live", "blast_radius_score": 2, "description": "Sandbox-scope compromise. Cleanup required but limited." },
445
- { "condition": "Single production credential confirmed live (or unconfirmed but production-shaped) on a single-cloud or single-vendor account", "blast_radius_score": 3, "description": "Production single-account compromise. Spend + data exposure within that account's IAM scope." },
446
- { "condition": "Production credential AND credential has broad IAM scope (admin / wildcard / service-account JSON with project owner)", "blast_radius_score": 4, "description": "Cloud-account-wide compromise. Data exfil + resource creation + lateral to other tenants." },
447
- { "condition": "Multiple production credentials AND credentials span identity layers (cloud + SaaS + SCM) AND repo is or was public", "blast_radius_score": 5, "description": "Org-wide identity boundary collapse. Treat as confirmed incident." }
587
+ {
588
+ "condition": "Single test/expired/example credential matched with FP distinguishing test passing",
589
+ "blast_radius_score": 1,
590
+ "description": "False-positive shaped match; no live exposure."
591
+ },
592
+ {
593
+ "condition": "Single non-production credential (test env, sandbox account) confirmed live",
594
+ "blast_radius_score": 2,
595
+ "description": "Sandbox-scope compromise. Cleanup required but limited."
596
+ },
597
+ {
598
+ "condition": "Single production credential confirmed live (or unconfirmed but production-shaped) on a single-cloud or single-vendor account",
599
+ "blast_radius_score": 3,
600
+ "description": "Production single-account compromise. Spend + data exposure within that account's IAM scope."
601
+ },
602
+ {
603
+ "condition": "Production credential AND credential has broad IAM scope (admin / wildcard / service-account JSON with project owner)",
604
+ "blast_radius_score": 4,
605
+ "description": "Cloud-account-wide compromise. Data exfil + resource creation + lateral to other tenants."
606
+ },
607
+ {
608
+ "condition": "Multiple production credentials AND credentials span identity layers (cloud + SaaS + SCM) AND repo is or was public",
609
+ "blast_radius_score": 5,
610
+ "description": "Org-wide identity boundary collapse. Treat as confirmed incident."
611
+ }
448
612
  ]
449
613
  },
450
614
  "compliance_theater_check": {
@@ -484,45 +648,78 @@
484
648
  }
485
649
  ],
486
650
  "escalation_criteria": [
487
- { "condition": "rwep >= 90 AND credential_appears_live == true", "action": "page_on_call" },
488
- { "condition": "blast_radius_score >= 4", "action": "trigger_playbook", "target_playbook": "cred-stores" },
489
- { "condition": "compliance_theater_check.verdict == 'theater' AND jurisdiction_obligations contains 'EU'", "action": "notify_legal" },
490
- { "condition": "any_secret_in_committed_history == true", "action": "raise_severity" }
651
+ {
652
+ "condition": "rwep >= 90 AND credential_appears_live == true",
653
+ "action": "page_on_call"
654
+ },
655
+ {
656
+ "condition": "blast_radius_score >= 4",
657
+ "action": "trigger_playbook",
658
+ "target_playbook": "cred-stores"
659
+ },
660
+ {
661
+ "condition": "compliance_theater_check.verdict == 'theater' AND jurisdiction_obligations contains 'EU'",
662
+ "action": "notify_legal"
663
+ },
664
+ {
665
+ "condition": "any_secret_in_committed_history == true",
666
+ "action": "raise_severity"
667
+ }
491
668
  ]
492
669
  },
493
-
494
670
  "validate": {
495
671
  "remediation_paths": [
496
672
  {
497
673
  "id": "rotate-and-purge",
498
674
  "description": "(1) Rotate the credential at the provider (AWS IAM, GCP, GitHub, Slack, Stripe, OpenAI, Anthropic), (2) revoke any sessions tied to the old credential, (3) remove the literal from the working tree + replace with a Vault/Secrets Manager template, (4) if the credential ever entered git history, BFG / git-filter-repo the history AND notify any forks/mirrors.",
499
- "preconditions": ["provider_supports_revocation == true", "rotation_ownership_identified == true"],
675
+ "preconditions": [
676
+ "provider_supports_revocation == true",
677
+ "rotation_ownership_identified == true"
678
+ ],
500
679
  "priority": 1,
501
- "compensating_controls": ["session-revocation", "cloudtrail-or-audit-log-review-for-misuse-window"],
680
+ "compensating_controls": [
681
+ "session-revocation",
682
+ "cloudtrail-or-audit-log-review-for-misuse-window"
683
+ ],
502
684
  "estimated_time_hours": 2
503
685
  },
504
686
  {
505
687
  "id": "fix-file-permissions",
506
688
  "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.",
507
- "preconditions": ["file_owner_is_current_user OR has_sudo == true"],
689
+ "preconditions": [
690
+ "file_owner_is_current_user OR has_sudo == true"
691
+ ],
508
692
  "priority": 2,
509
- "compensating_controls": ["perm-change-recorded"],
693
+ "compensating_controls": [
694
+ "perm-change-recorded"
695
+ ],
510
696
  "estimated_time_hours": 0.5
511
697
  },
512
698
  {
513
699
  "id": "tighten-prevention",
514
700
  "description": "Install pre-commit hook + pre-receive server-side hook running gitleaks/trufflehog. Add .gitignore entries for env/auth-config files. Add CI step scanning build artifacts under dist/build.",
515
- "preconditions": ["repo_governance_authority == true"],
701
+ "preconditions": [
702
+ "repo_governance_authority == true"
703
+ ],
516
704
  "priority": 2,
517
- "compensating_controls": ["pre-commit-config-versioned", "ci-config-versioned"],
705
+ "compensating_controls": [
706
+ "pre-commit-config-versioned",
707
+ "ci-config-versioned"
708
+ ],
518
709
  "estimated_time_hours": 2
519
710
  },
520
711
  {
521
712
  "id": "policy-exception",
522
713
  "description": "If rotation requires coordinated multi-system rollout (e.g. credential is consumed by 50+ services), generate exception with bounded duration + compensating audit-log monitoring.",
523
- "preconditions": ["coordinated_rotation_required == true", "credential_misuse_monitoring_in_place == true"],
714
+ "preconditions": [
715
+ "coordinated_rotation_required == true",
716
+ "credential_misuse_monitoring_in_place == true"
717
+ ],
524
718
  "priority": 4,
525
- "compensating_controls": ["enhanced-audit-log-alerting-on-credential", "incident-response-team-on-standby"],
719
+ "compensating_controls": [
720
+ "enhanced-audit-log-alerting-on-credential",
721
+ "incident-response-team-on-standby"
722
+ ],
526
723
  "estimated_time_hours": 24
527
724
  }
528
725
  ],
@@ -562,46 +759,87 @@
562
759
  "risk": "Even after rotation + purge + hook installation, the prior credential may have been scraped during the exposure window. The credential is revoked, but any data exfiltrated during the window is gone.",
563
760
  "why_remains": "Credential exposure is irreversible at the data-exfil level. Revocation prevents future misuse but does not undo prior misuse. Audit log review establishes upper bound on misuse but cannot prove negative for all classes (e.g. provider API calls within normal-looking patterns).",
564
761
  "acceptance_level": "ciso",
565
- "compensating_controls_in_place": ["credential-rotated", "session-revoked", "audit-log-baseline-captured", "pre-commit-hook-active", "ci-secret-scan-extended-to-build-artifacts"]
762
+ "compensating_controls_in_place": [
763
+ "credential-rotated",
764
+ "session-revoked",
765
+ "audit-log-baseline-captured",
766
+ "pre-commit-hook-active",
767
+ "ci-secret-scan-extended-to-build-artifacts"
768
+ ]
566
769
  },
567
770
  "evidence_requirements": [
568
771
  {
569
772
  "evidence_type": "scan_report",
570
773
  "description": "Pre-remediation full working-tree scan output with file paths + line offsets + matched indicator IDs + RWEP per finding. Plus post-remediation rescan showing clean state.",
571
774
  "retention_period": "7_years",
572
- "framework_satisfied": ["gdpr-art-32", "iso-27001-2022-A.8.24", "soc2-cc6.1", "pci-dss-4-req-3"]
775
+ "framework_satisfied": [
776
+ "gdpr-art-32",
777
+ "iso-27001-2022-A.8.24",
778
+ "soc2-cc6.1",
779
+ "pci-dss-4-req-3"
780
+ ]
573
781
  },
574
782
  {
575
783
  "evidence_type": "log_excerpt",
576
784
  "description": "Provider audit log excerpt for the exposure window for each rotated credential.",
577
785
  "retention_period": "7_years",
578
- "framework_satisfied": ["gdpr-art-33", "soc2-cc7.2", "nis2-art21-2c"]
786
+ "framework_satisfied": [
787
+ "gdpr-art-33",
788
+ "soc2-cc7.2",
789
+ "nis2-art21-2c"
790
+ ]
579
791
  },
580
792
  {
581
793
  "evidence_type": "ticket_reference",
582
794
  "description": "Rotation ticket(s) with timestamps, approvers, provider rotation confirmation IDs.",
583
795
  "retention_period": "7_years",
584
- "framework_satisfied": ["soc2-cc8.1", "iso-27001-2022-A.8.32"]
796
+ "framework_satisfied": [
797
+ "soc2-cc8.1",
798
+ "iso-27001-2022-A.8.32"
799
+ ]
585
800
  },
586
801
  {
587
802
  "evidence_type": "attestation",
588
803
  "description": "Signed exceptd attestation: repo identity, scan timestamp, finding count, RWEP at detection, RWEP post-remediation, rotated credential IDs (hashed).",
589
804
  "retention_period": "7_years",
590
- "framework_satisfied": ["nist-800-53-CA-7", "iso-27001-2022-A.5.36", "nis2-art21-2c"]
805
+ "framework_satisfied": [
806
+ "nist-800-53-CA-7",
807
+ "iso-27001-2022-A.5.36",
808
+ "nis2-art21-2c"
809
+ ]
591
810
  }
592
811
  ],
593
812
  "regression_trigger": [
594
- { "condition": "pre_commit", "interval": "on_event" },
595
- { "condition": "weekly", "interval": "7d" },
596
- { "condition": "post_dependency_update", "interval": "on_event" },
597
- { "condition": "new_secret_pattern_published", "interval": "on_event" }
813
+ {
814
+ "condition": "pre_commit",
815
+ "interval": "on_event"
816
+ },
817
+ {
818
+ "condition": "weekly",
819
+ "interval": "7d"
820
+ },
821
+ {
822
+ "condition": "post_dependency_update",
823
+ "interval": "on_event"
824
+ },
825
+ {
826
+ "condition": "new_secret_pattern_published",
827
+ "interval": "on_event"
828
+ }
598
829
  ]
599
830
  },
600
-
601
831
  "close": {
602
832
  "evidence_package": {
603
833
  "bundle_format": "json",
604
- "contents": ["scan_report", "log_excerpt", "ticket_reference", "attestation", "framework_gap_mapping", "compliance_theater_verdict", "residual_risk_statement"],
834
+ "contents": [
835
+ "scan_report",
836
+ "log_excerpt",
837
+ "ticket_reference",
838
+ "attestation",
839
+ "framework_gap_mapping",
840
+ "compliance_theater_verdict",
841
+ "residual_risk_statement"
842
+ ],
605
843
  "destination": "local_only",
606
844
  "signed": true
607
845
  },
@@ -613,42 +851,63 @@
613
851
  "framework_gap": "GDPR Art.32 / ISO A.8.24 / PCI Req.3 / SOC 2 CC6.1 + NIS2 Art.21(2)(j) collectively cover storage backend protection. None name source-artifact exposure as a distinct control class.",
614
852
  "new_control_requirement": "Continuous working-tree scanning + pre-commit + pre-receive secret blocking + build-artifact scan + Vault-templated secret enforcement. Source-artifact exposure becomes its own control class with quarterly attestation requirement."
615
853
  },
616
- "feeds_back_to_skills": ["dlp-gap-analysis", "framework-gap-analysis", "compliance-theater"]
854
+ "feeds_back_to_skills": [
855
+ "dlp-gap-analysis",
856
+ "framework-gap-analysis",
857
+ "compliance-theater"
858
+ ]
617
859
  },
618
860
  "notification_actions": [
619
861
  {
620
862
  "obligation_ref": "EU/GDPR Art.33 72h",
621
863
  "deadline": "computed_at_runtime",
622
864
  "recipient": "internal_legal",
623
- "evidence_attached": ["secret_inventory", "data_subject_impact_assessment", "containment_record"],
865
+ "evidence_attached": [
866
+ "secret_inventory",
867
+ "data_subject_impact_assessment",
868
+ "containment_record"
869
+ ],
624
870
  "draft_notification": "GDPR Art.33 72-hour notification: Credential exposure event affecting ${credential_count} credential(s) of type ${credential_class}. Exposure window: ${exposure_window}. Affected processing operations: ${processing_operations}. Categories of data subjects potentially affected: ${data_subject_categories}. Containment actions: credentials rotated, sessions revoked, audit logs reviewed for misuse. Risk assessment: ${risk_level}. No notification to data subjects required because ${art34_reasoning} OR notification to data subjects required and being prepared. Contact: ${dpo_contact}."
625
871
  },
626
872
  {
627
873
  "obligation_ref": "EU/GDPR Art.34 72h",
628
874
  "deadline": "computed_at_runtime",
629
875
  "recipient": "data_subjects",
630
- "evidence_attached": ["data_subject_categories_affected", "containment_record"],
876
+ "evidence_attached": [
877
+ "data_subject_categories_affected",
878
+ "containment_record"
879
+ ],
631
880
  "draft_notification": "GDPR Art.34 notification to data subjects (draft for review): We are writing to inform you of a credential exposure incident affecting systems that process your personal data. Affected systems: ${affected_systems}. Exposure window: ${exposure_window}. Containment actions completed: credentials rotated and revoked, audit logs reviewed. Steps you can take: ${recommended_actions}. Our DPO can be reached at ${dpo_contact}."
632
881
  },
633
882
  {
634
883
  "obligation_ref": "EU/NIS2 Art.23 24h",
635
884
  "deadline": "computed_at_runtime",
636
885
  "recipient": "internal_legal",
637
- "evidence_attached": ["secret_inventory", "exposure_window_estimate", "rotation_status"],
886
+ "evidence_attached": [
887
+ "secret_inventory",
888
+ "exposure_window_estimate",
889
+ "rotation_status"
890
+ ],
638
891
  "draft_notification": "NIS2 Art.23 early-warning notification: Credential exposure ${credential_class} on ${affected_system_count} system(s). Suspected window of exposure: ${exposure_window}. Initial containment: credentials rotated. Full incident assessment within 72h per Art.23(4)."
639
892
  },
640
893
  {
641
894
  "obligation_ref": "UK/UK GDPR Art.33 72h",
642
895
  "deadline": "computed_at_runtime",
643
896
  "recipient": "internal_legal",
644
- "evidence_attached": ["secret_inventory", "data_subject_impact_assessment"],
897
+ "evidence_attached": [
898
+ "secret_inventory",
899
+ "data_subject_impact_assessment"
900
+ ],
645
901
  "draft_notification": "UK GDPR Art.33 72-hour notification to ICO: Credential exposure event. Mirror of GDPR Art.33 notification body, addressed to ICO casework team."
646
902
  },
647
903
  {
648
904
  "obligation_ref": "US-CA/CCPA / CPRA Sec.1798.82 1440h",
649
905
  "deadline": "computed_at_runtime",
650
906
  "recipient": "data_subjects",
651
- "evidence_attached": ["california_resident_records_affected", "containment_record"],
907
+ "evidence_attached": [
908
+ "california_resident_records_affected",
909
+ "containment_record"
910
+ ],
652
911
  "draft_notification": "California breach notification: We are writing to notify you of a security incident that may have affected your personal information. ${incident_description}. ${types_of_information_affected}. ${steps_taken}. ${steps_individuals_can_take}. ${contact_information}."
653
912
  }
654
913
  ],
@@ -657,7 +916,12 @@
657
916
  "exception_template": {
658
917
  "scope": "Credential of class ${credential_class} (${credential_id_hash}) cannot be rotated within ${obligation_window} due to ${blocking_reason}.",
659
918
  "duration": "until_vendor_patch",
660
- "compensating_controls": ["enhanced-audit-log-alerting-on-credential-use", "incident-response-team-on-standby", "ip-allowlist-tightened-on-credential", "rate-limit-on-credential-tightened"],
919
+ "compensating_controls": [
920
+ "enhanced-audit-log-alerting-on-credential-use",
921
+ "incident-response-team-on-standby",
922
+ "ip-allowlist-tightened-on-credential",
923
+ "rate-limit-on-credential-tightened"
924
+ ],
661
925
  "risk_acceptance_owner": "ciso",
662
926
  "auditor_ready_language": "Pursuant to ${framework_id} ${control_id}, the organization documents a time-bound risk acceptance for unrotated credential ${credential_class} (${credential_id_hash}) on ${affected_system_count} system(s). Blocking reason: ${blocking_reason_narrative}. Rotation ETA: ${rotation_eta}. Compensating controls in place: ${compensating_controls}. Residual exposure: credential remains valid; provider audit logs are reviewed daily during the exception window for misuse indicators. Risk accepted by ${ciso_name} on ${acceptance_date}. Time-bound until ${duration_expiry} OR rotation completion, whichever is first. Detection coverage is provided by ${detection_controls}. The exception will be re-evaluated on (a) rotation completion, (b) listed expiry date, (c) any audit-log anomaly on the credential — whichever is first."
663
927
  }
@@ -669,22 +933,27 @@
669
933
  }
670
934
  }
671
935
  },
672
-
673
936
  "directives": [
674
937
  {
675
938
  "id": "full-repo-secret-scan",
676
939
  "title": "Full working-tree secret scan with all catalogued patterns + permission checks",
677
- "applies_to": { "always": true }
940
+ "applies_to": {
941
+ "always": true
942
+ }
678
943
  },
679
944
  {
680
945
  "id": "high-velocity-credentials",
681
946
  "title": "Targeted directive — AWS / GCP / GitHub / OpenAI / Anthropic high-velocity credentials",
682
- "applies_to": { "attack_technique": "T1552.001" }
947
+ "applies_to": {
948
+ "attack_technique": "T1552.001"
949
+ }
683
950
  },
684
951
  {
685
952
  "id": "private-key-material",
686
953
  "title": "Targeted directive — SSH/PEM private key material in working tree",
687
- "applies_to": { "attack_technique": "T1552.004" }
954
+ "applies_to": {
955
+ "attack_technique": "T1552.004"
956
+ }
688
957
  }
689
958
  ]
690
959
  }