nsauditor-ai-agent-skill 0.2.31 → 0.2.33

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -4,6 +4,20 @@ Release notes for **`nsauditor-ai-agent-skill`** — installable knowledge packa
4
4
 
5
5
  ---
6
6
 
7
+ ## 0.2.33 (2026-08-03) — Paired with EE 0.32.10 · no knowledge change, one honesty correction upstream
8
+
9
+ **No change to the skill's guidance, schemas, or plugin references.** Published in lockstep with Enterprise 0.32.10 and CE 0.2.35 so an agent installing the trio never mixes versions.
10
+
11
+ Worth knowing if you are teaching an agent to reason about NSAuditor's evidence: the Enterprise release corrects what its dependency-advisory gate measures (the packed-and-installed customer closure, not the maintainer's working tree) and makes it prove an advisory source answered before reporting clean. The SOC 2 matrix is now enumerated in full at **10 / 4 / 37 = 51** — enumeration completeness, not a coverage change. Plugin catalog UNCHANGED at **28 EE / 55 overall**.
12
+
13
+ ## 0.2.32 (2026-07-29) — Paired with EE 0.32.9 · the skill package's own provenance sweep
14
+
15
+ **This package carried the marker class the EE cycle existed to kill, and npm freezes it at publish.** `references/plugins.md` is loaded into an LLM's context and quoted back to customers. Swept from the shipped `files[]` set: **330 occurrences → 0** — memory-slug wiki links (19), reviewer-fold codes (274), internal roadmap ids (35) and internal audit-review names (5).
16
+
17
+ **`EE 0.x.y` version stamps are deliberately KEPT** — 382 of them, count asserted unchanged. In a changelog, and in "NEW EE 0.7.0" in the plugin catalogue, the version IS the useful provenance: it tells a reader which release introduced a capability.
18
+
19
+ Paired EE 0.32.9 highlights: the evidence pack no longer carries internal roadmap ids; a cloud scanner that could not run no longer renders as a clean PASS; and the evidence-gap routing prefix changed value (re-point text-matched suppressions — see the EE CHANGELOG).
20
+
7
21
  ## 0.2.31 (2026-07-28) — paired content bump for EE 0.32.8 (capability-claim honesty pass, part 2: the air-gapped-delivery class)
8
22
 
9
23
  - **Two corrections in this package's own tier tables — both were overclaims this skill would otherwise teach an agent to repeat.** `SKILL.md` line 524 listed **"RFC 3161 timestamps"** unhedged among shipping Enterprise capabilities; RFC 3161 timestamping is *implemented but not yet wired to a flag*, so the row now says so explicitly and directs readers not to quote it as shipping. **SHA-256 chain-of-custody is the layer that ships.** Both `SKILL.md` and `README.md` also said **"air-gapped deployment"**, which implied a delivery mechanism that does not exist; both now say **"air-gapped operation (offline licensing + offline CVE matching under `NSAUDITOR_OFFLINE_ONLY=1`)"**.
@@ -176,7 +190,7 @@ SKILL.md now teaches the `scan_cloud` `regions` argument: AWS region codes (e.g.
176
190
 
177
191
  ## 0.1.60 (2026-05-30) — Paired-release for EE 0.16.2 + CE 0.1.93 — **SKILL.md updated**: teaches the NEW MCP `scan_cloud` tool (audit AWS/GCP/Azure accounts directly, no network host) — added to the Pro/Enterprise Tools table (Enterprise tier) + the "which tool to use" decision tree, plus a result-interpretation rule ("a cloud was effectively audited only if it's in `auditedProviders`; `audited:false` / `notes` / `pluginsRan:0` means NOT audited — never report a clean pass"). Feature lives in CE 0.1.93; plugin count UNCHANGED (28); all six matrices UNCHANGED.
178
192
 
179
- ## 0.1.59 (2026-05-30) — Paired-release pin for EE 0.16.1 + CE 0.1.92 — MCP `NSA_ENV_FILE`: the MCP server now loads a per-environment dotenv file named by `NSA_ENV_FILE` at startup (the MCP analog of the 0.16.0 CLI `--env`), so an operator points the server at a specific account/cloud by changing one path in the Claude Desktop / Claude Code config. Loaded after auth + license (scan-target vars only); fail-fast + authoritative-file ambient-cred clearing close a false-clean caught by the `audit-cloud-plugin-false-negatives` review. Feature lives in CE; plugin count UNCHANGED (28); all six matrices UNCHANGED. SKILL.md/references unchanged.
193
+ ## 0.1.59 (2026-05-30) — Paired-release pin for EE 0.16.1 + CE 0.1.92 — MCP `NSA_ENV_FILE`: the MCP server now loads a per-environment dotenv file named by `NSA_ENV_FILE` at startup (the MCP analog of the 0.16.0 CLI `--env`), so an operator points the server at a specific account/cloud by changing one path in the Claude Desktop / Claude Code config. Loaded after auth + license (scan-target vars only); fail-fast + authoritative-file ambient-cred clearing close a false-clean caught by the framework audit review. Feature lives in CE; plugin count UNCHANGED (28); all six matrices UNCHANGED. SKILL.md/references unchanged.
180
194
 
181
195
  ## 0.1.58 (2026-05-29) — Paired-release pin for EE 0.16.0 + CE 0.1.91 — CLI per-account scanning: `--env` / `--aws-profile` flags + sentinel-host plugin scoping (`--host aws|gcp|azure` + `--plugins all` runs only that cloud's plugins); EE adds a declarative `cloudProvider` field to all 27 cloud plugins. Plugin count UNCHANGED (28); all six matrices UNCHANGED. SKILL.md/references unchanged.
182
196
 
@@ -198,7 +212,7 @@ Paired no-op bump (no standalone agent-skill content change; SKILL.md + `referen
198
212
 
199
213
  ## 0.1.52 (PUBLISHED 2026-05-28) — Paired-release pin for EE 0.15.4 + CE 0.1.85 — plugin 1020 non-current-version ACL sampling + public WRITE-vs-READ differentiation
200
214
 
201
- Paired-release pin for the EE 0.15.4 patch cycle: closes the two residuals the 0.15.3 spec §8 carried as deferred. **(R-MEDIUM-2)** NEW step 2c-v samples public ACLs on **non-current** object versions — on versioning-Enabled/Suspended buckets plugin 1020 calls `ListObjectVersions` (first-page, bounded by `AWS_S3_AUDIT_OBJECT_SAMPLE_CAP`), filters to `IsLatest !== true`, skips `DeleteMarkers`, reads each via `GetObjectAcl({Key, VersionId})`; closes the Class-B miss where a private current object retains a public-ACL overwritten version still served at `?versionId=`. Public `AllUsers`/`AuthenticatedUsers` grant → CRITICAL via the existing `"publicly accessible"` anchor; skipped on `BucketOwnerEnforced`. **(R-LOW-1)** NEW `extractPublicWriteGroups` helper flags public WRITE/WRITE_ACP/FULL_CONTROL grants (anyone-can-overwrite) distinctly from READ-only as an enrichment line on the already-CRITICAL finding. New evidence-gaps (`ListObjectVersions AccessDenied` naming `s3:ListBucketVersions`; per-version aggregate-failure threshold; version-list truncation; a folded `GetBucketVersioning AccessDenied` gap) reuse the existing `"S3 object-ACL evidence-gap"` anchor — never a silent PASS. **Plugin count UNCHANGED at 28 (cloud-substrate 27); all six coverage matrices UNCHANGED; ZERO framework-JSON edits.** No new dependencies; EE regression 6628/6628 GREEN (+27 tests vs the 6601 baseline). No standalone agent-skill code changes — `SKILL.md` + `references/plugins.md` use generic framing (no plugin row change). _(Staged on `main`; awaiting live AWS smoke + trio publish.)_
215
+ Paired-release pin for the EE 0.15.4 patch cycle: closes the two residuals the 0.15.3 spec §8 carried as deferred. NEW step 2c-v samples public ACLs on **non-current** object versions — on versioning-Enabled/Suspended buckets plugin 1020 calls `ListObjectVersions` (first-page, bounded by `AWS_S3_AUDIT_OBJECT_SAMPLE_CAP`), filters to `IsLatest !== true`, skips `DeleteMarkers`, reads each via `GetObjectAcl({Key, VersionId})`; closes the Class-B miss where a private current object retains a public-ACL overwritten version still served at `?versionId=`. Public `AllUsers`/`AuthenticatedUsers` grant → CRITICAL via the existing `"publicly accessible"` anchor; skipped on `BucketOwnerEnforced`. NEW `extractPublicWriteGroups` helper flags public WRITE/WRITE_ACP/FULL_CONTROL grants (anyone-can-overwrite) distinctly from READ-only as an enrichment line on the already-CRITICAL finding. New evidence-gaps (`ListObjectVersions AccessDenied` naming `s3:ListBucketVersions`; per-version aggregate-failure threshold; version-list truncation; a folded `GetBucketVersioning AccessDenied` gap) reuse the existing `"S3 object-ACL evidence-gap"` anchor — never a silent PASS. **Plugin count UNCHANGED at 28 (cloud-substrate 27); all six coverage matrices UNCHANGED; ZERO framework-JSON edits.** No new dependencies; EE regression 6628/6628 GREEN (+27 tests vs the 6601 baseline). No standalone agent-skill code changes — `SKILL.md` + `references/plugins.md` use generic framing (no plugin row change). _(Staged on `main`; awaiting live AWS smoke + trio publish.)_
202
216
 
203
217
  ## 0.1.51 (2026-05-28) — Paired-release pin for EE 0.15.3 + CE 0.1.84 — plugin 1020 object-level ACL enumeration + BucketOwnerEnforced short-circuit
204
218
 
@@ -218,7 +232,7 @@ Paired-release pin for the EE 0.15.0 cycle (Move C-2.3): NEW **plugin 1222 `azur
218
232
 
219
233
  ## 0.1.47 (PUBLISHED 2026-05-27) — Paired-release pin for EE 0.14.1 + CE 0.1.80 — plugin 1221 UDP restricted-port lane
220
234
 
221
- Paired-release pin for the EE 0.14.1 cycle: plugin 1221 (the Azure NSG perimeter auditor) gains a **UDP restricted-port lane** (Dim 2u/3u) — tiering UDP management/amplification services (SNMP 161 / CLDAP 389 / NTP 123 / rpcbind 111 / IPMI 623 / IKE 500 / Memcached 11211, etc.) in parallel with the existing TCP lane, attachment-aware (attached → CRITICAL effective; orphaned → MEDIUM latent) with per-transport priority/deny-override resolution — closing the R-MEDIUM-2 false negative where a public UDP service was silently treated as benign non-restricted "web tier" INFO. Dim-4 made protocol-aware. The six framework titlePatterns for 1221 were generalized `permits TCP inbound …` → `permits (?:TCP|UDP) inbound …` so UDP findings route to the same CC6.6/perimeter controls. **Plugin count UNCHANGED at 27 (cloud-substrate 25); all six coverage matrices UNCHANGED.** `references/plugins.md` 1221 row updated to the UDP lane. No standalone agent-skill code changes.
235
+ Paired-release pin for the EE 0.14.1 cycle: plugin 1221 (the Azure NSG perimeter auditor) gains a **UDP restricted-port lane** (Dim 2u/3u) — tiering UDP management/amplification services (SNMP 161 / CLDAP 389 / NTP 123 / rpcbind 111 / IPMI 623 / IKE 500 / Memcached 11211, etc.) in parallel with the existing TCP lane, attachment-aware (attached → CRITICAL effective; orphaned → MEDIUM latent) with per-transport priority/deny-override resolution — closing the false negative where a public UDP service was silently treated as benign non-restricted "web tier" INFO. Dim-4 made protocol-aware. The six framework titlePatterns for 1221 were generalized `permits TCP inbound …` → `permits (?:TCP|UDP) inbound …` so UDP findings route to the same CC6.6/perimeter controls. **Plugin count UNCHANGED at 27 (cloud-substrate 25); all six coverage matrices UNCHANGED.** `references/plugins.md` 1221 row updated to the UDP lane. No standalone agent-skill code changes.
222
236
 
223
237
  ## 0.1.46 (PUBLISHED 2026-05-26) — Paired-release pin for EE 0.14.0 + CE 0.1.79 — NEW plugin 1221 (Azure NSG Perimeter Auditor)
224
238
 
@@ -238,7 +252,7 @@ Paired-release pin for the EE 0.13.1 cycle: CIS-Hardened-Image detection goes LI
238
252
 
239
253
  ## 0.1.42 (PUBLISHED 2026-05-24) — Paired-release pin for EE 0.13.0 + CE 0.1.75 — CIS Critical Security Controls v8 sixth-framework introduction
240
254
 
241
- **Cycle hook**: EE 0.13.0 ships CIS Critical Security Controls v8 (Center for Internet Security, May 2021; v8.1 errata June 2024) as the sixth Track 3 framework — **17 covered + 21 partial + 115 OOS across 153 Safeguards / 18 Controls / 3 cumulative Implementation Groups** (engine substrate IG1 23-of-56 / IG2-cumulative 36-of-130 / IG3-cumulative 38-of-153). Implementation Group cumulative discipline (IG1=56 cyber-insurance baseline / IG2 cumulative=130 / IG3 cumulative=153; smallest-IG-membership tagging) + no-certification-body attestation discipline (CSAT / CIS-CAT Pro self-attestation, never "CIS certified") + Cloud Companion Guide v8 shared-responsibility + CIS-Hardened-Image substrate-evidence credit (4.1/4.2/4.6) + 5 Security Functions NOT 6 (no Govern) + 6 Asset Types + MS-ISAC/EI-ISAC/H-ISAC sector baselines + v7.1-to-v8 cross-reference. Skill #19 `audit-cis-controls-v8-implementation-group-perspective` authored 2026-05-24 via /skill-creator (833 lines / 5 files) per the institutional Per-Framework Adversarial-Audit Skill Pairing pattern. **`compliance_check` SKILL.md row updated FIVE → SIX shipped frameworks** with CIS Safeguard examples + IG-cumulative + no-cert-body attestation framing. No other agent-skill code changes — paired-publish for trio-publish discipline + customer discoverability.
255
+ **Cycle hook**: EE 0.13.0 ships CIS Critical Security Controls v8 (Center for Internet Security, May 2021; v8.1 errata June 2024) as the sixth Track 3 framework — **17 covered + 21 partial + 115 OOS across 153 Safeguards / 18 Controls / 3 cumulative Implementation Groups** (engine substrate IG1 23-of-56 / IG2-cumulative 36-of-130 / IG3-cumulative 38-of-153). Implementation Group cumulative discipline (IG1=56 cyber-insurance baseline / IG2 cumulative=130 / IG3 cumulative=153; smallest-IG-membership tagging) + no-certification-body attestation discipline (CSAT / CIS-CAT Pro self-attestation, never "CIS certified") + Cloud Companion Guide v8 shared-responsibility + CIS-Hardened-Image substrate-evidence credit (4.1/4.2/4.6) + 5 Security Functions NOT 6 (no Govern) + 6 Asset Types + MS-ISAC/EI-ISAC/H-ISAC sector baselines + v7.1-to-v8 cross-reference. a dedicated framework audit review authored 2026-05-24 via /skill-creator (833 lines / 5 files) per the institutional Per-Framework Adversarial-Audit Skill Pairing pattern. **`compliance_check` SKILL.md row updated FIVE → SIX shipped frameworks** with CIS Safeguard examples + IG-cumulative + no-cert-body attestation framing. No other agent-skill code changes — paired-publish for trio-publish discipline + customer discoverability.
242
256
 
243
257
  **Plugin catalog**: UNCHANGED at 24 plugins; MCP tool signatures unchanged; schemas unchanged; workflows unchanged. **SOC 2 + HIPAA + NIST CSF + PCI DSS + ISO 27001 matrices ALL UNCHANGED**; **CIS Controls v8 matrix NEW at 17/21/115 across 153 Safeguards**.
244
258
 
@@ -248,7 +262,7 @@ Paired-release pin for the EE 0.13.1 cycle: CIS-Hardened-Image detection goes LI
248
262
 
249
263
  ## 0.1.41 (PUBLISHED 2026-05-24) — Paired-release pin for EE 0.12.0 + CE 0.1.74 — ISO/IEC 27001:2022 fifth-framework introduction
250
264
 
251
- **Cycle hook**: EE 0.12.0 ships ISO/IEC 27001:2022 as the fifth Track 3 framework — 17 covered + 14 partial + 62 OOS across 93 Annex A controls (the complete Annex A universe across 4 themes). Statement of Applicability per Clause 6.1.3.d discipline + ISMS Clauses 4-10 OOS-by-design framing + 11 NEW 2022 controls + 5-attribute taxonomy + 2013-to-2022 transition discipline. Skill #18 `audit-iso-27001-2022-statement-of-applicability` authored 2026-05-24 via /skill-creator (705 lines / 5 files) per the institutional Per-Framework Adversarial-Audit Skill Pairing pattern. No agent-skill code changes — paired-publish for trio-publish discipline + customer discoverability.
265
+ **Cycle hook**: EE 0.12.0 ships ISO/IEC 27001:2022 as the fifth Track 3 framework — 17 covered + 14 partial + 62 OOS across 93 Annex A controls (the complete Annex A universe across 4 themes). Statement of Applicability per Clause 6.1.3.d discipline + ISMS Clauses 4-10 OOS-by-design framing + 11 NEW 2022 controls + 5-attribute taxonomy + 2013-to-2022 transition discipline. a dedicated framework audit review authored 2026-05-24 via /skill-creator (705 lines / 5 files) per the institutional Per-Framework Adversarial-Audit Skill Pairing pattern. No agent-skill code changes — paired-publish for trio-publish discipline + customer discoverability.
252
266
 
253
267
  **Plugin catalog**: UNCHANGED at 24 plugins; MCP tool signatures unchanged; schemas unchanged; workflows unchanged. **SOC 2 + HIPAA + NIST CSF + PCI DSS matrices ALL UNCHANGED**; **ISO/IEC 27001:2022 matrix NEW at 17/14/62 across 93 Annex A controls**.
254
268
 
@@ -256,9 +270,9 @@ Paired-release pin for the EE 0.13.1 cycle: CIS-Hardened-Image detection goes LI
256
270
 
257
271
  ---
258
272
 
259
- ## 0.1.40 (PUBLISHED 2026-05-23 to npm as `latest`) — Paired-release pin for EE 0.11.1 + CE 0.1.73 — PCI DSS v4.0.1 patch cycle (CAO authorship + 4 R-MEDIUM folds + `license --reset` subcommand)
273
+ ## 0.1.40 (PUBLISHED 2026-05-23 to npm as `latest`) — Paired-release pin for EE 0.11.1 + CE 0.1.73 — PCI DSS v4.0.1 patch cycle (CAO authorship + 4 folds + `license --reset` subcommand)
260
274
 
261
- **Cycle hook**: EE 0.11.1 ships the PCI DSS v4.0.1 patch cycle — the 4 R-MEDIUM authoring folds deferred from the EE 0.11.0 reviewer pass (CDE-scope badge + Req 12.8.5 TPSP matrix renderer + QSA enforcement-priority ranked view + CAO authorship for all 26 customized-eligible sub-requirements per Appendix D) PLUS the operator-discovered `nsauditor-ai license --reset` subcommand on the CE side. No agent-skill code changes — paired-publish for trio-publish discipline + customer discoverability.
275
+ **Cycle hook**: EE 0.11.1 ships the PCI DSS v4.0.1 patch cycle — the 4 authoring folds deferred from the EE 0.11.0 reviewer pass (CDE-scope badge + Req 12.8.5 TPSP matrix renderer + QSA enforcement-priority ranked view + CAO authorship for all 26 customized-eligible sub-requirements per Appendix D) PLUS the operator-discovered `nsauditor-ai license --reset` subcommand on the CE side. No agent-skill code changes — paired-publish for trio-publish discipline + customer discoverability.
262
276
 
263
277
  **Plugin catalog**: UNCHANGED at 24 plugins; MCP tool signatures unchanged; schemas unchanged; workflows unchanged. **Coverage matrices ALL UNCHANGED** (SOC 2 10/4/33 + HIPAA 7/3/45 + NIST CSF 2.0 13/10/83 + PCI DSS 20/8/39 MVP-67 — pure patch cycle, no framework expansion).
264
278
 
@@ -292,13 +306,13 @@ Paired-release pin for the EE 0.13.1 cycle: CIS-Hardened-Image detection goes LI
292
306
 
293
307
  **EE 0.10.0 + CE 0.1.71 paired-release highlights** (full detail in respective CHANGELOGs):
294
308
  - NEW `data/compliance/nist-csf.json` — auditor-canonical Subcategory-level mapping. 23 declared Subcategories + 6 OOS groups + schema-additive `function` / `categoryCode` / `subcategory` / `outcomeText` / `informativeReferences` fields. Inheritance contract: every titlePattern inherits from soc2.json's grep-verified pattern set, defended by 27-test anchor-drift suite.
295
- - EXTENDED EE `utils/soc2_renderer.mjs` — `'nist-csf'` slot table in `frameworkControlCitation` with 8 slots incl. NEW `implementation-tiers` disclaimer. `isNistCsfReport` flag detection. Implementation Tiers OOS disclaimer section in BOTH markdown AND HTML render paths (R-HIGH-2 reviewer fold from 2nd reviewer pass — markdown-only was the pre-fold state).
296
- - Schema-additive fields propagation to controlEntries — closes ghost-schema gap for `function`/`categoryCode`/`subcategory`/`outcomeText`/`informativeReferences` (NIST CSF) AND `requiredOrAddressable`/`standardOrSpec`/`ruleText` (HIPAA, EE 0.9.0 inherited gap) AND `manualProcedure` (SOC 2 + HIPAA, EE 0.9.3 + 0.9.4 inherited gap). R-HIGH-1 reviewer fold from 2nd reviewer pass.
297
- - 91 net new tests across 3 new test files (27 anchor-drift + 39 mapping + 25 renderer) + 1 fold-driven SOC 2→NIST cross-framework leak test (R-MEDIUM-1 from 2nd reviewer pass)
309
+ - EXTENDED EE `utils/soc2_renderer.mjs` — `'nist-csf'` slot table in `frameworkControlCitation` with 8 slots incl. NEW `implementation-tiers` disclaimer. `isNistCsfReport` flag detection. Implementation Tiers OOS disclaimer section in BOTH markdown AND HTML render paths (reviewer fold from 2nd reviewer pass — markdown-only was the pre-fold state).
310
+ - Schema-additive fields propagation to controlEntries — closes ghost-schema gap for `function`/`categoryCode`/`subcategory`/`outcomeText`/`informativeReferences` (NIST CSF) AND `requiredOrAddressable`/`standardOrSpec`/`ruleText` (HIPAA, EE 0.9.0 inherited gap) AND `manualProcedure` (SOC 2 + HIPAA, EE 0.9.3 + 0.9.4 inherited gap). reviewer fold from 2nd reviewer pass.
311
+ - 91 net new tests across 3 new test files (27 anchor-drift + 39 mapping + 25 renderer) + 1 fold-driven SOC 2→NIST cross-framework leak test (from 2nd reviewer pass)
298
312
  - 560-line `docs/nist-csf-coverage.md`
299
313
  - 2 reviewer passes (single-agent A combined NIST/code lens + parallel-reviewer B security/air-gap/citation-leak lens); 5 same-session folds total
300
314
 
301
- **Reviewer pass discipline**: 2-reviewer parallel pass per the EE 0.9.0 institutional template. Reviewer A verdict "ship with 4 small folds — cycle is structurally clean"; Reviewer B verdict "ship with 2 small folds beyond Reviewer A's findings — 2 R-HIGH genuinely new + 3 polish". 5 of 10 findings applied same-session (3 from Reviewer B + 2 from Reviewer A); 5 deferred as defer-acceptable polish.
315
+ **Reviewer pass discipline**: 2-reviewer parallel pass per the EE 0.9.0 institutional template. Reviewer A verdict "ship with 4 small folds — cycle is structurally clean"; Reviewer B verdict "ship with 2 small folds beyond Reviewer A's findings — 2 genuinely new + 3 polish". 5 of 10 findings applied same-session (3 from Reviewer B + 2 from Reviewer A); 5 deferred as defer-acceptable polish.
302
316
 
303
317
  **Regression**: EE 6104/6104 across 983 suites (+92 vs 0.9.4 baseline — 91 cycle-new tests + 1 fold-driven cross-framework leak test). 75-session 100% green streak preserved. **Plugin count UNCHANGED at 24**; **SOC 2 + HIPAA coverage matrices UNCHANGED at 10/4/33 + 7/3/45**; **NIST CSF 2.0 coverage matrix introduced at 13/10/83**.
304
318
 
@@ -363,7 +377,7 @@ EE's `loadFrameworkMap` was already framework-agnostic (reads `data/compliance/{
363
377
 
364
378
  Zero Data Exfiltration architecture means ePHI never leaves customer infrastructure. Nsasoft does not see, store, or process customer ePHI under any condition — no Business Associate Agreement needed. This is a self-hosted scanner, not a SaaS service.
365
379
 
366
- ### 6 same-session reviewer folds applied (2 R-HIGH + 2 R-MEDIUM + 1 R-LOW + 1 docstring; 0 R-CRITICAL)
380
+ ### 6 same-session reviewer folds applied (2 + 2 + 1 + 1 docstring; 0 )
367
381
 
368
382
  Two parallel reviewers (HIPAA Security Officer perspective + senior code reviewer perspective). Confirmed: §164.312 sub-criteria routing clean (no CloudTrail in (a)(1), no MFA in (a)(1), no TLS in (a)(2)(iv)); HHS R/A classification correct per control; §164.308 + §164.310 OOS enumerations complete against 45 CFR; rationale spot-check zero cross-framework citation leak.
369
383
 
@@ -391,13 +405,13 @@ The 0.8.0 customer migration carryover (suppressions targeting `match.source: 'a
391
405
 
392
406
  ---
393
407
 
394
- ## 0.1.35 — Catalog refresh: EE 0.8.0 MINOR VERSION MILESTONE (EE-RT.23 Move B plugin 1022 per-dim source-attribution refactor + Engine `details.category` projection contract + Key Vault soc2.json gap closure +13 mappings; 7 same-session reviewer folds; +23 new tests / +6 new suites; plugin count UNCHANGED at 24; coverage matrix UNCHANGED at 10/4/33; EE regression 5805/5805 across 907 suites; 68-session 100% green streak preserved; twenty-fifth consecutive trio-publish; ⚠️ customer migration: `match.source: 'azure-cloud-scanner'` suppressions silently no-op post-0.8.0)
408
+ ## 0.1.35 — Catalog refresh: EE 0.8.0 MINOR VERSION MILESTONE ( Move B plugin 1022 per-dim source-attribution refactor + Engine `details.category` projection contract + Key Vault soc2.json gap closure +13 mappings; 7 same-session reviewer folds; +23 new tests / +6 new suites; plugin count UNCHANGED at 24; coverage matrix UNCHANGED at 10/4/33; EE regression 5805/5805 across 907 suites; 68-session 100% green streak preserved; twenty-fifth consecutive trio-publish; ⚠️ customer migration: `match.source: 'azure-cloud-scanner'` suppressions silently no-op post-0.8.0)
395
409
 
396
410
  **Trio-publish institutionalization continued.** Paired with EE 0.8.0 + CE 0.1.68 — **twenty-fifth consecutive trio-publish across EE + CE + agent-skill in a single session** (0.4.5–0.8.0).
397
411
 
398
- ### Headline — MINOR VERSION MILESTONE: EE-RT.23 Move B plugin 1022 Azure scanner per-dim source-attribution refactor
412
+ ### Headline — MINOR VERSION MILESTONE: Move B plugin 1022 Azure scanner per-dim source-attribution refactor
399
413
 
400
- EE 0.8.0 closes the long-standing blocker (originally flagged in EE 0.6.9 R1-MEDIUM-1) for routing Azure storage findings into Appendix A "Cloud Bucket Exposure Attestation" without commingling NSG / RBAC / Key Vault. Plugin 1022 refactored so each of the 4 helpers (`auditNsgRules` / `auditRbac` / `auditStorageAccounts` / `auditKeyVaults`) attaches its own per-dim `source` field on every emission:
414
+ EE 0.8.0 closes the long-standing blocker (originally flagged in EE 0.6.9 -1) for routing Azure storage findings into Appendix A "Cloud Bucket Exposure Attestation" without commingling NSG / RBAC / Key Vault. Plugin 1022 refactored so each of the 4 helpers (`auditNsgRules` / `auditRbac` / `auditStorageAccounts` / `auditKeyVaults`) attaches its own per-dim `source` field on every emission:
401
415
 
402
416
  - `azure-nsg-auditor`
403
417
  - `azure-rbac-auditor`
@@ -421,15 +435,15 @@ Pre-0.8.0 the Key Vault dim emitted 10 distinct `details.category` values but ha
421
435
 
422
436
  All 10 KV anchor regexes use `^Key Vault '[^']+' <distinguishing-clause>` shape (literal-space anchors per `[[soc2_titlepattern_anchor_drift]]` discipline).
423
437
 
424
- ### 7 same-session reviewer folds applied (2 R-HIGH + 3 R-MEDIUM + 2 R-LOW; 0 R-CRITICAL)
438
+ ### 7 same-session reviewer folds applied (2 + 3 + 2 ; 0 )
425
439
 
426
- - **F1 R-HIGH**: anchor-drift defense test now loads patterns from shipped soc2.json directly (single source of truth — closes test/production-regex drift structurally; pre-fold the test regex array was MORE permissive than the production regex — EE-RT.20-class-recurrence INSIDE the defense test).
427
- - **F2 R-HIGH**: `computeBucketStats` dedup key provider-qualified `${source}::${resource}` (closes cross-cloud bucket-name collision for multi-cloud customers using shared naming conventions).
428
- - **F3 R-MEDIUM**: empty-string `details.category` projects null (consistency with harvester source-preservation `length > 0` guard).
429
- - **F4 R-MEDIUM**: SDK-error path coverage tests (KV throw + Storage throw — verifies soft-degrade doesn't accidentally emit findings with wrong source).
430
- - **F5 R-MEDIUM**: partial-failure backward-compat test (RBAC helper throws; NSG/Storage/KV findings still surface with correct per-dim sources).
431
- - **F6 R-LOW**: JSDoc documents `category` field on `analyseAgainstFramework` return shape.
432
- - **F7 R-LOW**: NSG soc2.json regex tightened from `~/^NSG rule .* allows inbound/` to `~/^NSG rule "[^"]+" allows inbound/` (rule-name closure anchor; preemptive cross-mapping defense).
440
+ - **F1 **: anchor-drift defense test now loads patterns from shipped soc2.json directly (single source of truth — closes test/production-regex drift structurally; pre-fold the test regex array was MORE permissive than the production regex —-class-recurrence INSIDE the defense test).
441
+ - **F2 **: `computeBucketStats` dedup key provider-qualified `${source}::${resource}` (closes cross-cloud bucket-name collision for multi-cloud customers using shared naming conventions).
442
+ - **F3 **: empty-string `details.category` projects null (consistency with harvester source-preservation `length > 0` guard).
443
+ - **F4 **: SDK-error path coverage tests (KV throw + Storage throw — verifies soft-degrade doesn't accidentally emit findings with wrong source).
444
+ - **F5 **: partial-failure backward-compat test (RBAC helper throws; NSG/Storage/KV findings still surface with correct per-dim sources).
445
+ - **F6 **: JSDoc documents `category` field on `analyseAgainstFramework` return shape.
446
+ - **F7 **: NSG soc2.json regex tightened from `~/^NSG rule.* allows inbound/` to `~/^NSG rule "[^"]+" allows inbound/` (rule-name closure anchor; preemptive cross-mapping defense).
433
447
 
434
448
  ### ⚠️ Customer migration required
435
449
 
@@ -441,28 +455,28 @@ EE full regression: **5805/5805 across 907 suites** (was 5782/900 at 0.7.3; +23
441
455
 
442
456
  ---
443
457
 
444
- ## 0.1.34 — Catalog refresh: EE 0.7.3 R-CRITICAL hotfix closing 2 production bugs surfaced by EE 0.7.2 dogfood scan against operator's GCP test infra (cross-version google-auth-library fragmentation broke SA impersonation chains [R-CRITICAL — 100% false-clean impact on free-trial/gmail GCP customers + business GCP customers with no-long-lived-SA-keys policy]; GOOGLE_CLOUD_PROJECT_ID env-var alias silently skipped [R-MEDIUM]; +14 new tests across 2 new suites incl. regression pin replicating gax 5.x grpc adapter idiom; plugin count UNCHANGED at 24; coverage matrix UNCHANGED at 10/4/33; EE regression 5782/5782 across 900 suites; 67-session 100% green streak preserved; twenty-fourth consecutive trio-publish)
458
+ ## 0.1.34 — Catalog refresh: EE 0.7.3 hotfix closing 2 production bugs surfaced by EE 0.7.2 dogfood scan against operator's GCP test infra (cross-version google-auth-library fragmentation broke SA impersonation chains [ — 100% false-clean impact on free-trial/gmail GCP customers + business GCP customers with no-long-lived-SA-keys policy]; GOOGLE_CLOUD_PROJECT_ID env-var alias silently skipped []; +14 new tests across 2 new suites incl. regression pin replicating gax 5.x grpc adapter idiom; plugin count UNCHANGED at 24; coverage matrix UNCHANGED at 10/4/33; EE regression 5782/5782 across 900 suites; 67-session 100% green streak preserved; twenty-fourth consecutive trio-publish)
445
459
 
446
460
  **Trio-publish institutionalization continued.** Paired with EE 0.7.3 + CE 0.1.67 — **twenty-fourth consecutive trio-publish across EE + CE + agent-skill in a single session** (0.4.5–0.7.3).
447
461
 
448
- ### Headline — R-CRITICAL hotfix surfaced by EE 0.7.2 dogfood scan within 30 minutes of the 0.7.2 trio publish
462
+ ### Headline — hotfix surfaced by EE 0.7.2 dogfood scan within 30 minutes of the 0.7.2 trio publish
449
463
 
450
464
  EE 0.7.3 closes 2 production bugs that shipped silently in EE 0.7.0–0.7.2. Both bugs surfaced when running `nsauditor-ai scan --plugins 1025 --compliance soc2` against operator's GCP test infra immediately after the 0.7.2 trio publish.
451
465
 
452
- **Gap #2 (R-CRITICAL)**: cross-version `google-auth-library` fragmentation. EE's `utils/gcp_auth.mjs` resolved `9.15.1` at the top level (hoisted via `googleapis@^144`); `@google-cloud/resource-manager@^6` bundles nested `10.6.2` + `google-gax@5.x` whose grpc adapter calls `headers.forEach((value, key) => ...)` expecting WHATWG Headers instance. 9.x returns plain object → `.forEach` undefined → TypeError → `2 UNKNOWN: Getting metadata from plugin failed with error: headers.forEach is not a function`. Plugin 1025's conservative classifier emitted `gcp-iam-project-unreadable` LOW + walkthroughRequired, masking the fact that ALL 7 dims silently skipped. Production false-clean impact: ~100% on any impersonation-using deployment in EE v0.7.0–0.7.2.
466
+ **Gap #2 **: cross-version `google-auth-library` fragmentation. EE's `utils/gcp_auth.mjs` resolved `9.15.1` at the top level (hoisted via `googleapis@^144`); `@google-cloud/resource-manager@^6` bundles nested `10.6.2` + `google-gax@5.x` whose grpc adapter calls `headers.forEach((value, key) =>...)` expecting WHATWG Headers instance. 9.x returns plain object → `.forEach` undefined → TypeError → `2 UNKNOWN: Getting metadata from plugin failed with error: headers.forEach is not a function`. Plugin 1025's conservative classifier emitted `gcp-iam-project-unreadable` LOW + walkthroughRequired, masking the fact that ALL 7 dims silently skipped. Production false-clean impact: ~100% on any impersonation-using deployment in EE v0.7.0–0.7.2.
453
467
 
454
468
  **Fix**: NEW `_wrapAuthClientHeadersShim` in `utils/gcp_auth.mjs` monkey-patches the Impersonated instance's `getRequestHeaders` to coerce 9.x's plain-object return into a Headers instance via `new Headers(plainObject)`. 10.x returns pass through unchanged. Version-agnostic, future-proof. +8 new tests including a regression pin that exactly replicates the gax 5.x grpc adapter idiom — catches any future shim regression at unit-test time.
455
469
 
456
470
  **Customer-segment impact:**
457
471
  - **GCP free-trial / gmail customers** — impersonation is the ONLY working credential model when `iam.disableServiceAccountKeyCreation` is enforced (Google's "Secure by default"). Pre-0.7.3 100% false-clean. **Post-0.7.3 audit works end-to-end.**
458
472
  - **Business GCP customers with no-long-lived-SA-keys security policy** — many enterprise security teams mandate impersonation as their auth model. Same impact. **Post-0.7.3 audit works.**
459
- - **Business GCP customers using JSON keyfiles or pure ADC** — unaffected (R-CRITICAL specific to impersonation injection; pure-ADC + keyfile paths use the nested 10.x auth chain entirely).
473
+ - **Business GCP customers using JSON keyfiles or pure ADC** — unaffected ( specific to impersonation injection; pure-ADC + keyfile paths use the nested 10.x auth chain entirely).
460
474
 
461
- **Gap #1 (R-MEDIUM)**: operators following the `gcloud auth application-default login` setup convention (which writes `GOOGLE_CLOUD_PROJECT_ID` with `_ID` suffix) saw silent skip with `[plugin 1025] No GCP_PROJECT_ID configured`. Extended `loadConfig` + `preflight` from 2-way OR to 3-way OR: `opts.projectId > GCP_PROJECT_ID > GOOGLE_CLOUD_PROJECT > GOOGLE_CLOUD_PROJECT_ID`. +6 new tests covering all precedence paths + preflight failure-reason enumeration + end-to-end run() with env-only resolution.
475
+ **Gap #1 **: operators following the `gcloud auth application-default login` setup convention (which writes `GOOGLE_CLOUD_PROJECT_ID` with `_ID` suffix) saw silent skip with `[plugin 1025] No GCP_PROJECT_ID configured`. Extended `loadConfig` + `preflight` from 2-way OR to 3-way OR: `opts.projectId > GCP_PROJECT_ID > GOOGLE_CLOUD_PROJECT > GOOGLE_CLOUD_PROJECT_ID`. +6 new tests covering all precedence paths + preflight failure-reason enumeration + end-to-end run with env-only resolution.
462
476
 
463
477
  ### Dogfood validation post-fix
464
478
 
465
- Re-ran the scan with both fixes applied. **8 findings emitted** (was 1 false-clean LOW pre-fix): 5 PASS + 2 MEDIUM + 1 LOW. All 7 dims exercise via the impersonated `nsauditor-readonly` audit SA. `accessDeniedByApi.listPolicies: 1` confirms the 0.7.2 R2-MED-13 counter wiring works end-to-end against real GCP.
479
+ Re-ran the scan with both fixes applied. **8 findings emitted** (was 1 false-clean LOW pre-fix): 5 PASS + 2 MEDIUM + 1 LOW. All 7 dims exercise via the impersonated `nsauditor-readonly` audit SA. `accessDeniedByApi.listPolicies: 1` confirms the 0.7.2 counter wiring works end-to-end against real GCP.
466
480
 
467
481
  ### Regression preserved
468
482
 
@@ -476,15 +490,15 @@ EE full regression: **5782/5782 across 900 suites** (was 5768/5768 across 898 su
476
490
 
477
491
  ### Headline — pure-test functional patch (no plugin/soc2.json/SDK changes)
478
492
 
479
- EE 0.7.2 is a pure-test functional patch closing the 5 test-coverage gaps deferred at 0.7.1's reviewer pass — bundled with the staged `peerDependencies.nsauditor-ai` bump (`^0.1.40` → `^0.1.65`) queued at 0.7.1 post-publish per `[[npm_tarball_replacement_trap]]` discipline. Plugin 1025 GCP IAM Project-Level Auditor's 7-dim coverage shipped in EE 0.7.1; this cycle backfills the test surface around it without altering production behavior.
493
+ EE 0.7.2 is a pure-test functional patch closing the 5 test-coverage gaps deferred at 0.7.1's reviewer pass — bundled with the staged `peerDependencies.nsauditor-ai` bump (`^0.1.40` → `^0.1.65`) queued at 0.7.1 post-publish per the npm tarball-immutability constraint discipline. Plugin 1025 GCP IAM Project-Level Auditor's 7-dim coverage shipped in EE 0.7.1; this cycle backfills the test surface around it without altering production behavior.
480
494
 
481
495
  ### Test additions — 50 new tests across 6 new suites
482
496
 
483
- - **R2-MED-7 BFS edge cases (+17)** — `_detectGcpImpersonationPaths` exercised against multiple disjoint cycles (Island A doesn't bleed into Island B), disconnected subgraphs, terminate-at-first-admin (multi-admin chain), parallel branches to distinct admins, depthCap exact-match + one-short + =1 boundaries, per-PATH visited Set semantics, malformed edges (null / missing-to / non-string-to), nonexistent edge targets, cycle through admin, self-loop on start, edge label fallback chain (label → displayName → key), fractional depthCap, parallel edges to same admin with different `via`.
484
- - **R2-MED-13 counter wiring (+15 parameterized)** — 5 v2 apiName strings × 3 counter classes: `projects.roles.list` + `projects.serviceAccounts.list` + `projects.serviceAccounts.keys.list` + `projects.serviceAccounts.getIamPolicy` + `listPolicies` × throttle-retry + access-denied + wall-budget-exhausted. Closes the institutional contract "every API surface increments the right counter key" — prior cycle tested v1's `getIamPolicy` directly but only indirect coverage of v2 apiNames via run() integration.
485
- - **R2-LOW-16/17 helper edges (+10)** — `_saEmailFromName`: trailing slash → `""`, leading slash → segment-after, only-slash → `""`, multiple slashes (lastIndexOf semantics), control-char strip BEFORE slash detection. `_parseIso8601ToMs`: positive `+HH:MM` offset (yields earlier UTC ms), negative `-HH:MM` offset (yields later UTC ms), date-only string (UTC midnight), fractional-seconds + Z, finite-return for well-formed-with-offset.
486
- - **R2-HIGH-4 SDK loader graceful-degradation contract (+8)** — direct unit tests for `_loadGoogleApisIamAdminSdk` + `_loadOrgPolicySdk` missing-dep error branches. Both SDKs are in optionalDependencies and NOT installed in the EE working tree by default. The institutional contract: loader throws with dep-name + `Cannot find package` cause; run()'s catch handler converts to single-warning skip of the affected dim cohort.
487
- - **R2-MED-12 buildGcpAuthOptions real-SDK fallback (+3)** — exercises the `deps._googleAuthLibrarySdk || await _loadGoogleAuthLibrarySdk()` fallback path that all other buildGcpAuthOptions tests bypass via dep injection. Uses `crypto.generateKeyPairSync` to write a valid PKCS#8 SA JSON keyfile to tmpdir, then verifies the real google-auth-library returns a real `Impersonated` instance with documented `targetPrincipal` + `lifetime` shape.
497
+ - **BFS edge cases (+17)** — `_detectGcpImpersonationPaths` exercised against multiple disjoint cycles (Island A doesn't bleed into Island B), disconnected subgraphs, terminate-at-first-admin (multi-admin chain), parallel branches to distinct admins, depthCap exact-match + one-short + =1 boundaries, per-PATH visited Set semantics, malformed edges (null / missing-to / non-string-to), nonexistent edge targets, cycle through admin, self-loop on start, edge label fallback chain (label → displayName → key), fractional depthCap, parallel edges to same admin with different `via`.
498
+ - **counter wiring (+15 parameterized)** — 5 v2 apiName strings × 3 counter classes: `projects.roles.list` + `projects.serviceAccounts.list` + `projects.serviceAccounts.keys.list` + `projects.serviceAccounts.getIamPolicy` + `listPolicies` × throttle-retry + access-denied + wall-budget-exhausted. Closes the institutional contract "every API surface increments the right counter key" — prior cycle tested v1's `getIamPolicy` directly but only indirect coverage of v2 apiNames via run integration.
499
+ - **-16/17 helper edges (+10)** — `_saEmailFromName`: trailing slash → `""`, leading slash → segment-after, only-slash → `""`, multiple slashes (lastIndexOf semantics), control-char strip BEFORE slash detection. `_parseIso8601ToMs`: positive `+HH:MM` offset (yields earlier UTC ms), negative `-HH:MM` offset (yields later UTC ms), date-only string (UTC midnight), fractional-seconds + Z, finite-return for well-formed-with-offset.
500
+ - **SDK loader graceful-degradation contract (+8)** — direct unit tests for `_loadGoogleApisIamAdminSdk` + `_loadOrgPolicySdk` missing-dep error branches. Both SDKs are in optionalDependencies and NOT installed in the EE working tree by default. The institutional contract: loader throws with dep-name + `Cannot find package` cause; run's catch handler converts to single-warning skip of the affected dim cohort.
501
+ - **buildGcpAuthOptions real-SDK fallback (+3)** — exercises the `deps._googleAuthLibrarySdk || await _loadGoogleAuthLibrarySdk` fallback path that all other buildGcpAuthOptions tests bypass via dep injection. Uses `crypto.generateKeyPairSync` to write a valid PKCS#8 SA JSON keyfile to tmpdir, then verifies the real google-auth-library returns a real `Impersonated` instance with documented `targetPrincipal` + `lifetime` shape.
488
502
 
489
503
  ### Regression preserved
490
504
 
@@ -492,11 +506,11 @@ EE full regression: **5768/5768 across 898 suites** (was 5715/5715 across 892 su
492
506
 
493
507
  ---
494
508
 
495
- ## 0.1.32 — Catalog refresh: plugin 1025 GCP IAM Project-Level Auditor EXTENDED to v2 (3 dims → 7 dims) — paired with EE 0.7.1 trio-publish (EE-RT.22 v2 R2 expansion closing all 4 v1-deferred dims; +4 new dims: custom-role permission audit + SA key custody + SA impersonation graph BFS + Organization Policy constraint enumeration; NEW `utils/gcp_auth.mjs` helper honors `GOOGLE_IMPERSONATE_SERVICE_ACCOUNT`; **17 same-session reviewer folds = NEW HIGH-WATER MARK** vs 0.7.0's 12 (1 R-CRITICAL EE-RT.20 class recurrence catch + 7 R-HIGH + 8 R-MEDIUM + 1 R-LOW(+1 grouped)); plugin count UNCHANGED at 24; +22 new soc2.json mappings; new SDK deps `googleapis` + `@google-cloud/org-policy` in optionalDependencies; twenty-second consecutive trio-publish)
509
+ ## 0.1.32 — Catalog refresh: plugin 1025 GCP IAM Project-Level Auditor EXTENDED to v2 (3 dims → 7 dims) — paired with EE 0.7.1 trio-publish (v2 R2 expansion closing all 4 v1-deferred dims; +4 new dims: custom-role permission audit + SA key custody + SA impersonation graph BFS + Organization Policy constraint enumeration; NEW `utils/gcp_auth.mjs` helper honors `GOOGLE_IMPERSONATE_SERVICE_ACCOUNT`; **17 same-session reviewer folds = NEW HIGH-WATER MARK** vs 0.7.0's 12 (1 class recurrence catch + 7 + 8 + 1 (+1 grouped)); plugin count UNCHANGED at 24; +22 new soc2.json mappings; new SDK deps `googleapis` + `@google-cloud/org-policy` in optionalDependencies; twenty-second consecutive trio-publish)
496
510
 
497
511
  **Trio-publish institutionalization continued.** Paired with EE 0.7.1 + CE 0.1.65 — **twenty-second consecutive trio-publish across EE + CE + agent-skill in a single session** (0.4.5–0.7.1).
498
512
 
499
- ### Headline — EE-RT.22 v2 plugin 1025 R2 expansion
513
+ ### Headline —, v2 plugin 1025 R2 expansion
500
514
 
501
515
  Plugin 1025 GCP IAM Project-Level Auditor extended from 3 audit dimensions to **7** via in-place R2 expansion (closes all 4 v1-deferred dims from the EE 0.7.0 cycle). Plugin count UNCHANGED at 24 (v2 = in-place expansion, not new plugin). Coverage matrix UNCHANGED at 10/4/33 — pure substrate-evidence depth uplift on already-covered CC6.1 / CC6.6 / C1.1 controls.
502
516
 
@@ -506,15 +520,15 @@ NEW `utils/gcp_auth.mjs` helper honors `GOOGLE_IMPERSONATE_SERVICE_ACCOUNT` env
506
520
 
507
521
  ### Reviewer fold high-water mark — 17 same-session folds
508
522
 
509
- NEW HIGH-WATER MARK vs 0.7.0's 12 folds. Distribution: 1 R-CRITICAL + 7 R-HIGH + 8 R-MEDIUM + 1 R-LOW(+1 grouped). The R-CRITICAL fold (R2-CRITICAL-1) was an EE-RT.20 R1-CRITICAL-1 class recurrence — soc2.json PASS-tier SA-key patterns silently failed to match when plugin emitted `(display: 'X')` between email and `has` clause. Production false-clean impact would have been ~100% on real GCP fixtures. Patterns rewritten to `'[^']+'.*has`.
523
+ NEW HIGH-WATER MARK vs 0.7.0's 12 folds. Distribution: 1 + 7 + 8 + 1 (+1 grouped). The review fold was an class recurrence — soc2.json PASS-tier SA-key patterns silently failed to match when plugin emitted `(display: 'X')` between email and `has` clause. Production false-clean impact would have been ~100% on real GCP fixtures. Patterns rewritten to `'[^']+'.*has`.
510
524
 
511
525
  ### Cross-repo privacy scrub (parallel non-functional work)
512
526
 
513
- Operator-flagged CRITICAL privacy class at 0.7.1 review: shipped npm files MUST NOT contain operator-private references. Substitutions applied across all 3 repos for personal emails / internal repo paths / real account IDs. New memory `[[npm_package_privacy]]` pinned. Force-push history rewrite applied to CE + agent-skill public repos to scrub identifiers from all historical commits.
527
+ Operator-flagged CRITICAL privacy class at 0.7.1 review: shipped npm files MUST NOT contain operator-private references. Substitutions applied across all 3 repos for personal emails / internal repo paths / real account IDs. The package-privacy rule is now enforced. Force-push history rewrite applied to CE + agent-skill public repos to scrub identifiers from all historical commits.
514
528
 
515
529
  ---
516
530
 
517
- ## 0.1.31 — Catalog refresh: NEW EE-RT.22 v1 plugin 1025 GCP IAM Project-Level Auditor — paired with EE 0.7.0 trio-publish (MINOR-VERSION MILESTONE opening the v0.7.x cross-cloud-parity line; first plugin in the GCP-IAM-deep-audit cohort; 3 audit dimensions across CC6.1 + CC6.6; 12 R1 reviewer folds (0 R-CRITICAL + 2 R-HIGH + 5 R-MEDIUM + 5 R-LOW); plugin count 23 → 24; 11 new soc2.json mappings; new SDK dep `@google-cloud/resource-manager`; twenty-first consecutive trio-publish)
531
+ ## 0.1.31 — Catalog refresh: NEW, v1 plugin 1025 GCP IAM Project-Level Auditor — paired with EE 0.7.0 trio-publish (MINOR-VERSION MILESTONE opening the v0.7.x cross-cloud-parity line; first plugin in the GCP-IAM-deep-audit cohort; 3 audit dimensions across CC6.1 + CC6.6; 12 R1 reviewer folds (0 + 2 + 5 + 5 ); plugin count 23 → 24; 11 new soc2.json mappings; new SDK dep `@google-cloud/resource-manager`; twenty-first consecutive trio-publish)
518
532
 
519
533
  **Trio-publish institutionalization continued.** Paired with EE 0.7.0 + CE 0.1.64 — **twenty-first consecutive trio-publish across EE + CE + agent-skill in a single session** (0.4.5–0.7.0).
520
534
 
@@ -525,7 +539,7 @@ Operator-flagged CRITICAL privacy class at 0.7.1 review: shipped npm files MUST
525
539
 
526
540
  ---
527
541
 
528
- ## 0.1.30 — Catalog refresh: EE-RT.21 v2 R2 cleanup for plugin 1024 GCP Cloud Storage Auditor — paired with EE 0.6.9 trio-publish (patch-level R2 reviewer-deferred-items cleanup: Appendix A multi-cloud renderer extension + evidence-gap soc2.json mappings; 5 R1 reviewer folds (0 R-CRITICAL + 1 R-HIGH + 1 R-MEDIUM + 3 R-LOW); plugin count UNCHANGED at 23; 3 new soc2.json mappings; NEW pre-publish doc-consistency gate; twentieth consecutive trio-publish)
542
+ ## 0.1.30 — Catalog refresh:, v2 R2 cleanup for plugin 1024 GCP Cloud Storage Auditor — paired with EE 0.6.9 trio-publish (patch-level R2 reviewer-deferred-items cleanup: Appendix A multi-cloud renderer extension + evidence-gap soc2.json mappings; 5 R1 reviewer folds (0 + 1 + 1 + 3 ); plugin count UNCHANGED at 23; 3 new soc2.json mappings; NEW pre-publish doc-consistency gate; twentieth consecutive trio-publish)
529
543
 
530
544
  **Trio-publish institutionalization continued.** Paired with EE 0.6.9 + CE 0.1.63 — **twentieth consecutive trio-publish across EE + CE + agent-skill in a single session** (0.4.5–0.6.9).
531
545
 
@@ -537,14 +551,14 @@ Operator-flagged CRITICAL privacy class at 0.7.1 review: shipped npm files MUST
537
551
 
538
552
  ### Reviewer-fold highlights (all closed same-session)
539
553
 
540
- - **R1-HIGH-1 (mappings)** — Missing C1.1 dual-mapping for `_CAT_METADATA_UNREADABLE` (rationale prose vs JSON-structure drift). Added the parallel C1.1 entry; cross-cloud parity with plugin 1020 S3 precedent restored.
541
- - **R1-MEDIUM-1 (renderer)** — Strengthened Azure-exclusion comment to cite the engine-projection constraint in addition to plugin-1022 commingling.
542
- - **R1-LOW-1 (renderer + mappings)** — Cross-control uniqueBuckets dedup test + combined metadata+IAM-failure regression test.
543
- - **R1-LOW-2 (renderer)** — Narrative phrasing tweak ("AWS S3 / GCS" → "AWS S3 or GCS" for disambiguation).
554
+ - **(mappings)** — Missing C1.1 dual-mapping for `_CAT_METADATA_UNREADABLE` (rationale prose vs JSON-structure drift). Added the parallel C1.1 entry; cross-cloud parity with plugin 1020 S3 precedent restored.
555
+ - **(renderer)** — Strengthened Azure-exclusion comment to cite the engine-projection constraint in addition to plugin-1022 commingling.
556
+ - **(renderer + mappings)** — Cross-control uniqueBuckets dedup test + combined metadata+IAM-failure regression test.
557
+ - **(renderer)** — Narrative phrasing tweak ("AWS S3 / GCS" → "AWS S3 or GCS" for disambiguation).
544
558
 
545
559
  ### NEW institutional discipline introduced this cycle
546
560
 
547
- **Pre-publish doc-consistency gate** codified in EE's `tasks/CLAUDE.md` after the 0.6.8 → user-caught doc drift (6 stale "22 plugin" claims hid across 4 docs in 2 repos). 22 doc-surface audit checklist + auto-grep + SOC 2 matrix invariant check. Saved as `[[pre_publish_doc_consistency_gate]]` auto-memory for cross-session persistence.
561
+ **Pre-publish doc-consistency gate** codified in EE's `tasks/CLAUDE.md` after the 0.6.8 → user-caught doc drift (6 stale "22 plugin" claims hid across 4 docs in 2 repos). 22 doc-surface audit checklist + auto-grep + SOC 2 matrix invariant check. Saved as the pre-publish doc-consistency gate auto-memory for cross-session persistence.
548
562
 
549
563
  ### Tests + regression
550
564
 
@@ -552,7 +566,7 @@ Operator-flagged CRITICAL privacy class at 0.7.1 review: shipped npm files MUST
552
566
 
553
567
  ---
554
568
 
555
- ## 0.1.29 — Catalog refresh: NEW plugin 1024 GCP Cloud Storage Auditor — paired with EE 0.6.8 trio-publish (first multi-cloud parity plugin in 6 months; mirrors plugin 1020 AWS S3 Auditor with 6 GCS-specific dimensions; 4 R1 reviewer folds (0 R-CRITICAL + 0 R-HIGH + 3 R-MEDIUM + 1 R-LOW — clean review pass); plugin count 22 → 23; 20 new soc2.json mappings; nineteenth consecutive trio-publish)
569
+ ## 0.1.29 — Catalog refresh: NEW plugin 1024 GCP Cloud Storage Auditor — paired with EE 0.6.8 trio-publish (first multi-cloud parity plugin in 6 months; mirrors plugin 1020 AWS S3 Auditor with 6 GCS-specific dimensions; 4 R1 reviewer folds (0 + 0 + 3 + 1 — clean review pass); plugin count 22 → 23; 20 new soc2.json mappings; nineteenth consecutive trio-publish)
556
570
 
557
571
  **Trio-publish institutionalization continued.** Paired with EE 0.6.8 + CE 0.1.62 — **nineteenth consecutive trio-publish across EE + CE + agent-skill in a single session** (0.4.5–0.6.8).
558
572
 
@@ -565,10 +579,10 @@ Operator-flagged CRITICAL privacy class at 0.7.1 review: shipped npm files MUST
565
579
 
566
580
  ### Reviewer-fold highlights (all closed same-session)
567
581
 
568
- - **R-MEDIUM-1** — Severity-ladder co-existence: when both `allUsers` and `allAuthenticatedUsers` are present in different bindings, CRITICAL finding surfaces the HIGH evidence in details + narrative.
569
- - **R-MEDIUM-2** — Per-bucket runtime exception severity: run()-level catch INFO → LOW for consistency with `_auditBucket` metadata-error pattern.
570
- - **R-MEDIUM-1 (mappings)** — Cross-cloud parity dual-mappings: 5 soc2.json entries dual-mapped to C1.2 + A1.2 matching AWS S3 precedents.
571
- - **R-LOW-1** — CMEK regex tightened from substring to full-format 6-segment match.
582
+ - **-1** — Severity-ladder co-existence: when both `allUsers` and `allAuthenticatedUsers` are present in different bindings, CRITICAL finding surfaces the HIGH evidence in details + narrative.
583
+ - **-2** — Per-bucket runtime exception severity: run-level catch INFO → LOW for consistency with `_auditBucket` metadata-error pattern.
584
+ - **(mappings)** — Cross-cloud parity dual-mappings: 5 soc2.json entries dual-mapped to C1.2 + A1.2 matching AWS S3 precedents.
585
+ - **-1** — CMEK regex tightened from substring to full-format 6-segment match.
572
586
 
573
587
  ### Tests + regression
574
588
 
@@ -576,17 +590,17 @@ Operator-flagged CRITICAL privacy class at 0.7.1 review: shipped npm files MUST
576
590
 
577
591
  ---
578
592
 
579
- ## 0.1.28 — Catalog refresh: plugin 1170 v3.1 SG-reference-graph edge dedup + plugin 1200 v6.1 CloudWatch Logs probe retry-on-empty parity — paired with EE 0.6.7 trio-publish (patch-level R2 reviewer-deferred-items cleanup cycle: closes both R2 items from 0.6.6 reviewer pass; 4 R1 reviewer folds (0 R-CRITICAL + 0 R-HIGH + 1 R-MEDIUM + 3 R-LOW — clean review pass) + 1 unanticipated `_retryOnNotFound` two-phase restructure (caught by test interaction); plugin count UNCHANGED at 22; soc2.json UNCHANGED; eighteenth consecutive trio-publish)
593
+ ## 0.1.28 — Catalog refresh: plugin 1170 v3.1 SG-reference-graph edge dedup + plugin 1200 v6.1 CloudWatch Logs probe retry-on-empty parity — paired with EE 0.6.7 trio-publish (patch-level R2 reviewer-deferred-items cleanup cycle: closes both R2 items from 0.6.6 reviewer pass; 4 R1 reviewer folds (0 + 0 + 1 + 3 — clean review pass) + 1 unanticipated `_retryOnNotFound` two-phase restructure (caught by test interaction); plugin count UNCHANGED at 22; soc2.json UNCHANGED; eighteenth consecutive trio-publish)
580
594
 
581
595
  **Trio-publish institutionalization continued.** Paired with EE 0.6.7 + CE 0.1.61 — **eighteenth consecutive trio-publish across EE + CE + agent-skill in a single session** (0.4.5–0.6.7).
582
596
 
583
597
  ### What changed
584
598
 
585
599
  - **`references/plugins.md`** — two plugin rows updated:
586
- - **Plugin 1170 v3.1** — extended row with edge-dedup discipline in `_buildSgReferenceGraph`: edges deduped by `(sourceGroupId, targetGroupId)` with `ports` aggregated as array of `{protocol, fromPort, toPort}`. Pre-fold a real-world ALB-fronting-app SG with 3 ingress perms on different ports (80/443/8080) referencing the same source SG emitted 3 distinct edges A→B; the BFS treated each as a separate chain, inflating `chainCount` 2-5× and exhausting per-target chain caps on noise. Post-fold the BFS sees exactly 1 chain per distinct (source, target) pair. `isCrossVpc` aggregation is AND-semantic — if ANY contributing pair is same-VPC, the merged edge is same-VPC (per `[[conservative_classifier_principle]]`). Classifier `_classifyTransitiveReachability` port-render accepts both v3.1 array shape and v3 single-object shape (back-compat preserved).
600
+ - **Plugin 1170 v3.1** — extended row with edge-dedup discipline in `_buildSgReferenceGraph`: edges deduped by `(sourceGroupId, targetGroupId)` with `ports` aggregated as array of `{protocol, fromPort, toPort}`. Pre-fold a real-world ALB-fronting-app SG with 3 ingress perms on different ports (80/443/8080) referencing the same source SG emitted 3 distinct edges A→B; the BFS treated each as a separate chain, inflating `chainCount` 2-5× and exhausting per-target chain caps on noise. Post-fold the BFS sees exactly 1 chain per distinct (source, target) pair. `isCrossVpc` aggregation is AND-semantic — if ANY contributing pair is same-VPC, the merged edge is same-VPC (per the conservative-classifier principle). Classifier `_classifyTransitiveReachability` port-render accepts both v3.1 array shape and v3 single-object shape (back-compat preserved).
587
601
  - **Plugin 1200 v6.1** — extended row with CloudWatch Logs probe retry-on-empty parity. Pre-fold the CWL Logs probe was asymmetric: `DescribeLogGroups` returns `logGroups: []` (NOT a thrown exception) on missing groups, so the shared `_retryOnNotFound` helper's thrown-NotFound retry path never fired. A freshly-created CWL log group probed within seconds of creation could false-DEAD. Post-fold `_retryOnNotFound` accepts an optional retry-on-result predicate; the CWL call site passes a predicate that fires retry when the response carries no exact-name match (covers both empty and prefix-only-sibling responses). Eventual-consistency parity now uniform across IAM / Lambda / SNS / SQS / EventBridge API destination / CloudWatch Logs.
588
602
  - **Two-phase restructure of `_retryOnNotFound`** — initially the result-based retry was added inside the existing try block, but a compound-path test interaction (transient empty → second-call throws `ResourceNotFoundException`) caused 3 total network calls. Restructured to two mutually-exclusive phases — Phase 1 = initial call + thrown-NotFound retry; Phase 2 = result-based retry — capping total calls at 2 on all compound paths. The per-call-site outer catch routes a second-call thrown error (NotFound → DEAD; AccessDenied → UNVERIFIABLE).
589
- - **4 R1 reviewer folds applied** (0 R-CRITICAL + 0 R-HIGH + 1 R-MEDIUM + 3 R-LOW — clean review pass): R-MEDIUM-1 arrival-order-independent AND-aggregation (locked with 2 regression fixtures + JSDoc tightening) + R-LOW-1 partial-render contract on malformed port specs (locked with 2 regression fixtures) + R-LOW-2 `_portKeys` scratch-lifetime documented at function-signature comment + R-LOW-1 compound-path coverage (transient empty → second-call AccessDenied → UNVERIFIABLE / transient empty → second-call thrown RNF → DEAD; drives the two-phase restructure decision).
603
+ - **4 R1 reviewer folds applied** (0 + 0 + 1 + 3 — clean review pass): arrival-order-independent AND-aggregation (locked with 2 regression fixtures + JSDoc tightening) + partial-render contract on malformed port specs (locked with 2 regression fixtures) + `_portKeys` scratch-lifetime documented at function-signature comment + compound-path coverage (transient empty → second-call AccessDenied → UNVERIFIABLE / transient empty → second-call thrown RNF → DEAD; drives the two-phase restructure decision).
590
604
  - **`SKILL.md`** — "post-EE 0.6.6" → "post-EE 0.6.7"; plugin 1170 v3.1 + plugin 1200 v6.1 highlights surfaced in plugin narratives; plugin count enumeration stays at 22.
591
605
  - **`peerDependencies`** floor: unchanged at `nsauditor-ai >=0.1.40`.
592
606
 
@@ -603,7 +617,7 @@ Operator-flagged CRITICAL privacy class at 0.7.1 review: shipped npm files MUST
603
617
 
604
618
  ---
605
619
 
606
- ## 0.1.27 — Catalog refresh: plugin 1170 v3 SG→SG transitive reachability + plugin 1200 v6 dead-target probe warm-up — paired with EE 0.6.6 trio-publish (minor cycle: EE-RT.16 v3 transitive chain reachability + EE-RT.20.5 v6 IAM/API-destination/CW-Logs target probes; 5 R1 reviewer folds (1 R-HIGH + 2 R-MEDIUM + 2 R-LOW; 0 R-CRITICAL — clean review pass); plugin count UNCHANGED at 22; seventeenth consecutive trio-publish)
620
+ ## 0.1.27 — Catalog refresh: plugin 1170 v3 SG→SG transitive reachability + plugin 1200 v6 dead-target probe warm-up — paired with EE 0.6.6 trio-publish (minor cycle:, v3 transitive chain reachability +, v6 IAM/API-destination/CW-Logs target probes; 5 R1 reviewer folds (1 + 2 + 2 ; 0 — clean review pass); plugin count UNCHANGED at 22; seventeenth consecutive trio-publish)
607
621
 
608
622
  **Trio-publish institutionalization continued.** Paired with EE 0.6.6 + CE 0.1.60 — **seventeenth consecutive trio-publish across EE + CE + agent-skill in a single session** (0.4.5–0.6.6).
609
623
 
@@ -612,14 +626,14 @@ Operator-flagged CRITICAL privacy class at 0.7.1 review: shipped npm files MUST
612
626
  - **`references/plugins.md`** — two plugin rows updated:
613
627
  - **Plugin 1170 v3** — extended row with SG→SG transitive chain reachability dimension: BFS from public-CIDR roots through `UserIdGroupPairs` SG-references; 2-hop emits HIGH, 3+ hop emits CRITICAL (operator-blindness principle); cycle defense + depth cap (default 5, max 20) + per-target chain cap (default 10, max 100); cross-VPC edges skipped as INFO trailer; per-hop port-flow tracked but NOT intersected (v3 v1 simplification — walkthroughRequired=true). New operator opts: `skipTransitiveReachability` / `transitiveChainDepthCap` / `transitiveChainsPerTargetCap` / `transitiveChainSamplesPerFindingCap`. 3 new soc2.json mappings under CC6.6 (transitive-public HIGH + CRITICAL + INFO truncation).
614
628
  - **Plugin 1200 v6** — extended row with three new dead-target probe branches: IAM role (`iam:GetRole` on path-stripped role NAME) + EventBridge API destination (`events:DescribeApiDestination` reuses `_EventBridgeSdk`) + CloudWatch Logs (`logs:DescribeLogGroups` with `logGroupNamePrefix` filter + exact-name disambiguation guard). New SDK deps `@aws-sdk/client-iam` + `@aws-sdk/client-cloudwatch-logs` (both in optionalDependencies). Companion-LOW emission contract unchanged (existing CC7.1 titlePattern target-type-agnostic). **Operator note**: `iam:GetRole` is a global API resolving per-partition — orchestrators wiring `opts._iamClient` must construct a single global IAM client per-partition.
615
- - **5 v6 R1 reviewer folds applied** (0 R-CRITICAL — clean review pass; 1 R-HIGH + 2 R-MEDIUM + 2 R-LOW): R-HIGH-1 (plugin 1170 v3) BFS short-circuits enqueue past per-target cap (closes path-enumeration explosion on hub-and-spoke topologies — pre-fold the BFS marked the target truncated but kept cloning `path` and `visited` Sets and walking past the cap) + R-MEDIUM-1 (plugin 1200 v6) IAM `NoSuchEntityException` / `NoSuchEntity` lifted into `_DEAD_TARGET_NOTFOUND_ERROR_NAMES` Set (bare disjunction collapsed; eventual-consistency retry restored for IAM — the canonical worst case for AWS eventual consistency, with IAM lag 10-30s documented; **9th cumulative recurrence** of the `[[emit_literal_set_drift]]` class across the EE codebase) + R-MEDIUM-2 (plugin 1200 v6) IAM partition-routing contract documented at `_loadIamSdk` (orchestrator must construct global IAM client per-partition; doc-only fold) + R-LOW-2 (plugin 1170 v3) depth-cap-hit surfaced separately from per-target-cap (closes silent-deep-truncation false-CLEAN class — pre-fold a graph deeper than `transitiveChainDepthCap` silently truncated without operator-visible signal) + R-LOW-2 (plugin 1200 v6) API destination ARN regex future-proofed against alias-only ARN shapes.
629
+ - **5 v6 R1 reviewer folds applied** (0 — clean review pass; 1 + 2 + 2 ): (plugin 1170 v3) BFS short-circuits enqueue past per-target cap (closes path-enumeration explosion on hub-and-spoke topologies — pre-fold the BFS marked the target truncated but kept cloning `path` and `visited` Sets and walking past the cap) + (plugin 1200 v6) IAM `NoSuchEntityException` / `NoSuchEntity` lifted into `_DEAD_TARGET_NOTFOUND_ERROR_NAMES` Set (bare disjunction collapsed; eventual-consistency retry restored for IAM — the canonical worst case for AWS eventual consistency, with IAM lag 10-30s documented; **9th cumulative recurrence** of the the emit-literal/set-drift class class across the EE codebase) + (plugin 1200 v6) IAM partition-routing contract documented at `_loadIamSdk` (orchestrator must construct global IAM client per-partition; doc-only fold) + (plugin 1170 v3) depth-cap-hit surfaced separately from per-target-cap (closes silent-deep-truncation false-CLEAN class — pre-fold a graph deeper than `transitiveChainDepthCap` silently truncated without operator-visible signal) + (plugin 1200 v6) API destination ARN regex future-proofed against alias-only ARN shapes.
616
630
  - **`SKILL.md`** — "post-EE 0.6.5" → "post-EE 0.6.6"; plugin 1170 v3 + plugin 1200 v6 highlights surfaced in plugin-1200 narrative; plugin count enumeration stays at 22.
617
631
  - **`peerDependencies`** floor: unchanged at `nsauditor-ai >=0.1.40`.
618
632
 
619
633
  ### R2 reviewer-deferred (queued for 0.6.7)
620
634
 
621
- - **R-LOW-1 (plugin 1200 v6)**: CloudWatch Logs probe doesn't retry on empty result (logs:DescribeLogGroups returns `logGroups: []` not an exception, so `_retryOnNotFound` doesn't apply). Lower priority than IAM since CWL eventual-consistency is much narrower.
622
- - **R-MEDIUM-1 (plugin 1170 v3)**: Edge dedup absent in `_buildSgReferenceGraph` — multi-rule references to the same SG (e.g., one perm per port) inflate chain counts 2-5×. Defer until operator feedback on chain-count noise.
635
+ - **(plugin 1200 v6)**: CloudWatch Logs probe doesn't retry on empty result (logs:DescribeLogGroups returns `logGroups: []` not an exception, so `_retryOnNotFound` doesn't apply). Lower priority than IAM since CWL eventual-consistency is much narrower.
636
+ - **(plugin 1170 v3)**: Edge dedup absent in `_buildSgReferenceGraph` — multi-rule references to the same SG (e.g., one perm per port) inflate chain counts 2-5×. Defer until operator feedback on chain-count noise.
623
637
  - **R-NIT** documentation folds.
624
638
 
625
639
  ### Tests + regression
@@ -637,8 +651,8 @@ Operator-flagged CRITICAL privacy class at 0.7.1 review: shipped npm files MUST
637
651
  - **`references/plugins.md`** — plugin 1200 row updated with v5 dim list:
638
652
  - **Dead-target companion-LOW (item)** — per-target liveness probes for Lambda + SNS + SQS via new `_probeTargetLiveness` helper (parallel via Promise.all + 2s default timeout). New MEDIUM verdict `*-alerting-destination-dead-targets` emitted as companion alongside PASS when targets point to deleted resources. New operator opts: `skipTargetLivenessProbe: true` + `deadTargetProbeTimeoutMs`. IAM role + API destination + CloudWatch Logs target probes deferred to 0.6.6.
639
653
  - **Sentinel observability** — `targetVerificationReason` enum (AccessDenied / SdkUnavailable / BeyondCap / SkippedByOpts) on rule shape; classifier surfaces `targetVerificationReasonBreakdown` in finding details.
640
- - **R-NIT named-constants** — `SH_HUB_NOT_ENABLED_ERROR_NAMES` frozen Set replaces 2 bare-string sites in SecurityHub helpers per `[[emit_literal_set_drift]]`.
641
- - **5 R1 reviewer folds applied** (0 R-CRITICAL — clean review pass; 3 R-HIGH + 1 R-MEDIUM + 1 consolidated R-LOW/R-NIT): R-HIGH-1 case-insensitive NotFound matching + R-HIGH-2 one-retry on NotFound (eventual-consistency defense) + R-HIGH-3 Lambda probe passes FULL ARN (alias-correctness server-side) + R-HIGH (Explore) parallel probes with per-target timeout + R-MEDIUM-1 SQS partition-aware via `GetQueueUrl` (closes false-DEAD on aws-cn / aws-us-gov / aws-iso partitions).
654
+ - **R-NIT named-constants** — `SH_HUB_NOT_ENABLED_ERROR_NAMES` frozen Set replaces 2 bare-string sites in SecurityHub helpers per the emit-literal/set-drift class.
655
+ - **5 R1 reviewer folds applied** (0 — clean review pass; 3 + 1 + 1 consolidated /R-NIT): case-insensitive NotFound matching + one-retry on NotFound (eventual-consistency defense) + Lambda probe passes FULL ARN (alias-correctness server-side) + (Explore) parallel probes with per-target timeout + SQS partition-aware via `GetQueueUrl` (closes false-DEAD on aws-cn / aws-us-gov / aws-iso partitions).
642
656
  - **Cross-plugin sessionToken sweep** — note added to the EE plugin catalog narrative: 18 EE AWS plugins (1020-1200) now thread `sessionToken` through their AWS-SDK credentials block. AssumeRole-style auditor credentials work uniformly across the entire EE catalog.
643
657
  - **`SKILL.md`** — "post-EE 0.6.4" → "post-EE 0.6.5"; plugin count enumeration stays at 22.
644
658
  - **`peerDependencies`** floor: unchanged at `nsauditor-ai >=0.1.40`.
@@ -668,13 +682,13 @@ npm install nsauditor-ai-agent-skill@0.1.26
668
682
 
669
683
  ---
670
684
 
671
- ## 0.1.25 — Catalog refresh: plugin 1200 v4 reviewer-cleanup cycle — paired with EE 0.6.4 trio-publish (patch-level cycle: EventBridge target verification + multi-failedAccount surface + trigger uniformity; 5 R1 reviewer folds incl. R-HIGH-1 cap-skew classifier closure; plugin count UNCHANGED at 22; fifteenth consecutive trio-publish)
685
+ ## 0.1.25 — Catalog refresh: plugin 1200 v4 reviewer-cleanup cycle — paired with EE 0.6.4 trio-publish (patch-level cycle: EventBridge target verification + multi-failedAccount surface + trigger uniformity; 5 R1 reviewer folds incl. cap-skew classifier closure; plugin count UNCHANGED at 22; fifteenth consecutive trio-publish)
672
686
 
673
687
  **Trio-publish institutionalization continued.** Paired with EE 0.6.4 + CE 0.1.58 — **fifteenth consecutive trio-publish across EE + CE + agent-skill in a single session** (0.4.5–0.6.4).
674
688
 
675
689
  ### What changed
676
690
 
677
- - **`references/plugins.md`** — plugin 1200 row updated with v4 dim list. **R-HIGH-2 EventBridge target verification (item)**: new `_listEventBridgeRuleTargets` helper with defensive pagination; `events:ListTargetsByRule` per matched rule (cap default 10 via `opts.targetVerificationRuleCap`; opt-out via `opts.skipEventBridgeTargetVerification`); new MEDIUM verdict `*-alerting-destination-targetless` for sink-less rules. **R-MEDIUM-2 multi-failedAccount surface**: Inspector2 helper return-shape `{accountStatus, accessDenied, failedAccounts: array}` (renamed plural; capped at AWS-documented 100); caller emits one LOW per failed account with per-region emission cap 10 + rollup LOW per region. **R-LOW-2 trigger uniformity**: GuardDuty alerting-destination trigger gates on `detector.Status === ENABLED` (symmetric with Inspector2). **5 R1 reviewer folds applied** (0 R-CRITICAL — clean review pass): R-HIGH-1 cap-skew classifier branch (LOW UNVERIFIABLE not MEDIUM TARGETLESS when cap-exceeded rules could be the actual sink) + R-HIGH consolidated pagination + JSDoc clarity + R-MEDIUM-1 multi-failedAccount per-region emission cap (10 + rollup) + R-MEDIUM-4 boundary tests + R-HIGH-2 dead-target documented-limitation note.
691
+ - **`references/plugins.md`** — plugin 1200 row updated with v4 dim list. **EventBridge target verification (item)**: new `_listEventBridgeRuleTargets` helper with defensive pagination; `events:ListTargetsByRule` per matched rule (cap default 10 via `opts.targetVerificationRuleCap`; opt-out via `opts.skipEventBridgeTargetVerification`); new MEDIUM verdict `*-alerting-destination-targetless` for sink-less rules. **multi-failedAccount surface**: Inspector2 helper return-shape `{accountStatus, accessDenied, failedAccounts: array}` (renamed plural; capped at AWS-documented 100); caller emits one LOW per failed account with per-region emission cap 10 + rollup LOW per region. **trigger uniformity**: GuardDuty alerting-destination trigger gates on `detector.Status === ENABLED` (symmetric with Inspector2). **5 R1 reviewer folds applied** (0 — clean review pass): cap-skew classifier branch (LOW UNVERIFIABLE not MEDIUM TARGETLESS when cap-exceeded rules could be the actual sink) + consolidated pagination + JSDoc clarity + multi-failedAccount per-region emission cap (10 + rollup) + boundary tests + dead-target documented-limitation note.
678
692
  - **`SKILL.md`** — "post-EE 0.6.3" → "post-EE 0.6.4"; plugin count enumeration stays at 22.
679
693
  - **`peerDependencies`** floor: unchanged at `nsauditor-ai >=0.1.40`.
680
694
 
@@ -685,7 +699,7 @@ AI coding agents using this skill now know that plugin 1200:
685
699
  - **Verifies EventBridge target presence per matched rule** — a rule with zero `Targets` (or just `ENABLED` state but no targets configured) routes to MEDIUM TARGETLESS instead of PASS. Closes the substrate-without-sink false-PASS class at the rule level.
686
700
  - **Emits one LOW per failed Inspector2 account** for delegated-admin scans — was first-failedAccount-only pre-fold; rest were silently dropped. Per-region emission cap of 10 + rollup LOW per region bounds finding pollution.
687
701
  - Exposes new operator opts: `skipEventBridgeTargetVerification: true` (cost-sensitive opt-out OR no IAM grant) + `targetVerificationRuleCap: 1..100` (per-rule verification cap; default 10).
688
- - **Distinguishes cap-skew unverifiable from sink-less rules** — when target-less rules exist AND others are beyond the verification cap (could be the real sink), emits LOW UNVERIFIABLE with `capExceeded: true` per `[[conservative_classifier_principle]]` rather than overclaiming MEDIUM TARGETLESS.
702
+ - **Distinguishes cap-skew unverifiable from sink-less rules** — when target-less rules exist AND others are beyond the verification cap (could be the real sink), emits LOW UNVERIFIABLE with `capExceeded: true` per the conservative-classifier principle rather than overclaiming MEDIUM TARGETLESS.
689
703
 
690
704
  ### Documented limitation queued for 0.6.5
691
705
 
@@ -704,13 +718,13 @@ npm install nsauditor-ai-agent-skill@0.1.25
704
718
 
705
719
  ---
706
720
 
707
- ## 0.1.24 — Catalog refresh: plugin 1200 v3 alerting-destination dim — paired with EE 0.6.3 trio-publish (patch-level extension: substrate-without-sink false-PASS closure via EventBridge rule + SecurityHub product subscription detection; R-CRITICAL Inspector Classic ARN-collision fold; SH-only MEDIUM tier; plugin count UNCHANGED at 22; fourteenth consecutive trio-publish)
721
+ ## 0.1.24 — Catalog refresh: plugin 1200 v3 alerting-destination dim — paired with EE 0.6.3 trio-publish (patch-level extension: substrate-without-sink false-PASS closure via EventBridge rule + SecurityHub product subscription detection; Inspector Classic ARN-collision fold; SH-only MEDIUM tier; plugin count UNCHANGED at 22; fourteenth consecutive trio-publish)
708
722
 
709
723
  **Trio-publish institutionalization continued.** Paired with EE 0.6.3 + CE 0.1.57 — **fourteenth consecutive trio-publish across EE + CE + agent-skill in a single session** (0.4.5–0.6.3).
710
724
 
711
725
  ### What changed
712
726
 
713
- - **`references/plugins.md`** — plugin 1200 row updated with v3 dim list. NEW alerting-destination dim (item c) verifies EventBridge rule + SecurityHub product subscription per service per region. New SDK deps `@aws-sdk/client-eventbridge` + `@aws-sdk/client-securityhub` (optionalDependencies). 4 same-session R1 reviewer folds applied: R-CRITICAL-1 SH product ARN substring collision closure (Inspector Classic vs Inspector2; boundary-anchored helper) + R-HIGH-1 SH-only PASS narrative split (SH-only is MEDIUM aggregation-only; auditor walkthrough required for SH → downstream paging) + R-HIGH-3 EventBridge content-filter grammar (`{prefix}` / `{wildcard}` matchers; regex-meta escape for operator IaC defense) + R-LOW-1 source case normalization. Also surfaces R-MEDIUM-2 (Inspector2 helper return-shape `{accountStatus, accessDenied, failedAccount}`) + item (d) BatchGetAccountStatus contract verification with `failedAccounts[]` per-account error channel surfaced via new `_CAT_INS_FAILED_ACCOUNT` LOW.
727
+ - **`references/plugins.md`** — plugin 1200 row updated with v3 dim list. NEW alerting-destination dim (item c) verifies EventBridge rule + SecurityHub product subscription per service per region. New SDK deps `@aws-sdk/client-eventbridge` + `@aws-sdk/client-securityhub` (optionalDependencies). 4 same-session R1 reviewer folds applied: SH product ARN substring collision closure (Inspector Classic vs Inspector2; boundary-anchored helper) + SH-only PASS narrative split (SH-only is MEDIUM aggregation-only; auditor walkthrough required for SH → downstream paging) + EventBridge content-filter grammar (`{prefix}` / `{wildcard}` matchers; regex-meta escape for operator IaC defense) + source case normalization. Also surfaces (Inspector2 helper return-shape `{accountStatus, accessDenied, failedAccount}`) + item (d) BatchGetAccountStatus contract verification with `failedAccounts[]` per-account error channel surfaced via new `_CAT_INS_FAILED_ACCOUNT` LOW.
714
728
  - **`SKILL.md`** — "post-EE 0.6.2" → "post-EE 0.6.3"; plugin count enumeration stays at 22 (existing plugin grew in scope).
715
729
  - **`peerDependencies`** floor: unchanged at `nsauditor-ai >=0.1.40`.
716
730
 
@@ -722,12 +736,12 @@ AI coding agents using this skill now know that plugin 1200:
722
736
  - Distinguishes **PASS** (EventBridge rule present), **MEDIUM SH-only** (SecurityHub aggregates but no proactive paging), **HIGH missing** (no path), and **LOW unverifiable** (AccessDenied / SDK unavailable).
723
737
  - Supports **EventBridge content-filter grammar** — `{prefix: "aws."}` catch-all rules and `{wildcard: "aws.guard*"}` glob rules both match correctly.
724
738
  - Exposes new operator opt: `skipAlertingDestination: true` for cost-sensitive runs.
725
- - Distinguishes a **true AccessDenied** from an **empty-body response** (R-MEDIUM-2 close-out) — `_getInspector2AccountStatus` no longer conflates the two cases.
739
+ - Distinguishes a **true AccessDenied** from an **empty-body response** (close-out) — `_getInspector2AccountStatus` no longer conflates the two cases.
726
740
  - Surfaces the **AWS-published `failedAccounts[]` per-account error channel** with `errorCode + errorMessage` via new `_CAT_INS_FAILED_ACCOUNT` LOW (item d close-out).
727
741
 
728
- ### R-CRITICAL-1 closure (worth a callout)
742
+ ### closure (worth a callout)
729
743
 
730
- The pre-fold substring check `:product/aws/inspector` would have matched BOTH Inspector Classic (deprecated 2024) and Inspector2 ARNs — a substrate-without-sink false-PASS where a stale Classic subscription emitting zero findings would have satisfied the Inspector2 dim. The R-CRITICAL fold uses boundary-anchored substring matching + the strict `/aws/inspector2` constant, and pins the regression with a dedicated test that asserts the Classic ARN does NOT match the Inspector2 dim.
744
+ The pre-fold substring check `:product/aws/inspector` would have matched BOTH Inspector Classic (deprecated 2024) and Inspector2 ARNs — a substrate-without-sink false-PASS where a stale Classic subscription emitting zero findings would have satisfied the Inspector2 dim. The review fold uses boundary-anchored substring matching + the strict `/aws/inspector2` constant, and pins the regression with a dedicated test that asserts the Classic ARN does NOT match the Inspector2 dim.
731
745
 
732
746
  ### Compatibility
733
747
 
@@ -748,7 +762,7 @@ npm install nsauditor-ai-agent-skill@0.1.24
748
762
 
749
763
  ### What changed
750
764
 
751
- - **`references/plugins.md`** — plugin 1200 row updated with v2 dim list. Multi-region enumeration (item a) replaces single-region scope; `FindingPublishingFrequency` check (item b) added as CC7.1 detection-latency dimension; Inspector2 baseline expansion (item e) grows scan-target baseline from {ec2, ecr, lambda} → {ec2, ecr, lambda, lambdaCode, codeRepository}. 4 same-session R1 reviewer folds applied (0 R-CRITICAL clean review pass): R-HIGH-1 region regex GovCloud + ISO support (closes FedRAMP / StateRAMP / IL5+ false-PASS class) + R-HIGH-2 frequency ordering not equality + R-MEDIUM-1 region cap defensibility + R-LOW-1 EC2 client instrumentation parity.
765
+ - **`references/plugins.md`** — plugin 1200 row updated with v2 dim list. Multi-region enumeration (item a) replaces single-region scope; `FindingPublishingFrequency` check (item b) added as CC7.1 detection-latency dimension; Inspector2 baseline expansion (item e) grows scan-target baseline from {ec2, ecr, lambda} → {ec2, ecr, lambda, lambdaCode, codeRepository}. 4 same-session R1 reviewer folds applied (0 clean review pass): region regex GovCloud + ISO support (closes FedRAMP / StateRAMP / IL5+ false-PASS class) + frequency ordering not equality + region cap defensibility + EC2 client instrumentation parity.
752
766
  - **`SKILL.md`** — "post-EE 0.6.1" → "post-EE 0.6.2"; plugin count enumeration stays at 22 (existing plugin grew in scope).
753
767
  - **`peerDependencies`** floor: unchanged at `nsauditor-ai >=0.1.40`.
754
768
 
@@ -781,7 +795,7 @@ npm install nsauditor-ai-agent-skill@0.1.23
781
795
 
782
796
  ### What changed
783
797
 
784
- - **`references/plugins.md`** — **NEW plugin 1200 row** added: 4 active SOC 2 dimensions (GuardDuty Detector enablement per region CC7.1, GuardDuty protection-feature coverage CC7.1 — institutional baseline S3_DATA_EVENTS / EKS_AUDIT_LOGS / EBS_MALWARE_PROTECTION / RDS_LOGIN_EVENTS / LAMBDA_NETWORK_LOGS / RUNTIME_MONITORING, Inspector2 enablement CC7.1+CC7.2, Inspector2 scan-target coverage CC7.1 zero / CC7.2 partial). First AWS-managed-threat-detection substrate audit. HIGH on `gd-not-enabled` silent-blind class; HIGH on `inspector2-disabled` / SUSPENDED silent-blind class for CVE coverage on EC2/ECR/Lambda; HIGH on `inspector2-coverage-zero` (enabled overall but zero scan targets active); MEDIUM on partial coverage with explicit `disabledResources`. **6 same-session R1 reviewer folds applied** including R1-CRITICAL-1 soc2.json titlePattern misalignment closure (4 patterns; would have silently failed CC7.1/CC7.2 compliance routing) + R1-CRITICAL-1 AccessDenied distinct findings + R1-CRITICAL-2 legacy DataSources case normalization + R1-HIGH-2 SUSPENDED/DISABLED Detector silent-blind closure + R1-HIGH-3/4 dead-code drift closures.
798
+ - **`references/plugins.md`** — **NEW plugin 1200 row** added: 4 active SOC 2 dimensions (GuardDuty Detector enablement per region CC7.1, GuardDuty protection-feature coverage CC7.1 — institutional baseline S3_DATA_EVENTS / EKS_AUDIT_LOGS / EBS_MALWARE_PROTECTION / RDS_LOGIN_EVENTS / LAMBDA_NETWORK_LOGS / RUNTIME_MONITORING, Inspector2 enablement CC7.1+CC7.2, Inspector2 scan-target coverage CC7.1 zero / CC7.2 partial). First AWS-managed-threat-detection substrate audit. HIGH on `gd-not-enabled` silent-blind class; HIGH on `inspector2-disabled` / SUSPENDED silent-blind class for CVE coverage on EC2/ECR/Lambda; HIGH on `inspector2-coverage-zero` (enabled overall but zero scan targets active); MEDIUM on partial coverage with explicit `disabledResources`. **6 same-session R1 reviewer folds applied** including soc2.json titlePattern misalignment closure (4 patterns; would have silently failed CC7.1/CC7.2 compliance routing) + AccessDenied distinct findings + legacy DataSources case normalization + SUSPENDED/DISABLED Detector silent-blind closure + -3/4 dead-code drift closures.
785
799
  - **`SKILL.md`** — plugin count enumeration 21 → 22; "post-EE 0.6.0" → "post-EE 0.6.1".
786
800
  - **`peerDependencies`** floor: unchanged at `nsauditor-ai >=0.1.40`.
787
801
 
@@ -836,13 +850,13 @@ npm install nsauditor-ai-agent-skill@0.1.20
836
850
 
837
851
  ---
838
852
 
839
- ## 0.1.19 — Catalog refresh: plugin 1190 AWS SES Email Integrity Auditor v3 extension (Part A DKIM public-key fingerprint capture/pin + Part B in-band DMARC alignment classifier; 5 same-session reviewer folds incl. 1 R-CRITICAL false-CLEAN closure on truncated DKIM keys) — EE 0.5.3; plugin count UNCHANGED at 20
853
+ ## 0.1.19 — Catalog refresh: plugin 1190 AWS SES Email Integrity Auditor v3 extension (Part A DKIM public-key fingerprint capture/pin + Part B in-band DMARC alignment classifier; 5 same-session reviewer folds incl. 1 false-CLEAN closure on truncated DKIM keys) — EE 0.5.3; plugin count UNCHANGED at 20
840
854
 
841
855
  **Trio-publish institutionalization continued.** Paired with EE 0.5.3 + CE 0.1.52 — **ninth consecutive trio-publish across EE + CE + agent-skill in a single session** (after 0.4.5/0.4.6/0.4.7/0.4.8/0.4.9/0.5.0/0.5.1/0.5.2). The 0.1.19 refresh keeps the AI-coding-agent knowledge surface current with the latest EE plugin extension.
842
856
 
843
857
  ### What changed
844
858
 
845
- - **`references/plugins.md`** — **plugin 1190 row** updated v2.1 → v3: 2 NEW evidence dimensions (Part A DKIM public-key fingerprint capture/pin + Part B in-band DMARC alignment classifier). NEW emission categories: `ses-dkim-fingerprint-verified` (PASS) / `ses-dkim-fingerprint-mismatch` (HIGH — operator-supplied pin store enables unauthorized rotation / key substitution attack detection) / `ses-dkim-fingerprint-unverifiable` (LOW + evidenceGap) + `ses-dmarc-alignment-strict-met` (PASS) / `ses-dmarc-alignment-relaxed` (INFO) / `ses-dmarc-alignment-dkim-strict-impossible` (HIGH — adkim=s + DKIM disabled) / `ses-dmarc-alignment-spf-strict-impossible` (HIGH — aspf=s + no custom MailFrom) / `ses-dmarc-alignment-unverifiable` (LOW). NEW kill-switches `_skipDkimFingerprintCapture` + `_skipDmarcAlignmentCheck`. R-CRITICAL closure (discovered via test): `_stripControlChars` 256-char truncation corrupted long DKIM keys → new `_stripControlCharsNoTruncate` helper.
859
+ - **`references/plugins.md`** — **plugin 1190 row** updated v2.1 → v3: 2 NEW evidence dimensions (Part A DKIM public-key fingerprint capture/pin + Part B in-band DMARC alignment classifier). NEW emission categories: `ses-dkim-fingerprint-verified` (PASS) / `ses-dkim-fingerprint-mismatch` (HIGH — operator-supplied pin store enables unauthorized rotation / key substitution attack detection) / `ses-dkim-fingerprint-unverifiable` (LOW + evidenceGap) + `ses-dmarc-alignment-strict-met` (PASS) / `ses-dmarc-alignment-relaxed` (INFO) / `ses-dmarc-alignment-dkim-strict-impossible` (HIGH — adkim=s + DKIM disabled) / `ses-dmarc-alignment-spf-strict-impossible` (HIGH — aspf=s + no custom MailFrom) / `ses-dmarc-alignment-unverifiable` (LOW). NEW kill-switches `_skipDkimFingerprintCapture` + `_skipDmarcAlignmentCheck`. closure (discovered via test): `_stripControlChars` 256-char truncation corrupted long DKIM keys → new `_stripControlCharsNoTruncate` helper.
846
860
  - **`SKILL.md`** — plugin 1190 v3 narrative added; "post-EE 0.5.2" → "post-EE 0.5.3". EE plugin count UNCHANGED at 20.
847
861
  - **`peerDependencies`** floor: unchanged at `nsauditor-ai >=0.1.40`.
848
862
 
@@ -866,7 +880,7 @@ npm install nsauditor-ai-agent-skill@0.1.19
866
880
 
867
881
  ### What changed
868
882
 
869
- - **`references/plugins.md`** — **plugin 1190 row** updated v2 → v2.1: 7 deferred reviewer-fold items closed. NEW emission category `ses-dkim-dns-partial-with-transients` MEDIUM (matched>0 + transient on remainder — preserves partial-match evidence rather than collapsing to LOW). NEW named Sets `_DNS_TRANSIENT_ERROR_CODES` + `_SES_CLASSIC_NOT_FOUND_ERROR_NAMES` + `_SES_CLASSIC_QUOTA_ERROR_NAMES` per [[emit_literal_set_drift]] discipline. NEW module-load-time disjointness IIFE `_assertDnsErrorCodeSetsDisjoint()` promotes invariant from test-time to Node startup. R-LOW-6 producer→consumer identityType normalization at both promoter sites.
883
+ - **`references/plugins.md`** — **plugin 1190 row** updated v2 → v2.1: 7 deferred reviewer-fold items closed. NEW emission category `ses-dkim-dns-partial-with-transients` MEDIUM (matched>0 + transient on remainder — preserves partial-match evidence rather than collapsing to LOW). NEW named Sets `_DNS_TRANSIENT_ERROR_CODES` + `_SES_CLASSIC_NOT_FOUND_ERROR_NAMES` + `_SES_CLASSIC_QUOTA_ERROR_NAMES` per the emit-literal/set-drift class discipline. NEW module-load-time disjointness IIFE `_assertDnsErrorCodeSetsDisjoint` promotes invariant from test-time to Node startup. producer→consumer identityType normalization at both promoter sites.
870
884
  - **`SKILL.md`** — plugin 1190 v2.1 narrative added; "post-EE 0.5.1" → "post-EE 0.5.2". EE plugin count UNCHANGED at 20.
871
885
  - **`peerDependencies`** floor: unchanged at `nsauditor-ai >=0.1.40`.
872
886
 
@@ -884,7 +898,7 @@ npm install nsauditor-ai-agent-skill@0.1.18
884
898
  ### Notes
885
899
 
886
900
  - No SKILL contract changes; pure catalog refresh.
887
- - `references/schemas.md` + `references/workflows.md` unchanged (no plugin-schema or workflow changes in EE 0.5.2; plugin 1190 v2.1 consolidation uses the same `cloudScanners` capability + same `run()` envelope established in EE-RT.12.25).
901
+ - `references/schemas.md` + `references/workflows.md` unchanged (no plugin-schema or workflow changes in EE 0.5.2; plugin 1190 v2.1 consolidation uses the same `cloudScanners` capability + same `run` envelope established in).
888
902
  - Eighth consecutive trio-publish institutionalizes the discipline across 8 ship cycles.
889
903
 
890
904
  ---
@@ -895,7 +909,7 @@ npm install nsauditor-ai-agent-skill@0.1.18
895
909
 
896
910
  ### What changed
897
911
 
898
- - **`references/plugins.md`** — **plugin 1150 row** updated v1 → v2: 5 → 7 dimensions. v1 dims preserved (encryption + transit-policy + topic-policy + DLQ). v2 NEW dims: **dim 6 SQS ApproximateAgeOfOldestMessage CloudWatch alarm coverage** (CC7.2 + A1.2 dual-mapped) — per-queue PASS / MEDIUM (silent backlog growth) / LOW (actions-disabled OR empty AlarmActions) / LOW + evidenceGap (CW SDK unavailable / AccessDenied / name un-extractable / truncated); **dim 7 SNS NumberOfNotificationsFailed CloudWatch alarm coverage** (CC7.2 + A1.2 dual-mapped) — per-topic analogue with same severity ladder. v2 single-fetch budget via `_enumerateMetricAlarms` + `_buildAlarmIndex` (mirrors plugin 1040's `_auditAlarmCoverage` scaffold). Soft-degrade contract: CW SDK load failure routes per-resource to LOW + evidenceGap rather than blocking primary substrate audit. **R-CRITICAL v2 fold (false-CLEAN closure)**: `actionable` requires BOTH `ActionsEnabled=true` AND non-empty `AlarmActions[]` (CloudWatch fires NO operator paging when AlarmActions=[] even with ActionsEnabled=true). **R-HIGH v2 fold**: soc2.json PASS-tier titlePatterns narrowed to anchor on namespace:metric clauses.
912
+ - **`references/plugins.md`** — **plugin 1150 row** updated v1 → v2: 5 → 7 dimensions. v1 dims preserved (encryption + transit-policy + topic-policy + DLQ). v2 NEW dims: **dim 6 SQS ApproximateAgeOfOldestMessage CloudWatch alarm coverage** (CC7.2 + A1.2 dual-mapped) — per-queue PASS / MEDIUM (silent backlog growth) / LOW (actions-disabled OR empty AlarmActions) / LOW + evidenceGap (CW SDK unavailable / AccessDenied / name un-extractable / truncated); **dim 7 SNS NumberOfNotificationsFailed CloudWatch alarm coverage** (CC7.2 + A1.2 dual-mapped) — per-topic analogue with same severity ladder. v2 single-fetch budget via `_enumerateMetricAlarms` + `_buildAlarmIndex` (mirrors plugin 1040's `_auditAlarmCoverage` scaffold). Soft-degrade contract: CW SDK load failure routes per-resource to LOW + evidenceGap rather than blocking primary substrate audit. ** v2 fold (false-CLEAN closure)**: `actionable` requires BOTH `ActionsEnabled=true` AND non-empty `AlarmActions[]` (CloudWatch fires NO operator paging when AlarmActions=[] even with ActionsEnabled=true). ** v2 fold**: soc2.json PASS-tier titlePatterns narrowed to anchor on namespace:metric clauses.
899
913
  - **`SKILL.md`** — plugin 1150 v2 narrative added to enumeration; "post-EE 0.5.0" → "post-EE 0.5.1". EE plugin count UNCHANGED at 20 (no new plugin in 0.5.1; existing plugin 1150 grew in scope across new dims 6 + 7).
900
914
  - **`peerDependencies`** floor: unchanged at `nsauditor-ai >=0.1.40`.
901
915
 
@@ -913,7 +927,7 @@ npm install nsauditor-ai-agent-skill@0.1.17
913
927
  ### Notes
914
928
 
915
929
  - No SKILL contract changes; pure catalog refresh.
916
- - `references/schemas.md` + `references/workflows.md` unchanged (no plugin-schema or workflow changes in EE 0.5.1; plugin 1150 v2 extension uses the same `cloudScanners` capability + same `run()` envelope established in EE-RT.12.25).
930
+ - `references/schemas.md` + `references/workflows.md` unchanged (no plugin-schema or workflow changes in EE 0.5.1; plugin 1150 v2 extension uses the same `cloudScanners` capability + same `run` envelope established in).
917
931
  - Seventh consecutive trio-publish institutionalizes the discipline across 7 ship cycles (0.4.5/0.4.6/0.4.7/0.4.8/0.4.9/0.5.0/0.5.1).
918
932
 
919
933
  ---
@@ -930,9 +944,9 @@ npm install nsauditor-ai-agent-skill@0.1.17
930
944
 
931
945
  ### EE 0.5.0 paired-release context
932
946
 
933
- - **EE plugin count UNCHANGED at 20** — the 0.5.0 minor-version milestone bump is a single-plugin EXTENSION (fourth extension cycle after EE-RT.16 v2 in 0.4.6 + EE-RT.14 v3 in 0.4.8 + EE-RT.17 v2 in 0.4.9). Plugin 1190 v2 closes the canonical false-CLEAN window where SES `Status=SUCCESS` substrate alone could not rule out post-verification DNS drift.
947
+ - **EE plugin count UNCHANGED at 20** — the 0.5.0 minor-version milestone bump is a single-plugin EXTENSION (fourth extension cycle after, v2 in 0.4.6 +, v3 in 0.4.8 +, v2 in 0.4.9). Plugin 1190 v2 closes the canonical false-CLEAN window where SES `Status=SUCCESS` substrate alone could not rule out post-verification DNS drift.
934
948
  - **Part A — DKIM CNAME DNS resolution promotion** (dim 1) — `_resolveDkimCnames` + `_promoteDkimFromDns`. Each `<token>._domainkey.<identityDomain>` CNAME resolved via node:dns/promises + matched against `<token>.dkim.amazonses.com` (case-insensitive per RFC 1035 §2.3.3). Four outcomes: PASS `ses-dkim-dns-verified` / MEDIUM `ses-dkim-dns-partial` / HIGH `ses-dkim-dns-missing` (production false-CLEAN closure) / LOW + evidenceGap `ses-dkim-dns-unverifiable`.
935
- - **Part B — DMARC TXT record parser + MailFrom promotion** (dim 2) — RFC 7489 §6.4 tag-list parser + `_dmarc.<identityDomain>` TXT lookup. Five outcomes. **R-CRITICAL-1 same-session fold (false-CLEAN closure)**: `pct=0` on `p=reject`/`p=quarantine` functionally equivalent to `p=none`; now routes to HIGH `ses-dmarc-policy-none`. **R-HIGH-1 same-session fold (subdomain-takeover false-NEGATIVE closure)**: `sp` subdomain-policy override now evaluated — `p=reject; sp=none` downgrades to HIGH.
949
+ - **Part B — DMARC TXT record parser + MailFrom promotion** (dim 2) — RFC 7489 §6.4 tag-list parser + `_dmarc.<identityDomain>` TXT lookup. Five outcomes. **same-session fold (false-CLEAN closure)**: `pct=0` on `p=reject`/`p=quarantine` functionally equivalent to `p=none`; now routes to HIGH `ses-dmarc-policy-none`. **same-session fold (subdomain-takeover false-NEGATIVE closure)**: `sp` subdomain-policy override now evaluated — `p=reject; sp=none` downgrades to HIGH.
936
950
  - **Part C — SES classic GetIdentityPolicies parity** (dim 4) — `_loadSesClassicSdk` restored (was removed in v1 reviewer-fold MEDIUM as dead-code load-check). Cross-API discrepancy detection emits HIGH `ses-classic-policy-discrepancy` on classic-only policies (canonical false-NEGATIVE class). Conservative on classic SDK unavailable / AccessDenied → LOW + evidenceGap `ses-classic-policy-unverifiable`.
937
951
  - **8 same-session reviewer folds across the cycle** (1 CRITICAL + 3 HIGH + 2 MEDIUM + 2 LOW); 6 queued in Pick-up Block.
938
952
  - **First plugin in EE to depend on `node:dns/promises`** — first ship to add NETWORK-LAYER cross-reference to AWS-SDK-substrate evidence baseline; structurally distinct evidence-acquisition surface from prior 0.4.x cycles.
@@ -950,18 +964,18 @@ npm install nsauditor-ai-agent-skill@0.1.17
950
964
 
951
965
  ### What changed
952
966
 
953
- - **`references/plugins.md`** — **plugin 1180 row** updated v1 → v2: dim 2 at-rest+KMS now includes kms:DescribeKey cross-reference promotion (mirrors plugin 1140 v2 pattern: UNVERIFIABLE `:key/UUID` → PASS/MEDIUM via KeyMetadata.KeyManager); dim 6 subnet placement now includes ec2:DescribeRouteTables verifier (HIGH on IGW-routed subnets with per-subnet `igwDestinationsBySubnet` evidence; PASS on all-verified-private; LOW + evidenceGap on main-RT-inheritance per R-MEDIUM-2 false-NEGATIVE closure; LOW + evidenceGap on AccessDenied). Cross-plugin sister of plugin 1170 SG perimeter (layer-3 subnet→IGW vs layer-4 SG ingress). Per-resource caching (kmsKeyManagerCache + subnetGroupCache + subnetSetRoutingCache).
967
+ - **`references/plugins.md`** — **plugin 1180 row** updated v1 → v2: dim 2 at-rest+KMS now includes kms:DescribeKey cross-reference promotion (mirrors plugin 1140 v2 pattern: UNVERIFIABLE `:key/UUID` → PASS/MEDIUM via KeyMetadata.KeyManager); dim 6 subnet placement now includes ec2:DescribeRouteTables verifier (HIGH on IGW-routed subnets with per-subnet `igwDestinationsBySubnet` evidence; PASS on all-verified-private; LOW + evidenceGap on main-RT-inheritance per a review fold false-NEGATIVE closure; LOW + evidenceGap on AccessDenied). Cross-plugin sister of plugin 1170 SG perimeter (layer-3 subnet→IGW vs layer-4 SG ingress). Per-resource caching (kmsKeyManagerCache + subnetGroupCache + subnetSetRoutingCache).
954
968
  - **`SKILL.md`** — plugin 1180 v2 narrative added to enumeration; "post-EE 0.4.8" → "post-EE 0.4.9". EE plugin count UNCHANGED at 20 (no new plugin in 0.4.9; existing plugin 1180 grew in scope).
955
969
  - **`peerDependencies`** floor: unchanged at `nsauditor-ai >=0.1.40`.
956
970
 
957
971
  ### EE 0.4.9 paired-release context
958
972
 
959
- - **EE plugin count UNCHANGED at 20** — seventh-ship-cycle in the 0.4.x stream is another single-plugin EXTENSION (third extension cycle after EE-RT.16 v2 in 0.4.6 + EE-RT.14 v3 in 0.4.8). Plugin 1180 v2 closes **both** v1 deferred items (R-MEDIUM-3 KMS-DescribeKey promotion + R-LOW-2 subnet route-table cross-reference).
973
+ - **EE plugin count UNCHANGED at 20** — seventh-ship-cycle in the 0.4.x stream is another single-plugin EXTENSION (third extension cycle after, v2 in 0.4.6 +, v3 in 0.4.8). Plugin 1180 v2 closes **both** v1 deferred items (KMS-DescribeKey promotion + subnet route-table cross-reference).
960
974
  - **Part A — kms:DescribeKey cross-reference promotion** (dim 2 at-rest encryption; mirrors plugin 1140 v2 pattern). UNVERIFIABLE `:key/UUID` ARN shapes promoted via `KeyMetadata.KeyManager` to deterministic PASS (CUSTOMER) / MEDIUM (AWS). Conservative on AccessDenied / NotFound / unknown KeyManager.
961
- - **Part B — Subnet route-table verifier** (dim 6 subnet placement; closes v1 R-LOW-2). `elasticache:DescribeCacheSubnetGroups` + `ec2:DescribeRouteTables` walk. Per-subnet IGW-route detection via `/^igw-[a-f0-9]+$/i` (correctly excludes egress-only `eigw-`). HIGH on IGW-routed subnet(s) (with per-subnet `igwDestinationsBySubnet` evidence per R-HIGH-1 fold) / PASS on all-verified-private / **LOW + evidenceGap on main-RT-inheritance per R-MEDIUM-2 reviewer-fold false-NEGATIVE closure** (default-VPC main-RT typically routes `0.0.0.0/0 → igw-*`).
975
+ - **Part B — Subnet route-table verifier** (dim 6 subnet placement; closes v1 -2). `elasticache:DescribeCacheSubnetGroups` + `ec2:DescribeRouteTables` walk. Per-subnet IGW-route detection via `/^igw-[a-f0-9]+$/i` (correctly excludes egress-only `eigw-`). HIGH on IGW-routed subnet(s) (with per-subnet `igwDestinationsBySubnet` evidence per review fold) / PASS on all-verified-private / **LOW + evidenceGap on main-RT-inheritance per reviewer fold false-NEGATIVE closure** (default-VPC main-RT typically routes `0.0.0.0/0 → igw-*`).
962
976
  - **7 same-session reviewer folds across the cycle** (independent `general-purpose-agent` review yielded 12 findings; 7 folded same-session, 1 deferred to cross-plugin Thread H sweep, 4 withdrawn after verification).
963
977
  - **No new SDK dependencies** — `@aws-sdk/client-kms` + `@aws-sdk/client-ec2` already declared in optionalDependencies since EE 0.4.5.
964
- - **Real-AWS smoke validation END-TO-END**: smoke against `<operator-test-account>` (no fixture changes needed). `redis-leaky-cache` → dim 6 LOW `elasticache-subnet-main-rt-inheritance` (the R-MEDIUM-2 fold escalation demonstrably firing against the real default-VPC main-RT-inheritance pattern); `findingsBySeverity: { pass:1, medium:3, high:5, low:2, info:1 }`; durationMs=1428. KMS promotion path NOT exercised against real AWS (existing fixtures use alias-form CMK keys; unit tests + plugin 1140 v2 real-AWS validation cover the promotion path).
978
+ - **Real-AWS smoke validation END-TO-END**: smoke against `<operator-test-account>` (no fixture changes needed). `redis-leaky-cache` → dim 6 LOW `elasticache-subnet-main-rt-inheritance` (the review fold escalation demonstrably firing against the real default-VPC main-RT-inheritance pattern); `findingsBySeverity: { pass:1, medium:3, high:5, low:2, info:1 }`; durationMs=1428. KMS promotion path NOT exercised against real AWS (existing fixtures use alias-form CMK keys; unit tests + plugin 1140 v2 real-AWS validation cover the promotion path).
965
979
  - **EE full regression: 4696/4696** (was 4642 at EE 0.4.8 publish; +54 tests). 45-session 100% green streak preserved.
966
980
  - **Coverage matrix UNCHANGED at 10/4/33** — substrate evidence depth growth on already-covered CC6.6 + C1.1 via 5 new aws-elasticache-redis-auditor mapping rules.
967
981
 
@@ -975,13 +989,13 @@ npm install nsauditor-ai-agent-skill@0.1.17
975
989
 
976
990
  ### What changed
977
991
 
978
- - **`references/plugins.md`** — **plugin 1140 row** updated to reflect v3 extension (7 → 10 dimensions; +database audit-logging triad: pgAudit / CloudWatch Logs exports / CloudWatch Logs retention; aurora-aware log-path detection per R-HIGH-1 reviewer-fold). Notes the false-PASS closure on `rds-pgaudit-misconfigured` (Postgres silently ignores pgaudit.log when shared_preload_libraries omits pgaudit per R-MEDIUM-2 reviewer-fold). Engine-dispatched essential/optional CloudWatch log type policy via `_RDS_ENGINE_CWL_NAMES` covering mysql/mariadb/aurora-mysql/postgres/aurora-postgresql/oracle-*/sqlserver-* variants.
992
+ - **`references/plugins.md`** — **plugin 1140 row** updated to reflect v3 extension (7 → 10 dimensions; +database audit-logging triad: pgAudit / CloudWatch Logs exports / CloudWatch Logs retention; aurora-aware log-path detection per reviewer fold). Notes the false-PASS closure on `rds-pgaudit-misconfigured` (Postgres silently ignores pgaudit.log when shared_preload_libraries omits pgaudit per reviewer fold). Engine-dispatched essential/optional CloudWatch log type policy via `_RDS_ENGINE_CWL_NAMES` covering mysql/mariadb/aurora-mysql/postgres/aurora-postgresql/oracle-*/sqlserver-* variants.
979
993
  - **`SKILL.md`** — plugin 1140 v3 enumeration line updated with v3 narrative; "post-EE 0.4.7" → "post-EE 0.4.8". EE plugin count UNCHANGED at 20 (no new plugin in 0.4.8; existing plugin 1140 grew in scope).
980
994
  - **`peerDependencies`** floor: unchanged at `nsauditor-ai >=0.1.40` (EE 0.4.0-cohort paired-release floor).
981
995
 
982
996
  ### EE 0.4.8 paired-release context
983
997
 
984
- - **EE plugin count UNCHANGED at 20** — sixth-ship-cycle in the 0.4.x stream is a single-plugin EXTENSION rather than NEW plugin. Plugin 1140 `aws-rds-auditor` grew from 7 → 10 dimensions via **EE-RT.14 v3** — first 0.4.x extension cycle of an existing plugin since EE-RT.16 v2 (plugin 1170 RESTRICTED_PORTS extension in 0.4.6).
998
+ - **EE plugin count UNCHANGED at 20** — sixth-ship-cycle in the 0.4.x stream is a single-plugin EXTENSION rather than NEW plugin. Plugin 1140 `aws-rds-auditor` grew from 7 → 10 dimensions via **, v3** — first 0.4.x extension cycle of an existing plugin since, v2 (plugin 1170 RESTRICTED_PORTS extension in 0.4.6).
985
999
  - Closes the "database activity logs" SOC 2 dimension per `tasks/things-to-check.md` §4 audit-canonical checklist (CC7.2 + CC7.3 continuous monitoring + event evaluation).
986
1000
  - **9 same-session reviewer folds across the cycle** (independent `general-purpose-agent` review yielded 12 findings; 9 folded same-session, 3 deferred to v3.1 / cross-plugin sweep).
987
1001
  - **HIGH-1 closure** — Aurora cluster log-path detection (pre-fold whole Aurora fleet returned false-INFO MEDIUM on dim 10 because helper hard-coded `/aws/rds/instance/<id>/` even for aurora-* engines that publish to `/aws/rds/cluster/<DBClusterIdentifier>/`).
@@ -1001,22 +1015,22 @@ npm install nsauditor-ai-agent-skill@0.1.17
1001
1015
 
1002
1016
  ### What changed
1003
1017
 
1004
- - **`references/plugins.md`** — added **plugin 1190 row** (AWS SES Email Integrity Auditor; 6 dimensions: DKIM enablement + signing status / custom MailFrom domain alignment / configuration set TLS enforcement / identity sending authorization policy permissive principals / dedicated IP pool sending posture / suppression list state; CC6.1 / CC6.6 / C1.1 / CC7.1-substrate / Privacy-substrate). Notes the **multi-class wildcard detector** (bare `"*"` / `{AWS:*}` / `{Service:*}` / `{Federated:*}` / `{CanonicalUser:*}` / array forms per R-HIGH-4 reviewer-fold) + **distinct HIGH `ses-sending-auth-notprincipal-allow` category** per R-CRITICAL-1 reviewer-fold catching the NotPrincipal+Effect=Allow wildcard-EQUIVALENT class (matches plugins 1070 + 1150 NotPrincipal+Allow discipline) + **LOW + evidenceGap `ses-sending-auth-malformed-statement`** per R-HIGH-2 reviewer-fold for Effect-missing send-action statements + **ZDE invariant** at run() envelope boundary (NEVER reads suppressed-destination email addresses).
1018
+ - **`references/plugins.md`** — added **plugin 1190 row** (AWS SES Email Integrity Auditor; 6 dimensions: DKIM enablement + signing status / custom MailFrom domain alignment / configuration set TLS enforcement / identity sending authorization policy permissive principals / dedicated IP pool sending posture / suppression list state; CC6.1 / CC6.6 / C1.1 / CC7.1-substrate / Privacy-substrate). Notes the **multi-class wildcard detector** (bare `"*"` / `{AWS:*}` / `{Service:*}` / `{Federated:*}` / `{CanonicalUser:*}` / array forms per reviewer fold) + **distinct HIGH `ses-sending-auth-notprincipal-allow` category** per reviewer fold catching the NotPrincipal+Effect=Allow wildcard-EQUIVALENT class (matches plugins 1070 + 1150 NotPrincipal+Allow discipline) + **LOW + evidenceGap `ses-sending-auth-malformed-statement`** per reviewer fold for Effect-missing send-action statements + **ZDE invariant** at run envelope boundary (NEVER reads suppressed-destination email addresses).
1005
1019
  - **`SKILL.md`** — added plugin 1190 to the EE plugin enumeration; updated "post-EE 0.4.6" → "post-EE 0.4.7"; bumped EE plugin count 19 → 20 and ID range 1020-1180 → 1020-1190 in the Editions table.
1006
1020
  - **`README.md`** — bumped EE plugin count 19 → 20 and ID range 1020-1180 → 1020-1190 in the Editions table.
1007
1021
  - **`peerDependencies`** floor: unchanged at `nsauditor-ai >=0.1.40` (EE 0.4.0-cohort paired-release floor).
1008
1022
 
1009
1023
  ### EE 0.4.7 paired-release context
1010
1024
 
1011
- - **EE plugin count: 19 → 20** — fifth plugin-count growth in the 0.4.x cycle. NEW plugin **1190 AWS SES Email Integrity Auditor** (EE-RT.18 v1) covers 6 SOC 2 evidence dimensions spanning confidentiality + email-integrity. Closes the next-highest-priority gap from `tasks/things-to-check.md` AWS SOC 2 audit-canonical compliance checklist after Redis closed in 0.4.6. Dual API surface discipline: v1 uses SESv2 only (canonical modern API surface covers all 6 dimensions); `@aws-sdk/client-ses` declared in optionalDependencies for v2+ cross-API parity.
1025
+ - **EE plugin count: 19 → 20** — fifth plugin-count growth in the 0.4.x cycle. NEW plugin **1190 AWS SES Email Integrity Auditor** (v1) covers 6 SOC 2 evidence dimensions spanning confidentiality + email-integrity. Closes the next-highest-priority gap from `tasks/things-to-check.md` AWS SOC 2 audit-canonical compliance checklist after Redis closed in 0.4.6. Dual API surface discipline: v1 uses SESv2 only (canonical modern API surface covers all 6 dimensions); `@aws-sdk/client-ses` declared in optionalDependencies for v2+ cross-API parity.
1012
1026
  - **11 same-session reviewer folds across the cycle** — **ties the single-cycle reviewer-fold record** for security-classifier-correctness-surface plugins (independent `general-purpose-agent` review yielded 12 findings; 11 folded same-session, 1 deferred to cross-plugin Thread H sweep).
1013
1027
  - **CRITICAL-1 closure** — NotPrincipal+Effect=Allow distinct HIGH category (pre-fold silently classified as bounded = false-CLEAN class).
1014
1028
  - **HIGH-4 closure** — `_isWildcardPrincipal` walks every Principal class value (pre-fold only `principal.AWS` was inspected, leaking `{Service:"*"}` + `{Federated:"*"}` as silent CLEAN).
1015
1029
  - **HIGH-2 closure** — missing-Effect on send-action statement now surfaces LOW + evidenceGap `ses-sending-auth-malformed-statement` (was silent-dropped pre-fold).
1016
1030
  - **Fourth EE plugin to ship without smoke-time SDK hotfix** — preemptive `@aws-sdk/client-ses` + `@aws-sdk/client-sesv2` addition.
1017
- - **EE full regression: 4574/4574** (was 4458 at EE 0.4.6 publish; +116 tests across the cycle: 94 EE-RT.18 v1 unit-test suite + 22 reviewer-fold pin tests). 43-session 100% green streak preserved.
1031
+ - **EE full regression: 4574/4574** (was 4458 at EE 0.4.6 publish; +116 tests across the cycle: 94, v1 unit-test suite + 22 reviewer-fold pin tests). 43-session 100% green streak preserved.
1018
1032
  - **Coverage matrix UNCHANGED at 10/4/33** — substrate-evidence depth growth on already-covered CC6.1 / CC6.6 / C1.1 via 8 new aws-ses-auditor mapping rules.
1019
- - **No real-AWS smoke against violation-tier fixtures** — operator's internal test infrastructure has NO SES paired fixtures yet (full-stack fixtures deferred to EE-RT.18 v2 alongside DKIM CNAME DNS resolution + DMARC TXT record parsing). Empty-account smoke baseline against <operator-test-account> DID succeed end-to-end (plugin loads via CE→EE binding, all 4 SESv2 API enumerations succeed, baseline 2 INFO findings emit correctly, durationMs=842, ZDE invariant preserved).
1033
+ - **No real-AWS smoke against violation-tier fixtures** — operator's internal test infrastructure has NO SES paired fixtures yet (full-stack fixtures deferred to, v2 alongside DKIM CNAME DNS resolution + DMARC TXT record parsing). Empty-account smoke baseline against <operator-test-account> DID succeed end-to-end (plugin loads via CE→EE binding, all 4 SESv2 API enumerations succeed, baseline 2 INFO findings emit correctly, durationMs=842, ZDE invariant preserved).
1020
1034
  - **Memory tag closures:** `aws_string_case_normalization` at **20×** with explicit SPLIT-SURFACE callout (DKIM/Tls/MailFromStatus enums upcased / IAM Action/Effect lowercased); `conservative_classifier_principle` reinforced in 5 new fold sites; `emit_literal_set_drift` extended with `_DKIM_STATUS_VALID` + `_MAILFROM_STATUS_SUCCESS` + `_TLS_POLICY_VALID` named-constant discipline.
1021
1035
 
1022
1036
  **Recommended install path:** `npm install nsauditor-ai-agent-skill@0.1.13` (for AI-coding-agent users; pair with `npm install -g nsauditor-ai@0.1.46 @nsasoft/nsauditor-ai-ee@0.4.7`).
@@ -1036,9 +1050,9 @@ npm install nsauditor-ai-agent-skill@0.1.17
1036
1050
 
1037
1051
  ### EE 0.4.6 paired-release context
1038
1052
 
1039
- - **EE plugin count: 18 → 19** — fourth plugin-count growth in the 0.4.x cycle. NEW plugin **1180 AWS ElastiCache Redis Auditor** (EE-RT.17 v1) covers 6 SOC 2 substrate-evidence dimensions spanning confidentiality + availability + segmentation. Dual API enumeration (DescribeReplicationGroups + DescribeCacheClusters) with inter-API dedup; Memcached out-of-scope by design.
1040
- - **Plus EE-RT.16 v2** — plugin 1170 RESTRICTED_PORTS grown 13 → 23 ports per CIS AWS Foundations v3.0 + operator-config + per-SG cardinality cap with rollup trailer + system-managed-SG name-prefix exclusion list.
1041
- - **10 same-session reviewer folds across the cycle** (7 EE-RT.16 v2 incl. 2 CONVERGENT-CRITICAL findings + 3 EE-RT.17 v1) — most-folds-in-a-single-cycle for 0.4.x to date.
1053
+ - **EE plugin count: 18 → 19** — fourth plugin-count growth in the 0.4.x cycle. NEW plugin **1180 AWS ElastiCache Redis Auditor** (v1) covers 6 SOC 2 substrate-evidence dimensions spanning confidentiality + availability + segmentation. Dual API enumeration (DescribeReplicationGroups + DescribeCacheClusters) with inter-API dedup; Memcached out-of-scope by design.
1054
+ - **Plus, v2** — plugin 1170 RESTRICTED_PORTS grown 13 → 23 ports per CIS AWS Foundations v3.0 + operator-config + per-SG cardinality cap with rollup trailer + system-managed-SG name-prefix exclusion list.
1055
+ - **10 same-session reviewer folds across the cycle** (7, v2 incl. 2 CONVERGENT-CRITICAL findings + 3, v1) — most-folds-in-a-single-cycle for 0.4.x to date.
1042
1056
  - **Third EE plugin to ship without smoke-time SDK hotfix** — preemptive `@aws-sdk/client-elasticache` addition.
1043
1057
  - **EE full regression: 4458/4458** (was 4361 at EE 0.4.5 publish; +97 tests). 42-session 100% green streak preserved.
1044
1058
  - **Coverage matrix UNCHANGED at 10/4/33** — substrate-evidence depth growth on already-covered CC6.1 / CC6.2 / CC6.6 / A1.2 / C1.1.
package/SKILL.md CHANGED
@@ -16,7 +16,9 @@ description: >
16
16
 
17
17
  # NSAuditor AI — Agent Skill
18
18
 
19
- > **Version:** 0.2.31 (post-EE-0.32.8 — a **documentation-and-prose** release, no behaviour change. Capability-claim honesty pass, part 2: the air-gapped-delivery class. **27 withdrawn-claim sites** (distinct lines) across the three published packages, each verified against the code — an arm64 image (the build forces `--platform linux/amd64`), offline-installable tarballs (an `npm pack` tarball still resolves deps from a registry), monthly NVD feed bundles (nothing produces one), an air-gapped install script (none exists), a `feed import` CLI command (`importFeed()` has zero non-test callers), and CE's absolute "every feature works without internet access". **Five of the sites were rendered runtime strings**, not documentation: coverage-gap rationales in `utils/intelligence_engine.mjs` that render verbatim into the assessor-facing evidence pack and named a command that does not exist. **In this skill:** the Enterprise tier row's unhedged "RFC 3161 timestamps" is corrected — RFC 3161 timestamping is implemented but not yet wired to a flag, so **do not describe it as shipping**; SHA-256 chain-of-custody is the layer that ships. "Air-gapped deployment" is now stated as "air-gapped operation (offline licensing + offline CVE matching under `NSAUDITOR_OFFLINE_ONLY=1`)". Plugin count UNCHANGED at 28; all seven coverage matrices UNCHANGED. No MCP tool or plugin schema change.)
19
+ > **Version:** 0.2.33 (post-EE-0.32.10 — **no knowledge change**; published in lockstep with EE 0.32.10 + CE 0.2.35. Upstream: the dependency-advisory gate now measures the packed-and-installed customer closure rather than the maintainer's working tree, and proves an advisory source answered before reporting clean; SOC 2 matrix enumerated in full at **10 / 4 / 37 = 51** (completeness, not a coverage change). Plugin catalog UNCHANGED at 28 EE / 55 overall.)
20
+
21
+ > **Prior:** 0.2.32 (post-EE-0.32.9 — the skill package's own provenance sweep.)
20
22
 
21
23
  > **Prior:** 0.2.30 (post-EE-0.32.7 — a **matrix-neutral** release that does two things. (1) **Cross-framework routing:** the network-scan analysis agents' findings now route in **all seven compliance frameworks**, not just SOC 2 — a host serving cleartext or exposing SMB previously failed the SOC 2 report and read clean in HIPAA / NIST CSF / ISO 27001 / CIS v8 / PCI / GDPR off the same scan; that gap is closed (mutation-proven guard; all seven `coverageSummary` blocks byte-identical). (2) **Capability-claim honesty pass:** several Pro/Enterprise capabilities advertised without a shipping implementation — verification engine, branded reports, usage metering, Docker per-scan isolation, and the ZDE "policy engine" / Enterprise-CTEM datastore framings — are **withdrawn**; the real cores (the code-enforced ZDE read-only guarantee, Pro-tier CTEM retention) ship and are described honestly, and the `verifiers/` stub files no longer ship. Plugin count UNCHANGED at 28; all seven coverage matrices UNCHANGED.)
22
24
 
@@ -153,6 +155,23 @@ These tools return a license upgrade prompt on CE installations:
153
155
  | `compliance_check` | Enterprise | SOC 2 (AICPA TSC 2017) + HIPAA (§164.312 Technical Safeguards) + NIST CSF 2.0 Core + PCI DSS v4.0.1 (sub-requirement-level for QSA RoC; PCI SSC June 2024 errata) + ISO/IEC 27001:2022 (per-Annex-A-code-level for ISO/IEC 17021-1 certification body assessors; ISO + IEC October 2022; 2013 edition retired October 31, 2025) + **CIS Critical Security Controls v8** (per-Safeguard-level; Center for Internet Security May 2021, v8.1 errata June 2024) + **GDPR Article 32 (Security of Processing)** (sub-measure-level; Regulation (EU) 2016/679; **Art. 32 infrastructure substrate only, NOT GDPR compliance**) gap analysis — all seven shipped (SOC 2 EE 0.3.x; HIPAA EE 0.9.0; NIST CSF 2.0 EE 0.10.0; PCI DSS v4.0.1 EE 0.11.0; ISO/IEC 27001:2022 EE 0.12.0; CIS Controls v8 EE 0.13.0; **GDPR Article 32 EE 0.20.0**). Multi-framework via `--compliance all` (shorthand for all seven frameworks; EE 0.31.4) or `--compliance soc2,hipaa,nist-csf,pci-dss,iso-27001,cis-v8,gdpr` (any CSV subset; aliases `nist`/`pci`/`iso`/`cis`); an unknown token **fails fast** (no "Framework load failed" stub). The hepta-framework one-scan produces seven complete auditor-ready evidence packs. **CIS Controls v8**: 17 covered + 23 partial + 113 OOS across 153 Safeguards / 18 Controls. **Implementation Group cumulative discipline** — IG1=56 (cyber-insurance baseline; ~50-70% of mid-market policies require IG1 attestation), IG2 cumulative=130, IG3 cumulative=153; smallest-IG-membership tagging (NEVER report IG2 as 74-of-74 in isolation). **No-certification-body attestation discipline** — engine output is INPUT to CSAT / CIS-CAT Pro self-attestation OR a SOC 2 auditor cross-validating CIS scope, never "CIS certified." Cloud Companion Guide v8 shared-responsibility + CIS-Hardened-Image substrate-evidence credit (Safeguards 4.1/4.2/4.6) + 5 Security Functions (NOT 6 — no Govern) + 6 Asset Types + MS-ISAC/EI-ISAC/H-ISAC sector baselines + v7.1-to-v8 cross-reference. CIS Safeguard examples: `3.3` Data Access Control Lists, `5.4` Restrict Administrator Privileges, `6.3` MFA for Externally-Exposed Applications, `8.2` Collect Audit Logs, `11.4` Isolated Recovery Data Instance. ISO 27001 Annex A code examples: `A.5.15` Access control, `A.5.23` NEW 2022 Cloud services, `A.8.5` Secure authentication, `A.8.9` NEW 2022 Configuration management, `A.8.16` NEW 2022 Monitoring activities, `A.8.24` Use of cryptography. Statement of Applicability per Clause 6.1.3.d discipline + ISMS Clauses 4-10 OOS-by-design framing (7 Major Nonconformity classes — absence of internal audit per Clause 9.2 or management review per Clause 9.3 = auto-fail Stage 2) + 5-attribute taxonomy NEW in 2022 (controlType / informationSecurityProperties / cybersecurityConcepts [5 categories, NOT 6 like NIST CSF 2.0] / operationalCapabilities / securityDomains) + 2013-to-2022 transition discipline. Pair with ISO-aware GRC (Drata ISO 27001 / Vanta ISO 27001 / AuditBoard / OneTrust ISMS / Secureframe ISO 27001) for SoA workflow + internal audit + management review. PCI DSS sub-requirement examples: `Req 1.2.1` NSC config standards, `Req 8.4.1` MFA on non-console admin, `Req 10.2.1` audit logs enabled, `Req 11.3.1` quarterly internal vuln scans. Defined-vs-Customized Approach discipline per Appendix E (15 Defined-only sub-requirements enforced at schema layer; CHD Scope operator-attested via CDE DFD per Req 1.2.4; card-brand AOC enforcement view — Visa CISP / Mastercard SDP / Amex DSOP / Discover DISC). **GRC push (Enterprise, opt-in):** set `COMPLIANCE_GRC_PROVIDER=vanta` (or `drata` / `secureframe`) + `COMPLIANCE_GRC_TOKEN` to map the findings to the platform's evidence/test records and push them at scan time (ZDE-redacted egress; token never serialized; the Vanta·Drata·Secureframe connector trio is complete — Secureframe records model, live tenant validation in progress). |
154
156
  | `export_report` | Enterprise | Formatted compliance/risk report (PDF, HTML) |
155
157
 
158
+ ### Evidence gaps — never read one as a pass (post EE 0.32.9)
159
+
160
+ A finding whose text opens `Evidence gap (…)`, or which carries `details.evidenceGap: true`,
161
+ means **the scanner could not verify that surface** — it is NOT a clean result and must never
162
+ be summarised as one. Two shapes to recognise:
163
+
164
+ - `Evidence gap (multi-region enumeration incomplete): …` / `Evidence gap (scan time budget
165
+ exceeded): …` — enumeration did not finish. Report what was NOT covered, not what was.
166
+ - `Evidence gap: the <source> scanner could not run (<reason>) …` — an entire cloud's
167
+ scanner failed to start (an optional SDK absent, credentials unusable). Every in-scope
168
+ control of that cloud is a gap. **Do not describe a multi-cloud scan as clean when one
169
+ cloud's scanner never ran.**
170
+
171
+ If a scan predates EE 0.32.9, its gap findings lead with a retired prefix that no framework
172
+ anchor matches, so they route to no control — the engine detects this and warns. Advise a
173
+ re-scan rather than reusing the old artifact.
174
+
156
175
  ### Cross-framework routing — cite the engine, do NOT freehand-map (post EE 0.32.7)
157
176
 
158
177
  When a user asks which controls a finding maps to, **read it from the engine's compliance
@@ -232,10 +251,10 @@ Operational Integrity (1100), AWS IAM Effective Decrypt-Path Auditor (1110), AWS
232
251
  Lifecycle + Cross-Region Replication Auditor (1120), AWS Backup Auditor (1130), AWS
233
252
  RDS Auditor (1140 v3 — extended in EE 0.4.8 with database audit-logging; 7→10 dims:
234
253
  +pgAudit / +CloudWatch Logs exports / +CloudWatch Logs retention; aurora-aware
235
- log-path detection per R-HIGH-1 reviewer-fold), AWS SQS/SNS Auditor (1150 v2 —
254
+ log-path detection per reviewer fold), AWS SQS/SNS Auditor (1150 v2 —
236
255
  extended in EE 0.5.1: 5 → 7 dims with CloudWatch alarm coverage on SQS
237
256
  ApproximateAgeOfOldestMessage + SNS NumberOfNotificationsFailed; closes 1 CRITICAL
238
- false-CLEAN class on empty-AlarmActions silent-PASS per R-CRITICAL fold; first
257
+ false-CLEAN class on empty-AlarmActions silent-PASS per review fold; first
239
258
  plugin-1150 dim to cross an SDK boundary — SQS+SNS → CloudWatch), AWS EC2
240
259
  SG Perimeter Auditor (1170 v2 — RESTRICTED_PORTS 23 ports per CIS AWS Foundations
241
260
  v3.0), AWS VPC Endpoints / PrivateLink Auditor (1160 — NEW in EE 0.6.0; first plugin
@@ -243,40 +262,40 @@ to audit the PrivateLink isolation boundary; 4 dims: endpoint policy permissive
243
262
  principals CC6.6, PrivateDNS enabled CC6.6, endpoint state A1.2+CC7.2, type substrate
244
263
  Privacy+CC6.6), AWS ElastiCache Redis Auditor (1180 v2 — extended in EE 0.4.9:
245
264
  kms:DescribeKey promotion + subnet route-table verifier; closes both v1 deferred items
246
- R-MEDIUM-3 + R-LOW-2; main-RT-inheritance false-NEGATIVE closure per R-MEDIUM-2
265
+ + -2; main-RT-inheritance false-NEGATIVE closure per a review fold
247
266
  reviewer-fold), AWS SES Email Integrity Auditor (1190 v3 — extended in EE 0.5.0 +
248
267
  consolidated in EE 0.5.2 + v3 extension in EE 0.5.3: DKIM CNAME DNS resolution + DMARC
249
268
  TXT record parser + SES classic API parity + deferred-items sweep + DKIM public-key
250
269
  fingerprint capture/pin + in-band DMARC alignment classifier; closes 1 CRITICAL
251
- false-CLEAN class on DMARC pct=0 per R-CRITICAL-1 fold + 1 HIGH false-NEGATIVE class
252
- on DMARC sp subdomain-policy override per R-HIGH-1 fold + new MEDIUM
253
- ses-dkim-dns-partial-with-transients per v2.1 R-MEDIUM-2 fold + silent-loss-class
270
+ false-CLEAN class on DMARC pct=0 per review fold + 1 HIGH false-NEGATIVE class
271
+ on DMARC sp subdomain-policy override per review fold + new MEDIUM
272
+ ses-dkim-dns-partial-with-transients per v2.1 review fold + silent-loss-class
254
273
  closure on SES classic API quota exhaustion via cause: "classic-sdk-quota-exhausted"
255
- per v2.1 R-HIGH-2 reviewer-fold; first plugin in EE to depend on node:dns/promises
274
+ per v2.1 reviewer fold; first plugin in EE to depend on node:dns/promises
256
275
  for live DNS cross-reference), AWS Inspector2 / GuardDuty Enablement Auditor (1200 v6 —
257
276
  NEW in EE 0.6.1, extended through EE 0.6.6; first AWS-managed-threat-detection
258
277
  substrate audit; bundles two services per the plugin 1150 precedent.
259
278
  **v4 EE 0.6.4 reviewer-cleanup cycle** (closes 3 of 4 R2-deferred items from
260
- EE-RT.20.2): **R-HIGH-2 EventBridge target verification** — new `_listEventBridgeRuleTargets`
279
+ ): **EventBridge target verification** — new `_listEventBridgeRuleTargets`
261
280
  helper with defensive NextToken pagination; per-rule target verification via
262
281
  `events:ListTargetsByRule` (cap default 10 via `opts.targetVerificationRuleCap`;
263
282
  opt-out via `opts.skipEventBridgeTargetVerification`); new MEDIUM verdict
264
283
  `*-alerting-destination-targetless` for sink-less rules (zero Targets — substrate-
265
- without-sink at the rule level). **R-MEDIUM-2 multi-failedAccount surface** —
284
+ without-sink at the rule level). **multi-failedAccount surface** —
266
285
  helper return-shape `{accountStatus, accessDenied, failedAccounts: array}`
267
286
  (renamed plural; capped at AWS-documented 100); caller emits one LOW per failed
268
- account with per-region emission cap 10 + rollup LOW. **R-LOW-2 trigger
287
+ account with per-region emission cap 10 + rollup LOW. **trigger
269
288
  uniformity** — GuardDuty alerting-destination trigger gates on `detector.Status
270
289
  === ENABLED` (matches Inspector2 enabled-only semantic). **5 v4 R1 folds**
271
- (0 R-CRITICAL): R-HIGH-1 cap-skew classifier branch (LOW UNVERIFIABLE not
290
+ (0 ): cap-skew classifier branch (LOW UNVERIFIABLE not
272
291
  MEDIUM TARGETLESS when cap-exceeded rules could be the actual sink) +
273
- R-HIGH consolidated `_listEventBridgeRuleTargets` pagination + JSDoc clarity +
274
- R-MEDIUM-1 multi-failedAccount per-region emission cap (10 + rollup) +
275
- R-MEDIUM-4 boundary tests + R-HIGH-2 dead-target documented-limitation note.
292
+ consolidated `_listEventBridgeRuleTargets` pagination + JSDoc clarity +
293
+ multi-failedAccount per-region emission cap (10 + rollup) +
294
+ boundary tests + dead-target documented-limitation note.
276
295
  **v3 EE 0.6.3 alerting-destination dim preserved**: EventBridge rule on source
277
296
  `aws.guardduty`/`aws.inspector2` OR SecurityHub product subscription (boundary-
278
297
  anchored `_shArnMatchesProduct` helper + strict `/aws/inspector2` constant per
279
- v3 R-CRITICAL-1); verdict tiers PASS / MEDIUM SH-only / MEDIUM TARGETLESS (v4
298
+ v3 -1); verdict tiers PASS / MEDIUM SH-only / MEDIUM TARGETLESS (v4
280
299
  added) / HIGH missing / LOW UNVERIFIABLE; new SDK deps `@aws-sdk/client-eventbridge`
281
300
  + `@aws-sdk/client-securityhub`. **v2 EE 0.6.2 preserved**: multi-region via
282
301
  ec2:DescribeRegions + GuardDuty FindingPublishingFrequency check + Inspector2
@@ -284,14 +303,14 @@ baseline expansion (+lambdaCode +codeRepository). Operator opts: `regions[]` /
284
303
  `skipMultiRegion` / `regionListCap` / `gdFrequencyPassFrequency` /
285
304
  `skipAlertingDestination` / `skipEventBridgeTargetVerification` /
286
305
  `targetVerificationRuleCap` / `skipTargetLivenessProbe` / `deadTargetProbeTimeoutMs`.
287
- **v5 EE 0.6.5 closes the 0.6.4 R-HIGH-2 documented limitation** via per-target
306
+ **v5 EE 0.6.5 closes the 0.6.4 documented limitation** via per-target
288
307
  liveness probes for Lambda (`lambda:GetFunction` on full qualified ARN — alias/
289
308
  version correctness verified server-side) + SNS (`sns:GetTopicAttributes`) +
290
309
  SQS (`sqs:GetQueueUrl` + `GetQueueAttributes` — partition-aware via SDK URL
291
310
  resolution; works on aws-cn / aws-us-gov / aws-iso). Companion-LOW emitted
292
311
  alongside PASS when targets dead. Parallel probes via Promise.all + 2s default
293
312
  timeout. One-retry on NotFound with 750ms backoff (eventual-consistency defense).
294
- Case-insensitive NotFound matching per `[[aws_string_case_normalization]]`.
313
+ Case-insensitive NotFound matching per the AWS string-case normalisation discipline.
295
314
  Sentinel observability — `targetVerificationReason` enum (AccessDenied /
296
315
  SdkUnavailable / BeyondCap / SkippedByOpts) on rule shape. R-NIT
297
316
  `SH_HUB_NOT_ENABLED_ERROR_NAMES` frozen Set. **v6 EE 0.6.6 closes the long
@@ -300,14 +319,14 @@ NAME; new SDK dep `@aws-sdk/client-iam`) + EventBridge API destination
300
319
  (`events:DescribeApiDestination` reuses `_EventBridgeSdk`) + CloudWatch Logs
301
320
  (`logs:DescribeLogGroups` with `logGroupNamePrefix` filter + exact-name
302
321
  disambiguation guard so prefix-match siblings don't false-LIVE; new SDK dep
303
- `@aws-sdk/client-cloudwatch-logs`). **Operator note (v6 R-MEDIUM-2)**:
322
+ `@aws-sdk/client-cloudwatch-logs`). **Operator note (v6 -2)**:
304
323
  `iam:GetRole` is a global API resolving per-partition; orchestrators wiring
305
324
  `opts._iamClient` must construct a single global IAM client per-partition (NOT
306
- per-region). **v6 R-MEDIUM-1 fold**: IAM `NoSuchEntityException` /
325
+ per-region). **v6 review fold**: IAM `NoSuchEntityException` /
307
326
  `NoSuchEntity` lifted into `_DEAD_TARGET_NOTFOUND_ERROR_NAMES` Set; bare
308
327
  disjunction collapsed; eventual-consistency retry restored for IAM (the canonical
309
- worst case — 9th cumulative recurrence of `[[emit_literal_set_drift]]` class).
310
- **v6 R-LOW-2 fold**: API destination ARN regex future-proofed against alias-only
328
+ worst case — 9th cumulative recurrence of the emit-literal/set-drift class class).
329
+ **v6 review fold**: API destination ARN regex future-proofed against alias-only
311
330
  ARN shapes. **v6.1 EE 0.6.7 closes the Logs probe retry-on-empty parity**:
312
331
  `_retryOnNotFound` accepts an optional retry-on-result predicate; CWL Logs probe
313
332
  fires retry when the response carries no exact-name match (covers both empty
@@ -318,8 +337,8 @@ NotFound retry; Phase 2 = result-based retry; phases are mutually exclusive
318
337
  sites (Lambda / SNS / SQS / IAM / EventBridge API destination) pass only two
319
338
  args; default `retryOnResultPredicate = null` cleanly skips Phase 2. Dim 5
320
339
  org-scope still deferred to a future cycle. Total folds across all cycles:
321
- 6 v1 + 4 v2 + 4 v3 (1 R-CRITICAL) + 5 v4 + 5 v5 + 4 v6 (0 R-CRITICAL) + 1 v6.1
322
- (0 R-CRITICAL / 0 R-HIGH) = 29 R1 folds applied same-session.
340
+ 6 v1 + 4 v2 + 4 v3 (1 ) + 5 v4 + 5 v5 + 4 v6 (0 ) + 1 v6.1
341
+ (0 / 0 ) = 29 R1 folds applied same-session.
323
342
 
324
343
  **v5 also brings a cross-plugin contract change**: all 18 EE AWS plugins
325
344
  (1020-1200) now thread `sessionToken` through their AWS-SDK credentials block,
@@ -327,7 +346,7 @@ unblocking AssumeRole-style auditor credentials uniformly across the catalog).
327
346
  **EE plugin IDs use the disjoint 1000+ range** (per EE 0.3.9 renumbering) to avoid
328
347
  CE collision. CE reserves 001-099.
329
348
 
330
- **Plugin 1170 v3 (EE 0.6.6) SG→SG transitive chain reachability** — `aws-ec2-sg-perimeter-auditor` v3 extension. Pre-v3 each Security Group was audited in isolation; a SG with no direct public-CIDR ingress would emit the PASS-tier "no direct public-internet ingress CIDR rules" finding even if transitively reachable from the internet through a `UserIdGroupPairs` chain. v3 builds the SG-reference graph (`_buildSgReferenceGraph`), identifies public-CIDR roots (`_findPubliclyReachableSgs` — 0.0.0.0/0 / ::/0 ingress), and BFS-walks the graph (`_walkTransitiveReachability`) with cycle defense + depth cap (default 5, max 20) + per-target chain cap (default 10, max 100). 2-hop chains emit **HIGH**; 3+ hop chains emit **CRITICAL** (operator-blindness principle — deeper chains less likely to be noticed). Cross-VPC edges skipped (out-of-scope for v3 v1; INFO trailer). v3 v1 simplification: per-hop port-flow tracked but NOT intersected (`walkthroughRequired=true`). New operator opts: `skipTransitiveReachability` / `transitiveChainDepthCap` / `transitiveChainsPerTargetCap` / `transitiveChainSamplesPerFindingCap`. **v3 R-HIGH-1 fold**: BFS short-circuits enqueue past per-target cap (closes path-enumeration explosion on hub-and-spoke topologies — pre-fold the BFS kept cloning `path` and `visited` Sets and walking past the cap). **v3 R-LOW-2 fold**: depth-cap-hit surfaced separately from per-target-cap (closes silent-deep-truncation false-CLEAN class). 3 new soc2.json mappings under CC6.6 (transitive HIGH + CRITICAL + INFO truncation). **v3.1 EE 0.6.7 closes the edge-dedup R2-deferred item**: `_buildSgReferenceGraph` now dedupes edges by `(sourceGroupId, targetGroupId)` with `ports` aggregated as array of `{protocol, fromPort, toPort}`. Pre-fold a real-world ALB-fronting-app SG with 3 ingress perms on different ports (80/443/8080) referencing the same source SG emitted 3 distinct edges A→B; the BFS treated each as a separate chain, inflating `chainCount` 2-5× and exhausting per-target chain caps on noise. Post-fold the BFS sees exactly 1 chain per distinct (source, target) pair. `isCrossVpc` aggregation is AND-semantic — if ANY contributing pair is same-VPC, the merged edge is same-VPC (per `[[conservative_classifier_principle]]`: walk possibly-same-VPC chains rather than silently skip). Classifier port-render accepts both v3.1 array shape and v3 single-object shape (back-compat). **v3.1 R-MEDIUM-1 fold**: arrival-order independence locked with 2 regression fixtures + JSDoc tightening. **v3.1 R-LOW-1 fold**: partial-render contract on malformed port specs locked with 2 fixtures. **v3.1 R-LOW-2 fold**: `_portKeys` scratch-lifetime documented (MUST NOT escape).
349
+ **Plugin 1170 v3 (EE 0.6.6) SG→SG transitive chain reachability** — `aws-ec2-sg-perimeter-auditor` v3 extension. Pre-v3 each Security Group was audited in isolation; a SG with no direct public-CIDR ingress would emit the PASS-tier "no direct public-internet ingress CIDR rules" finding even if transitively reachable from the internet through a `UserIdGroupPairs` chain. v3 builds the SG-reference graph (`_buildSgReferenceGraph`), identifies public-CIDR roots (`_findPubliclyReachableSgs` — 0.0.0.0/0 / ::/0 ingress), and BFS-walks the graph (`_walkTransitiveReachability`) with cycle defense + depth cap (default 5, max 20) + per-target chain cap (default 10, max 100). 2-hop chains emit **HIGH**; 3+ hop chains emit **CRITICAL** (operator-blindness principle — deeper chains less likely to be noticed). Cross-VPC edges skipped (out-of-scope for v3 v1; INFO trailer). v3 v1 simplification: per-hop port-flow tracked but NOT intersected (`walkthroughRequired=true`). New operator opts: `skipTransitiveReachability` / `transitiveChainDepthCap` / `transitiveChainsPerTargetCap` / `transitiveChainSamplesPerFindingCap`. **v3 review fold**: BFS short-circuits enqueue past per-target cap (closes path-enumeration explosion on hub-and-spoke topologies — pre-fold the BFS kept cloning `path` and `visited` Sets and walking past the cap). **v3 review fold**: depth-cap-hit surfaced separately from per-target-cap (closes silent-deep-truncation false-CLEAN class). 3 new soc2.json mappings under CC6.6 (transitive HIGH + CRITICAL + INFO truncation). **v3.1 EE 0.6.7 closes the edge-dedup R2-deferred item**: `_buildSgReferenceGraph` now dedupes edges by `(sourceGroupId, targetGroupId)` with `ports` aggregated as array of `{protocol, fromPort, toPort}`. Pre-fold a real-world ALB-fronting-app SG with 3 ingress perms on different ports (80/443/8080) referencing the same source SG emitted 3 distinct edges A→B; the BFS treated each as a separate chain, inflating `chainCount` 2-5× and exhausting per-target chain caps on noise. Post-fold the BFS sees exactly 1 chain per distinct (source, target) pair. `isCrossVpc` aggregation is AND-semantic — if ANY contributing pair is same-VPC, the merged edge is same-VPC (per the conservative-classifier principle: walk possibly-same-VPC chains rather than silently skip). Classifier port-render accepts both v3.1 array shape and v3 single-object shape (back-compat). **v3.1 review fold**: arrival-order independence locked with 2 regression fixtures + JSDoc tightening. **v3.1 review fold**: partial-render contract on malformed port specs locked with 2 fixtures. **v3.1 review fold**: `_portKeys` scratch-lifetime documented (MUST NOT escape).
331
350
 
332
351
  **EE SOC 2 substrate-evidence coverage (post-EE 0.10.0):** 10 covered controls (CC6.1 /
333
352
  CC6.2 / CC6.6 / CC6.7 / CC6.8 / CC7.1 / CC7.2 / CC7.3 / C1.1 / C1.2) + 4 partial
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nsauditor-ai-agent-skill",
3
- "version": "0.2.31",
3
+ "version": "0.2.33",
4
4
  "description": "AI Agent Skill for NSAuditor AI — gives any AI coding agent built-in knowledge of NSAuditor's MCP tools, schemas, plugins, and security audit workflows.",
5
5
  "keywords": [
6
6
  "nsauditor",
@@ -170,7 +170,7 @@ listings, and default pages.
170
170
  | 1022 | Azure Cloud Scanner | Enterprise | NSG rule analysis + RBAC role assignments + Storage account hardening | CC6.1 / CC6.6 / C1.1 |
171
171
  | 1023 | Zero Trust Checker | Enterprise | Segmentation + encryption + identity + lateral movement scoring (reads OBSERVED open ports) | CC6.6 |
172
172
  | 1024 | GCP Cloud Storage Auditor (EE 0.6.8) | Enterprise | Multi-cloud parity sister of plugin 1020 AWS S3. 6 dimensions: bucket-level IAM public bindings (allUsers = CRITICAL, allAuthenticatedUsers = HIGH); Uniform Bucket-Level Access enforcement (closes legacy bucket-ACL false-PASS class); Object Versioning; Bucket Lock retention policy (SEC 17a-4 / FINRA 4511 WORM-alignment); CMEK via Cloud KMS (four-tier custody ladder); bucket-level access logging. NEW SDK dep `@google-cloud/storage`. | CC6.1 / CC6.6 / CC7.1 / C1.1 / C1.2 / A1.2 |
173
- | 1025 | GCP IAM Project-Level Auditor (NEW EE 0.7.0; **EXTENDED EE 0.7.1 v2** — 3 dims → 7 dims via in-place R2 expansion closing all 4 v1-deferred dims; 17 same-session reviewer folds = NEW HIGH-WATER MARK vs 0.7.0's 12) | Enterprise | First plugin in the v0.7.x GCP-IAM-deep-audit cohort. Mirrors plugin 1030 AWS IAM Deep Auditor's shadow-admin discipline adapted to the GCP IAM data model. **7 dimensions (v2 EE 0.7.1):** **v1 dims preserved:** project-scope public-member bindings (allUsers = CRITICAL, allAuthenticatedUsers = HIGH at the project root); admin-equivalent role inventory across 12 predefined sensitive roles (roles/owner, roles/editor, roles/iam.securityAdmin, roles/resourcemanager.projectIamAdmin, the iam.serviceAccount* impersonation cohort, the workloadIdentity cohort); IAM Conditions classifier on sensitive-role bindings (restrictive CEL token allowlist = PASS, absent on sensitive = MEDIUM, vacuous = LOW + evidenceGap). **v2 NEW dims (EE 0.7.1):** **dim 4 custom-role permission audit** (CC6.1; `iam.projects.roles.list` view=FULL; `*` wildcard = CRITICAL; admin-equivalent permission intersection across `_ADMIN_EQUIVALENT_PERMISSIONS` 16-entry allowlist = HIGH — expanded 11→16 via R1-MED-2 fold to include `iam.serviceAccounts.create` + `.disable` + `.enable` for audit-evasion class + `iam.denypolicies.create` + `iam.workloadIdentityPools.create` for federation backdoor) + **dim 5 SA key custody** (CC6.1 + C1.1 dual-mapped; user-managed long-lived keys = HIGH — canonical SA-credential-leakage class; 90-day rotation narrative-uplift; per-SA `keysFetchError` propagation closes silent-PASS false-clean class via R2-HIGH-5 fold) + **dim 6 SA impersonation graph BFS** (CC6.1; mirrors plugin 1030 shadow-admin BFS adapted to GCP IAM data model; per-PATH visited Set for cycle defense; default depth cap = 4; walks the 3 canonical impersonation roles `roles/iam.serviceAccountTokenCreator` + `serviceAccountUser` + `serviceAccountOpenIdTokenCreator`; 2-hop = HIGH, 3+ hop = CRITICAL; **project-scope impersonation grants surface independently as CRITICAL `_CAT_SA_IMPERSONATION_PROJECT_SCOPE`** via R1-HIGH-2 fold — real GCP privesc class entirely missed pre-fold; public-sentinel impersonation grants surface INDEPENDENTLY of BFS as CRITICAL `_CAT_SA_IMPERSONATION_PUBLIC`) + **dim 7 Organization Policy constraint enumeration** (CC6.6 + C1.1 dual-mapped; `@google-cloud/org-policy` ListPolicies; 4 sensitive constraints `iam.disableServiceAccountKeyCreation` + `.disableServiceAccountKeyUpload` + `iam.allowedPolicyMemberDomains` + `iam.automaticIamGrantsForDefaultServiceAccounts`; enforce/denyAll/allowlist = PASS; absent/not-enforced/`reset:true` = MEDIUM via R1-HIGH-4 fold). **NEW `utils/gcp_auth.mjs`** honors `GOOGLE_IMPERSONATE_SERVICE_ACCOUNT` env var (closes the gap where GCP client libraries do NOT honor gcloud CLI's `auth/impersonate_service_account` config). **R-CRITICAL fold (R2-CRITICAL-1) — EE-RT.20 R1-CRITICAL-1 class recurrence catch**: soc2.json PASS-tier SA-key patterns silently failed to match when plugin emitted `(display: 'X')` between email and `has` clause; production false-clean impact would have been ~100% on real GCP fixtures. Patterns rewritten to `'[^']+'.*has`; displayName-populated test fixtures added. **+22 new soc2.json mappings** (plugin 1025 total 11 → 33: 12 CC6.1 + 3 CC6.6 + 7 C1.1 dual-maps). **NEW SDK deps:** `googleapis` + `@google-cloud/org-policy` in optionalDependencies (lazy-loaded with graceful degradation; missing SDK skips affected dim cohort). | CC6.1 / CC6.6 / C1.1 |
173
+ | 1025 | GCP IAM Project-Level Auditor (NEW EE 0.7.0; **EXTENDED EE 0.7.1 v2** — 3 dims → 7 dims via in-place R2 expansion closing all 4 v1-deferred dims; 17 same-session reviewer folds = NEW HIGH-WATER MARK vs 0.7.0's 12) | Enterprise | First plugin in the v0.7.x GCP-IAM-deep-audit cohort. Mirrors plugin 1030 AWS IAM Deep Auditor's shadow-admin discipline adapted to the GCP IAM data model. **7 dimensions (v2 EE 0.7.1):v1 dims preserved:** project-scope public-member bindings (allUsers = CRITICAL, allAuthenticatedUsers = HIGH at the project root); admin-equivalent role inventory across 12 predefined sensitive roles (roles/owner, roles/editor, roles/iam.securityAdmin, roles/resourcemanager.projectIamAdmin, the iam.serviceAccount* impersonation cohort, the workloadIdentity cohort); IAM Conditions classifier on sensitive-role bindings (restrictive CEL token allowlist = PASS, absent on sensitive = MEDIUM, vacuous = LOW + evidenceGap). **v2 NEW dims (EE 0.7.1):dim 4 custom-role permission audit** (CC6.1; `iam.projects.roles.list` view=FULL; `*` wildcard = CRITICAL; admin-equivalent permission intersection across `_ADMIN_EQUIVALENT_PERMISSIONS` 16-entry allowlist = HIGH — expanded 11→16 via review fold to include `iam.serviceAccounts.create` + `.disable` + `.enable` for audit-evasion class + `iam.denypolicies.create` + `iam.workloadIdentityPools.create` for federation backdoor) + **dim 5 SA key custody** (CC6.1 + C1.1 dual-mapped; user-managed long-lived keys = HIGH — canonical SA-credential-leakage class; 90-day rotation narrative-uplift; per-SA `keysFetchError` propagation closes silent-PASS false-clean class via review fold) + **dim 6 SA impersonation graph BFS** (CC6.1; mirrors plugin 1030 shadow-admin BFS adapted to GCP IAM data model; per-PATH visited Set for cycle defense; default depth cap = 4; walks the 3 canonical impersonation roles `roles/iam.serviceAccountTokenCreator` + `serviceAccountUser` + `serviceAccountOpenIdTokenCreator`; 2-hop = HIGH, 3+ hop = CRITICAL; **project-scope impersonation grants surface independently as CRITICAL `_CAT_SA_IMPERSONATION_PROJECT_SCOPE`** via review fold — real GCP privesc class entirely missed pre-fold; public-sentinel impersonation grants surface INDEPENDENTLY of BFS as CRITICAL `_CAT_SA_IMPERSONATION_PUBLIC`) + **dim 7 Organization Policy constraint enumeration** (CC6.6 + C1.1 dual-mapped; `@google-cloud/org-policy` ListPolicies; 4 sensitive constraints `iam.disableServiceAccountKeyCreation` + `.disableServiceAccountKeyUpload` + `iam.allowedPolicyMemberDomains` + `iam.automaticIamGrantsForDefaultServiceAccounts`; enforce/denyAll/allowlist = PASS; absent/not-enforced/`reset:true` = MEDIUM via review fold). **NEW `utils/gcp_auth.mjs`** honors `GOOGLE_IMPERSONATE_SERVICE_ACCOUNT` env var (closes the gap where GCP client libraries do NOT honor gcloud CLI's `auth/impersonate_service_account` config). **review fold — class recurrence catch**: soc2.json PASS-tier SA-key patterns silently failed to match when plugin emitted `(display: 'X')` between email and `has` clause; production false-clean impact would have been ~100% on real GCP fixtures. Patterns rewritten to `'[^']+'.*has`; displayName-populated test fixtures added. **+22 new soc2.json mappings** (plugin 1025 total 11 → 33: 12 CC6.1 + 3 CC6.6 + 7 C1.1 dual-maps). **NEW SDK deps:** `googleapis` + `@google-cloud/org-policy` in optionalDependencies (lazy-loaded with graceful degradation; missing SDK skips affected dim cohort). | CC6.1 / CC6.6 / C1.1 |
174
174
  | 1030 | AWS IAM Deep Auditor | Enterprise | Shadow-admin path detection via BFS over PassRole / AssumeRole / federated trust; restrictive-Condition allowlist (Auth0 / Okta / Cognito) | CC6.1 |
175
175
  | 1040 | AWS CloudTrail Operational Integrity | Enterprise | Trail health + log-file validation + KMS-CMK; CloudWatch alarm coverage vs CIS AWS Foundations Benchmark v1.5 §3.1–3.14; cross-account S3 trail-destination WORM verification (SEC 17a-4 / FINRA 4511) | CC7.2 / CC7.3 |
176
176
  | 1050 | AWS API Gateway Assurance | Enterprise | Per-method/route authorization classifier; custom-domain TLS policy; stage-level access logging / throttling / WAF; public-endpoint exposure; Lambda authorizer cross-reference via lambda:GetFunction | CC6.1 / CC6.6 / CC6.7 / CC7.1 / A1.2 |
@@ -182,13 +182,13 @@ listings, and default pages.
182
182
  | 1110 | AWS IAM Effective Decrypt-Path Auditor | Enterprise | Cross-plugin reconciler: walks IAM policies for kms:Decrypt / kms:ReEncrypt / kms:GenerateDataKey grants and cross-references against destination KMS key policies (plugin 1070) to compute effective decrypt path; closes NotAction-implicit-decrypt false-PASS class | CC6.1 / CC6.6 / C1.1 / C1.2 |
183
183
  | 1120 | AWS S3 Lifecycle + Cross-Region Replication Auditor | Enterprise | S3 lifecycle policy enumeration (CC7.1 retention-cadence) + cross-region replication topology (A1.2 DR substrate); destination-bucket reachability verification closes silent-PASS class where replication source FAILED but emitted clean | C1.1 / C1.2 / A1.2 |
184
184
  | 1130 | AWS Backup Auditor — headline thread | Enterprise | The largest single-plugin institutional-hardening arc in the EE codebase (~7800 lines, 545 tests). Audits Plans + Vaults + Recovery Points + Selections + Frameworks + Restore Testing + ReportPlans + Legal Holds + VaultType + Vault Tags + Vault Access Policy. **12-dimension air-gapped vault attestation arc** for LogicallyAirGappedBackupVault: 6 cryptographic-isolation mechanisms (vault TYPE + ARN account-segment-separation + destination KMS key-policy clean + destination KMS Grants clean + MRK-replica topology clean + source-account VPC-endpoint policy clean) + 6 substrate dimensions (PITR/retention/encryption/RestoreTesting/Legal Holds/vault Access Policy) | CC6.3 / CC6.6 / CC7.1 / CC8.1 / C1.1 / C1.2 / A1.2 |
185
- | 1140 | AWS RDS Auditor (v3 — extended in EE 0.4.8) | Enterprise | **10 SOC 2 substrate-evidence dimensions** (v1=3 + v2=4 + v3=3). **v1+v2 (preserved):** Multi-AZ (A1.2) + storage encryption at rest with KMS-key custody classification + **kms:DescribeKey cross-reference promotes UNVERIFIABLE `:key/UUID` ARN shapes to deterministic PASS/MEDIUM** + parameter-group SSL enforcement (postgres rds.force_ssl + mysql require_secure_transport) + BackupRetentionPeriod (7-day baseline) + PubliclyAccessible + IAMDatabaseAuthenticationEnabled + snapshot encryption. **v3 NEW (database audit-logging, EE 0.4.8 EE-RT.14 v3):** **dim 8 pgAudit enabled** (postgres-only — `DescribeDBParameters → pgaudit.log` non-empty AND `shared_preload_libraries` contains `pgaudit` token per R-MEDIUM-2 reviewer-fold **false-PASS closure** — Postgres silently ignores the GUC when SPL omits pgaudit; new MEDIUM `rds-pgaudit-misconfigured` category; non-postgres engines = INFO + engine-not-applicable) + **dim 9 CloudWatch Logs exports** (`EnabledCloudwatchLogsExports` engine-dispatched: postgres essential=`postgresql`; mysql/mariadb essential=`error`; oracle essential=`audit`+`trace`; sqlserver essential=`error`; empty=HIGH / partial=MEDIUM / complete=PASS) + **dim 10 CloudWatch Logs retention** (`logs:DescribeLogGroups` enumeration on engine-dispatched prefix per R-HIGH-1 reviewer-fold **false-INFO closure**: `/aws/rds/instance/<id>/` for non-Aurora, `/aws/rds/cluster/<DBClusterIdentifier>/` for `aurora-*` engines — pre-fold hard-coded the instance path → 0 log groups on every Aurora node = false-INFO MEDIUM across the whole Aurora fleet; 30-day institutional baseline operator-tunable via `opts.auditLogRetentionPassMinDays` clamped 1..3653). **9 same-session v3 reviewer folds** (HIGH-1 Aurora cluster log-path; MEDIUM-2 pgAudit-SPL cross-check; MEDIUM-3/4/5 cwl-opt-out + retentionDistribution + transient-error distinct categories; LOW-8/9/10 + NIT-12). **Real-AWS smoke END-TO-END against `<operator-test-account>`** (in-place modification of rds-compliant-cluster; cost $0): ALL 3 v3 PASS-path classifiers validated + unmodified rds-violator-db validates HIGH path. **First 0.4.x extension cycle to validate BOTH PASS-path AND HIGH-path classifiers** against real AWS in the same smoke run. | A1.2 / CC6.1 / CC6.6 / C1.1 / CC7.2 / CC7.3 |
186
- | 1150 | AWS SQS/SNS Auditor (NEW EE 0.4.4 v1; **EXTENDED EE 0.5.1 v2** — 5 → 7 dimensions: CloudWatch alarm coverage on SQS ApproximateAgeOfOldestMessage + SNS NumberOfNotificationsFailed; first plugin-1150 dim to cross an SDK boundary — SQS+SNS → CloudWatch) | Enterprise | First multi-service plugin in EE codebase. **7 dimensions total** (v1: 5; v2 EE 0.5.1 added dims 6 + 7). **v1 dims preserved:** SQS encryption at rest (SqsManagedSseEnabled OR KmsMasterKeyId; four-tier classification) + SQS transit-encryption policy (aws:SecureTransport Deny statement) + SNS topic encryption at rest + SNS topic-policy permissive-Principal (full NotAction-Allow + NotPrincipal-Allow + Resource-scope filtering per plugin 1070 + 1110 precedent) + SQS dead-letter queue presence (dual-mapped A1.2 + CC7.1). **v2 EE 0.5.1 NEW dims:** **dim 6 — SQS ApproximateAgeOfOldestMessage CloudWatch alarm coverage** (CC7.2 + A1.2 dual-mapped) — per-queue classifier `_classifySqsAgeAlarmCoverage` checks for at least one `AWS/SQS:ApproximateAgeOfOldestMessage` MetricAlarm with the queue's `QueueName` dimension AND **both** `ActionsEnabled=true` AND non-empty `AlarmActions[]`. Four outcomes: PASS `sqs-age-alarm-covered` / MEDIUM `sqs-age-alarm-missing` (silent backlog growth class) / LOW `sqs-age-alarm-actions-disabled` (matching alarm with all disabled OR empty AlarmActions — informational-only) / LOW + evidenceGap `sqs-age-alarm-coverage-unverifiable` (CW SDK unavailable / DescribeAlarms AccessDenied / queue name un-extractable / pagination truncated). **dim 7 — SNS NumberOfNotificationsFailed CloudWatch alarm coverage** (CC7.2 + A1.2 dual-mapped) — per-topic analogue with `AWS/SNS:NumberOfNotificationsFailed` metric + `TopicName` dimension; same four-tier severity ladder. **v2 single-fetch budget pattern** (mirrors plugin 1040): `_enumerateMetricAlarms` paginates `cloudwatch:DescribeAlarms` ONCE per scan; `_buildAlarmIndex` builds per-resource Maps (`sqsAgeByQueueName` + `snsFailureByTopicName`) for O(1) per-resource lookup. Pagination cap default 20 pages × 100 alarms = 2000 alarm ceiling, operator-tunable via `opts.cwAlarmPageCap`. **Soft-degrade contract** — CW SDK load failure routes per-resource classifier to LOW + evidenceGap rather than blocking SQS+SNS primary substrate audit. **R-CRITICAL v2 fold (false-CLEAN closure)**: `actionable` requires BOTH `ActionsEnabled=true` AND non-empty `AlarmActions[]` array — CloudWatch fires NO operator paging when AlarmActions=[] even with ActionsEnabled=true; pre-fold an `{ActionsEnabled:true, AlarmActions:[]}` alarm passed as PASS-tier evidence on a structurally broken alarm. Discriminates "all disabled" vs "all empty actions" in remediation narrative. **R-HIGH v2 fold**: soc2.json PASS-tier titlePatterns narrowed to anchor on `AWS/SQS:ApproximateAgeOfOldestMessage` / `AWS/SNS:NumberOfNotificationsFailed` clauses. **R-MEDIUM/R-LOW v2 folds**: defensive shape guard + multi-alarm collision tests + FIFO end-to-end + corrupted-shape defensive tests. **7 same-session v2 reviewer folds** (1 CRITICAL + 1 HIGH + 2 MEDIUM + 1 LOW + 1 NIT; 6 folded same-session, 1 NIT deferred). **No new SDK dependencies** — `@aws-sdk/client-cloudwatch` already declared in optionalDependencies since EE 0.4.0 (used by plugin 1040). **23 soc2.json titlePattern entries total** (11 v1 + 12 v2: 8 CC7.2 + 4 A1.2 dual-mapped). **Synthetic-mock validation only** this cycle for v2 — real-AWS smoke deferred (no SQS/SNS paired fixtures yet in operator's internal test infrastructure; ship-without per documented gap, EE 0.5.0 SES precedent). Closes the **"messaging monitoring" SOC 2 dimension** per `tasks/things-to-check.md` §4 institutional checklist: *"Track SQS ApproximateAgeOfOldestMessage and SNS delivery failure metrics inside CloudWatch to prove operational monitoring."* | C1.1 / CC6.6 / A1.2 / CC7.1 / CC7.2 |
187
- | 1160 | AWS VPC Endpoints / PrivateLink Auditor (**NEW EE 0.6.0** — first new plugin since EE 0.4.7; first plugin to audit the PrivateLink isolation boundary; plugin count 20 → 21) | Enterprise | Audits AWS VPC endpoints (Interface + Gateway flavors) against **4 SOC 2 substrate-evidence dimensions** — VPC endpoints govern VPC-to-managed-service traffic without public-internet traversal (PrivateLink primitive). **Complements plugin 1170 SG perimeter** (1170 = layer-4 ingress; 1160 = service-layer perimeter). **Dim 1 — Endpoint policy permissive principals** (CC6.6 segmentation; wildcard-Principal classifier mirroring plugin 1150 SNS topic-policy discipline; NotPrincipal-Allow + Action-sensitivity filter via `_VPCE_SENSITIVE_ACTIONS` frozen Set; unconditional wildcard on sensitive action = CRITICAL — PrivateLink isolation BROKEN at policy layer; WITH Condition = HIGH walkthroughRequired). **Dim 2 — PrivateDNS enabled** (CC6.6; Interface + PrivateDnsEnabled=false = MEDIUM silent-bypass class — clients still resolve service-public hostname → traffic over public internet; Gateway = INFO not-applicable). **Dim 3 — Endpoint state** (A1.2 + CC7.2; `available` = PASS / `failed` = HIGH silent-failure / transient = INFO / unknown enum = LOW + evidenceGap). **Dim 4 — Endpoint type substrate disclosure** (Privacy + CC6.6; INFO substrate evidence per VPC). **2 same-session reviewer folds** (R-MEDIUM unknown-type fail-safe defaults to Interface — safer audit path; R-NIT Effect case-insensitivity regression pin). **No new SDK deps** — `@aws-sdk/client-ec2` already declared since EE 0.4.5 (used by plugin 1170 + plugin 1180 v2). 7 new soc2.json titlePattern entries (5 CC6.6 + 2 CC7.2/A1.2 dual-mapped). 57 plugin tests + 2 reviewer-fold pins (59 total). Synthetic-mock validation only — no VPC endpoint paired fixtures yet in operator's internal test infrastructure. | CC6.6 / A1.2 / CC7.2 / Privacy (substrate) |
188
- | 1170 | AWS EC2 SG Perimeter Auditor (v3.1 — extended in EE 0.6.7 with `_buildSgReferenceGraph` edge-dedup; v3 EE 0.6.6 SG→SG transitive chain reachability; v2 EE 0.4.6 RESTRICTED_PORTS 23-port baseline; v1 EE 0.4.5 base) | Enterprise | Orthogonal evidence to plugin 1023 zero-trust-checker (1023 reads OBSERVED open ports; 1170 reads DECLARED SG policy via DescribeSecurityGroups). **v3 dimensions: 6 v2 dims + 1 NEW v3 transitive-reachability dim.** **v3 EE 0.6.6 SG→SG transitive chain reachability** — `_buildSgReferenceGraph` builds nodes + directed edges per UserIdGroupPairs reference (cross-VPC edges flagged at edge-build time). `_findPubliclyReachableSgs` identifies SGs with 0.0.0.0/0 or ::/0 ingress as BFS roots. `_walkTransitiveReachability` BFS-walks the graph with cycle defense (per-traversal `visited` Set cloned at each branch), depth cap (default 5, max 20 — operator-tunable via `transitiveChainDepthCap`), per-target chain cap (default 10, max 100 — operator-tunable via `transitiveChainsPerTargetCap`). `_classifyTransitiveReachability` emits per-target findings: **2-hop = HIGH** (direct from public root, one indirection) / **3+ hop = CRITICAL** (operator-blindness principle — deeper chains less likely to be noticed). Cross-VPC edges skipped (out-of-scope for v3 v1 — cross-VPC peering / Transit Gateway is a separate audit surface); surfaced as INFO trailer. **v3 v1 simplifications**: per-hop port-flow tracked but NOT intersected (`walkthroughRequired=true` on every transitive finding — operator walkthrough verifies port-flow alignment across the chain); cross-VPC out of scope. **v3 R-HIGH-1 reviewer fold (EE 0.6.6)**: BFS short-circuits enqueue past per-target cap (closes path-enumeration explosion on hub-and-spoke topologies — pre-fold the BFS marked the target truncated but kept cloning `path` and `visited` Sets and walking past the cap, causing O(paths × depth) heap usage on 200+ SG accounts with fan-out ≥10). **v3 R-LOW-2 reviewer fold**: depth-cap-hit surfaced separately from per-target-cap (closes silent-deep-truncation false-CLEAN class — pre-fold a graph deeper than `transitiveChainDepthCap` silently truncated without operator-visible signal). New operator opts: `skipTransitiveReachability` / `transitiveChainDepthCap` / `transitiveChainsPerTargetCap` / `transitiveChainSamplesPerFindingCap`. **v3.1 EE 0.6.7 closes the edge-dedup R2-deferred item**: `_buildSgReferenceGraph` now dedupes edges by `(sourceGroupId, targetGroupId)` with `ports` aggregated as array of `{protocol, fromPort, toPort}`. Pre-fold a real-world ALB-fronting-app SG with 3 ingress perms on different ports (80/443/8080) referencing the same source SG emitted 3 distinct edges A→B; BFS treated each as separate chain, inflating `chainCount` 2-5× and exhausting per-target chain caps on noise. Post-fold the BFS sees exactly 1 chain per distinct (source, target) pair. `isCrossVpc` AND-aggregation per `[[conservative_classifier_principle]]` (any same-VPC pair → merged edge same-VPC → walked rather than silently skipped). Classifier port-render accepts both v3.1 array shape and v3 single-object shape (back-compat preserved). **v3.1 R-MEDIUM-1 fold**: arrival-order independence locked with 2 regression fixtures + JSDoc tightening. **v3.1 R-LOW-1 fold**: partial-render contract on malformed port specs locked with 2 fixtures. **v3.1 R-LOW-2 fold**: `_portKeys` scratch lifetime documented (MUST NOT escape). 3 new soc2.json mappings under CC6.6 (transitive-public HIGH `Security Group ... shortest = 2 hops` + transitive-public CRITICAL `... shortest = 3+ hops` + INFO truncation trailer `SG→SG transitive reachability walk truncated:`). **v2 EE 0.4.6 preserved**: 6 dimensions — IPv4 0.0.0.0/0 ingress to **RESTRICTED_PORTS (v2: 23 ports per CIS AWS Foundations v3.0)** — SSH/RDP/MS SQL/MySQL/Postgres/Redshift/Redis/Memcached/MongoDB/Elasticsearch/CouchDB/Docker/Kubelet/K8s-API/etcd/Kibana/InfluxDB/Kafka/Consul/ZooKeeper/Vault CRITICAL + IPv6 ::/0 sibling CRITICAL + all-protocol (-1) wildcard CRITICAL + public ingress to non-restricted ports INFO + egress 0.0.0.0/0 INFO + orphan SG (no attached ENI) LOW governance. **v2: `opts.additionalRestrictedPorts` operator-config knob** + **per-SG cardinality cap with rollup trailer** (defends against finding-size DoS on 1000+ SG accounts) + **system-managed-SG name-prefix exclusion list** (ElasticMapReduce- / eks-cluster-sg- / AWSServiceRole / awseb- prefixes excluded from orphan-detection). UserIdGroupPairs rules surfaced as INFO + evidenceGap at v2; **v3 (EE 0.6.6) now closes transitive SG→SG chain analysis** | CC6.6 / CC6.2 |
189
- | 1180 | AWS ElastiCache Redis Auditor (v2 — extended in EE 0.4.9) | Enterprise | First plugin in 1170-1180 ID range. **6 SOC 2 substrate-evidence dimensions** (v1 unchanged in count; v2 grew dims 2 + 6 in scope). **v1 dims preserved:** transit encryption (TransitEncryptionEnabled wraps RESP in TLS; HIGH on disabled) + Redis AUTH/IAM-auth user groups (PASS on UserGroupIds; MEDIUM no-authentication) + Multi-AZ deployment (HIGH disabled / INFO standalone-not-applicable / INFO+evidenceGap on transient enabling/disabling states) + SnapshotRetentionLimit cadence (HIGH=0 / MEDIUM 1-6 / PASS ≥7; operator-tunable `opts.snapshotRetentionPassMinDays`). Dual API enumeration (DescribeReplicationGroups + DescribeCacheClusters) with inter-API dedup. **v2 GROWN dims (EE 0.4.9 EE-RT.17 v2):** **dim 2 at-rest encryption + KMS key custody** — original four-tier ladder (HIGH disabled → MEDIUM AWS-owned-default → MEDIUM `alias/aws/elasticache` → PASS customer-managed CMK + LOW+evidenceGap on `:key/UUID` per conservative-classifier-principle) **PLUS v2 kms:DescribeKey cross-reference promotion** (mirrors plugin 1140 v2): UNVERIFIABLE `:key/UUID` ARN shapes promoted via KeyMetadata.KeyManager to deterministic PASS `elasticache-at-rest-customer-managed-kms-promoted` (CUSTOMER) / MEDIUM `elasticache-at-rest-aws-managed-kms-promoted` (AWS); conservative on AccessDenied/NotFound/unknown KeyManager. **dim 6 subnet routing** — v1 INFO substrate (`elasticache-subnet-group-substrate`) plus **v2 ec2:DescribeRouteTables verifier** that walks the cache subnet group's subnets via elasticache:DescribeCacheSubnetGroups + filtered ec2:DescribeRouteTables, classifying each subnet on Internet Gateway route presence via /^igw-[a-f0-9]+$/i (correctly excludes egress-only eigw-): HIGH `elasticache-subnet-public-route-detected` (with per-subnet `igwDestinationsBySubnet` evidence per R-HIGH-1 fold) / PASS `elasticache-subnet-private-verified` (all subnets verified IGW-free) / LOW + evidenceGap `elasticache-subnet-main-rt-inheritance` per R-MEDIUM-2 false-NEGATIVE closure (default-VPC main-RT typically routes `0.0.0.0/0 → igw-*`) / LOW + evidenceGap `elasticache-subnet-verification-unverifiable` on AccessDenied. **Cross-plugin sister of plugin 1170 SG perimeter** (layer-3 subnet→IGW vs layer-4 SG ingress policy). **7 same-session v2 reviewer folds** (HIGH-1 IGW destination evidence; MEDIUM-2 main-RT-inheritance false-NEGATIVE closure; MEDIUM-3 cache-key naming; LOW-6/7/9/10/11 + NIT-12). **Per-resource caching** prevents N×M API explosion (kmsKeyManagerCache + subnetGroupCache + subnetSetRoutingCache). **No new SDK deps** — @aws-sdk/client-kms + @aws-sdk/client-ec2 reused from EE 0.4.5. **Real-AWS smoke END-TO-END against <operator-test-account>**: R-MEDIUM-2 fold escalation demonstrably firing in production (`redis-leaky-cache` → dim 6 LOW main-RT-inheritance). | CC6.1 / CC6.2 / CC6.6 / A1.2 / C1.1 |
190
- | 1200 | AWS Inspector2 / GuardDuty Enablement Auditor (NEW EE 0.6.1, EXTENDED EE 0.6.2 v2 multi-region + FindingPublishingFrequency + Inspector2 baseline expansion, EXTENDED EE 0.6.3 v3 alerting-destination dim closes substrate-without-sink false-PASS class, EXTENDED EE 0.6.4 v4 EventBridge target verification + multi-failedAccount + trigger uniformity, EXTENDED EE 0.6.5 v5 dead-target companion-LOW + sentinel observability + R-NIT named-constants, **EXTENDED EE 0.6.6 v6** — dead-target probe warm-up (IAM role + EventBridge API destination + CloudWatch Logs); plugin count UNCHANGED at 22 — existing plugin grew ~870 → ~1400 → ~2100 → ~2400 → ~2800 → ~3000 lines) | Enterprise | **v6 EE 0.6.6 dead-target probe warm-up** (closes the 0.6.5 R2-deferred long tail of unverifiable ARN shapes): three new branches in `_probeTargetLiveness` — **IAM role** (`iam:GetRole` on path-stripped role NAME extracted from `arn:aws:iam::ACCOUNT:role/[path/]NAME`; new SDK dep `@aws-sdk/client-iam`) + **EventBridge API destination** (`events:DescribeApiDestination` reuses existing `_EventBridgeSdk`) + **CloudWatch Logs log group** (`logs:DescribeLogGroups` with `logGroupNamePrefix` filter + **exact-name disambiguation guard** `groups.some((g) => g.logGroupName === logGroupName)` so prefix-match siblings don't false-LIVE; new SDK dep `@aws-sdk/client-cloudwatch-logs`). Companion-LOW emission contract unchanged (existing CC7.1 titlePattern is target-type-agnostic). **5 v6 R1 reviewer folds** (0 R-CRITICAL — clean review pass; 1 R-HIGH + 2 R-MEDIUM + 2 R-LOW): R-HIGH-1 (plugin 1170 v3) BFS short-circuits enqueue past per-target cap + **R-MEDIUM-1 IAM `NoSuchEntityException` / `NoSuchEntity` lifted into `_DEAD_TARGET_NOTFOUND_ERROR_NAMES` Set** (pre-fold the bare disjunction `err.name === "NoSuchEntityException"` at the IAM catch site bypassed the Set AND silently disabled `_retryOnNotFound` for IAM — the canonical worst-case for AWS eventual consistency with IAM lag 10-30s documented; **9th cumulative recurrence** of the `[[emit_literal_set_drift]]` class across the EE codebase; post-fold bare disjunction collapsed to `_isDeadTargetNotFoundError(err)` and eventual-consistency retry restored for IAM) + **R-MEDIUM-2 IAM partition-routing contract documented** at `_loadIamSdk` (`iam:GetRole` is a global API resolving per-partition — orchestrators wiring `opts._iamClient` must construct a single global IAM client per-partition NOT per-region; passing a commercial region in GovCloud / aws-cn / ISO flips the partition and routes to a wrong endpoint) + **R-LOW-2 (plugin 1200 v6) API destination ARN regex future-proofed** (trailing `/` made optional in `:api-destination\/([^/]+)` so future AWS ARN shapes without UUID suffix don't false-malformed). **v6.1 EE 0.6.7 closes the CloudWatch Logs probe retry-on-empty parity R2-deferred item**: `_retryOnNotFound` accepts an optional retry-on-result predicate; CWL Logs call site passes a predicate that fires retry when the response carries no exact-name match (covers both empty and prefix-only-sibling responses). **Restructured to two-phase to cap total network calls at 2 on compound paths** — Phase 1 = initial call + thrown-NotFound retry; Phase 2 = result-based retry; phases are MUTUALLY EXCLUSIVE (single retry total). A nested-try design would have layered both retries on compound paths (first-call empty → retry → second-call throws RNF → retry again), producing 3 network calls. The per-call-site outer catch routes a second-call thrown error (NotFound → DEAD; AccessDenied → UNVERIFIABLE). Existing call sites (Lambda / SNS / SQS / IAM / EventBridge API destination) pass only two args; the default `retryOnResultPredicate = null` cleanly skips Phase 2. **v6.1 R-LOW-1 fold**: compound-path coverage locked with 2 tests — transient empty → second-call AccessDenied → UNVERIFIABLE / transient empty → second-call thrown RNF → DEAD; both verify total network calls = 2 (drove the two-phase restructure decision). No new soc2.json mappings (companion-LOW pattern target-type-agnostic). v6 tests: +5 (2 IAM retry-regression: transient-NoSuchEntity-retry-succeeds + lowercase-NoSuchEntity-retry-then-DEAD; reviewer-fold regression pins also include 3 plugin 1170 v3 fixtures: hub-and-spoke per-target-cap + depthCapHit-true + depthCapHit-false). **v5 EE 0.6.5 v4-reviewer-cleanup cycle** (closes 4 R2-deferred items from EE-RT.20.3): **Dead-target companion-LOW** — closes the EE 0.6.4 R-HIGH-2 documented limitation. Per-target liveness probes for Lambda (`lambda:GetFunction` on full qualified ARN — alias/version correctness verified server-side) + SNS (`sns:GetTopicAttributes`) + SQS (`sqs:GetQueueUrl` + `GetQueueAttributes` — partition-aware via SDK URL resolution; works on aws-cn / aws-us-gov / aws-iso). New `_probeTargetLiveness` helper with parallel probes via Promise.all + per-target timeout (default 2s; operator-tunable via `deadTargetProbeTimeoutMs`). One-retry on NotFound with 750ms backoff (eventual-consistency defense). New MEDIUM verdict `*-alerting-destination-dead-targets` emitted as companion alongside PASS when at least one Target.Arn points to deleted resource. `deadTargetArnsTotal` + `deadTargetArnsTruncated` for JSON-consumer visibility on 11+ case. IAM role + API destination + CloudWatch Logs target probes deferred to 0.6.6 (3-4 more IAM grants). New operator opt `skipTargetLivenessProbe: true`. **Sentinel observability** — rule shape extended with `targetVerificationReason` (AccessDenied / SdkUnavailable / BeyondCap / SkippedByOpts) stable enum; classifier surfaces `targetVerificationReasonBreakdown` in unverifiable verdict details. **R-NIT named-constants** — `SH_HUB_NOT_ENABLED_ERROR_NAMES` frozen Set replaces 2 bare-string sites in SecurityHub helpers per `[[emit_literal_set_drift]]`. **Cross-plugin sessionToken sweep (catalog-wide)** — 18 EE AWS plugins (1020-1200) all thread `sessionToken` through their AWS-SDK credentials block. Closes AssumeRole-style auditor credential gap — auditors using `aws sts assume-role` (canonical cross-account audit pattern) had all auto-loaded clients fail signing pre-fold. **5 v5 R1 reviewer folds** (0 R-CRITICAL — clean review pass): R-HIGH-1 case-insensitive NotFound matching (defends against future AWS SDK case changes per `[[aws_string_case_normalization]]` 15× recurrent class) + R-HIGH-2 one-retry on NotFound (eventual-consistency defense; freshly-created resources transiently return NotFound for ~30s) + R-HIGH-3 Lambda probe passes FULL ARN to GetFunction.FunctionName (alias `PROD` pointing to deleted version surfaces as DEAD instead of false-LIVE) + R-HIGH (Explore) parallel probes via Promise.all + per-target timeout + R-MEDIUM-1 SQS partition-aware via `GetQueueUrl` (pre-fold synthesized `amazonaws.com` URL would have crashed on aws-cn / aws-us-gov / aws-iso partitions) + R-LOW-1 cap-constant lift to module-level + R-MEDIUM-2 truncation fields + R-NIT JSDoc accuracy. **R2 reviewer-deferred** (queued for 0.6.6): IAM role + API destination + CloudWatch Logs target liveness probes. 1 new soc2.json mapping rule (CC7.1 companion-LOW dead-target). New SDK deps `@aws-sdk/client-lambda` + `@aws-sdk/client-sns` + `@aws-sdk/client-sqs` (all already in optionalDependencies from prior cycles). v5 tests: +48 (1 R-NIT + 8 sentinel + 20 sessionToken-sweep + 15 dead-target base + 4 R-HIGH-fold regression pins). **v4 EE 0.6.4 reviewer-cleanup cycle** (closes 3 of 4 R2-deferred items from EE-RT.20.2): **R-HIGH-2 EventBridge target verification** — new `_listEventBridgeRuleTargets` helper with defensive NextToken pagination (hard cap 500); per-rule target verification via `events:ListTargetsByRule` (cap default 10 via `opts.targetVerificationRuleCap`; opt-out via `opts.skipEventBridgeTargetVerification`); new MEDIUM verdict `*-alerting-destination-targetless` for sink-less rules (zero Targets — substrate-without-sink at the rule level). **R-MEDIUM-2 multi-failedAccount surface** — Inspector2 helper return-shape `{accountStatus, accessDenied, failedAccounts: array}` (renamed plural; capped at AWS-documented 100); caller emits one LOW per failed account with per-region emission cap 10 + rollup LOW per region. **R-LOW-2 trigger uniformity** — GuardDuty alerting-destination trigger gates on `detector.Status === ENABLED` (matches Inspector2 enabled-only semantic). **5 v4 R1 reviewer folds** (0 R-CRITICAL — clean review pass): R-HIGH-1 cap-skew classifier branch (LOW UNVERIFIABLE not MEDIUM TARGETLESS when cap-exceeded rules could be the actual sink per `[[conservative_classifier_principle]]`) + R-HIGH consolidated `_listEventBridgeRuleTargets` pagination + JSDoc clarity + R-MEDIUM-1 multi-failedAccount per-region emission cap (10 + rollup LOW) + R-MEDIUM-4 boundary tests + R-HIGH-2 dead-target documented-limitation note (per-target liveness probes deferred to 0.6.5 companion-LOW; ~6 new IAM grants). **R2 reviewer-deferred** (queued for 0.6.5): R-LOW-3 sessionToken cross-plugin sweep (18 plugins) + companion-LOW for dead-target ARNs + `targetCount: null` sentinel observability + R-NIT named-constants for InvalidAccessException / ResourceNotFoundException. 1 new soc2.json mapping rule (CC7.1 MEDIUM TARGETLESS). v4 tests: +29 (3 R-LOW-2 + 6 R-MEDIUM-2 + 14 R-HIGH-2 base + 6 R1-fold regression pins). **v3 EE 0.6.3 alerting-destination dim (item c)** — closes the substrate-without-sink false-PASS class. Verifies at least one of EventBridge rule (source=`aws.guardduty`/`aws.inspector2`; `_eventBridgeSourceMatches` recognizes string + `{prefix}` + `{wildcard}` content-filter forms case-insensitively, regex-meta escape in wildcard glob defends against operator IaC) AND/OR SecurityHub product subscription (`_shArnMatchesProduct` boundary-anchored helper; constants `/aws/guardduty` + `/aws/inspector2` strict — does NOT match deprecated Inspector Classic). Verdict tiers per service per region: PASS `*-alerting-destination-present` (EB rule present) / MEDIUM `*-alerting-destination-sh-only` (R-HIGH-1 fold — SH aggregates but doesn't guarantee proactive paging; auditor walkthrough to confirm `aws.securityhub` EventBridge downstream rule) / HIGH `*-alerting-destination-missing` (no path; substrate-without-sink class) / LOW `*-alerting-destination-unverifiable` (AccessDenied / SDK unavailable; conservative classifier). New SDK deps `@aws-sdk/client-eventbridge` + `@aws-sdk/client-securityhub` (optionalDependencies). Operator opt: `skipAlertingDestination: true`. Soft-degrade on auto-load failure → fall back to LOW UNVERIFIABLE. **v3 R-MEDIUM-2 fold** — `_getInspector2AccountStatus` returns `{accountStatus, accessDenied, failedAccount}` distinguishing true AccessDenied from empty-body / SDK-unavailable (was `null | <obj>` pre-fold; caller emitted false `_CAT_INS_ACCESSDENIED` LOW on empty body). **v3 item (d) fold** — surfaces AWS-published `failedAccounts[].errorCode + errorMessage` via new `_CAT_INS_FAILED_ACCOUNT` LOW. **v3 R1 reviewer folds applied** (4 total; 1 R-CRITICAL + 2 R-HIGH + 1 R-LOW): R-CRITICAL-1 SH product ARN substring collision closure (`/aws/inspector` would have matched BOTH Inspector Classic deprecated-2024 AND Inspector2 — false-PASS for stale Classic subscriptions emitting zero findings; boundary-anchored helper + strict `/aws/inspector2` constant) + R-HIGH-1 SH-only PASS narrative split (PASS requires EB rule; SH-only → MEDIUM) + R-HIGH-3 EventBridge content-filter grammar (prefix + wildcard matchers) + R-LOW-1 source case normalization. **R2 reviewer-deferred** (queued for 0.6.4): R-HIGH-2 EB target verification (events:ListTargetsByRule + IAM grant) + R-LOW-2 asymmetric trigger uniformity + R-MEDIUM-2 multi-failedAccount surface + R-LOW-3 sessionToken support cross-plugin sweep. 5 new soc2.json titlePattern entries (4 CC7.1 + 1 CC7.2 PASS) all anchored to actual emission strings per `[[soc2_titlepattern_anchor_drift]]`. v3 tests: +61 (+8 suites) — 5 R-MEDIUM-2 + 5 item-(d) + 30 item-(c) base + 21 R1-fold regression pins. **v2 EE 0.6.2 dims preserved** (4 dims; v2 (a) multi-region enumeration via ec2:DescribeRegions + (b) FindingPublishingFrequency check + (e) Inspector2 baseline expansion +lambdaCode +codeRepository per Inspector2 GA 2024+; operator opts `regions[]` / `skipMultiRegion` / `regionListCap` / `gdFrequencyPassFrequency`; closes FedRAMP / StateRAMP / IL5+ false-PASS class for GovCloud + ISO regions via 4-part region regex fold). **v1 EE 0.6.1 base** — 4 active dims (dim 5 org-scope deferred to 0.6.4): Dim 1 GuardDuty Detector enablement per region (CC7.1 — HIGH `gd-not-enabled`) + Dim 2 GuardDuty protection-feature coverage (CC7.1 institutional baseline) + Dim 3 Inspector2 enablement (CC7.1 + CC7.2 — DISABLED/SUSPENDED = HIGH) + Dim 4 Inspector2 scan-target coverage (CC7.1 zero / CC7.2 partial). Plugin 1200 audits AWS GuardDuty + AWS Inspector2 enablement state across **all opted-in regions** — **foundation-layer institutional evidence for CC7.1 detection procedures + CC7.2 monitoring** (an audit pack without managed-threat-detection evidence has no AWS-native anomaly-detection or CVE-detection stream). **v2 EE 0.6.2 GROWN scope** (closes 3 of 4 R2-deferred items from EE-RT.20 v1): **(a) Multi-region enumeration** — `ec2:DescribeRegions` enumerates opted-in regions (AllRegions=false defensively); per-region GuardDuty + Inspector2 dispatch; per-region findings carry region tag. Operator opts: `regions: string[]` (filter to subset, validated + deduped + capped 64 default), `skipMultiRegion: true` (cost-sensitive opt-out), `regionListCap` (1..256 clamp). Soft-degrade: EC2 SDK load failure / DescribeRegions AccessDenied → fall back to `config.region` + distinct `_CAT_REGION_ENUM_ACCESSDENIED` LOW finding. Back-compat: legacy single-region opts (`_guardDutyClient` / `_inspector2Client` singular) still respected. **(b) GuardDuty FindingPublishingFrequency check** — CC7.1 detection-latency. `_classifyGuardDutyFrequency` 4 outcomes: PASS `gd-frequency-optimal` / LOW `gd-frequency-suboptimal` / LOW `gd-frequency-unverifiable` (null detector or unknown enum). Operator-tunable: `gdFrequencyPassFrequency` (FIFTEEN_MINUTES / ONE_HOUR / SIX_HOURS; default FIFTEEN_MINUTES). **Ordering-based comparison** via `_GD_FREQUENCY_RANK` map (R-HIGH-2 fold) — stricter actual = PASS even when operator tuned baseline upward. **(e) Inspector2 baseline expansion** — `lambdaCode` (Lambda code scanning) + `codeRepository` (Inspector2 GitHub/GitLab scanning, GA 2024+) added to `_INS_INSTITUTIONAL_BASELINE_RESOURCES` (was {ec2, ecr, lambda}; now {ec2, ecr, lambda, lambdaCode, codeRepository}). **v1 dims preserved (4 active dims; dim 5 org-scope deferred to 0.6.3):** Dim 1 GuardDuty Detector enablement per region (CC7.1 — HIGH `gd-not-enabled`) + Dim 2 GuardDuty protection-feature coverage (CC7.1 — institutional baseline S3_DATA_EVENTS / EKS_AUDIT_LOGS / EBS_MALWARE_PROTECTION / RDS_LOGIN_EVENTS / LAMBDA_NETWORK_LOGS / RUNTIME_MONITORING) + Dim 3 Inspector2 enablement (CC7.1 + CC7.2 — DISABLED/SUSPENDED = HIGH) + Dim 4 Inspector2 scan-target coverage (CC7.1 zero / CC7.2 partial). **4 same-session R1 v2 reviewer folds** (network-security + Explore in parallel; 0 R-CRITICAL clean review pass): **R-HIGH-1 region regex GovCloud + ISO support** — pre-fold `^[a-z]{2,}-[a-z]+-[0-9]+$` silently dropped 4-part region IDs (`us-gov-east-1` / `us-iso-east-1` / `us-isob-east-1` / `us-isof-south-1`); operator passing `regions: ["us-gov-east-1"]` got silent skip + false-PASS — institutional-critical for FedRAMP / StateRAMP / IL5+ scope. Post-fold `^[a-z]{2,}(-[a-z]+){1,2}-[0-9]+$` admits 3- AND 4-part IDs. + **R-HIGH-2 frequency ordering not equality** (described above). + **R-MEDIUM-1 `_REGION_LIST_CAP` defensibility** — pre-fold hardcoded 32 silently truncated 4-part regions (AWS has ~40+ regions in 2026); post-fold default raised to 64 + operator-tunable + explicit truncation warning. + **R-LOW-1 EC2 client instrumentation** — operator-supplied `_ec2Client` now receives Thread-H AccessDenied counter + throttle-retry contract uniformly. **R2 reviewer-deferred** (queued in EE-RT.20.2 / 0.6.3): alerting-destination check (item c — needs `@aws-sdk/client-eventbridge` + `@aws-sdk/client-securityhub` integrations) + BatchGetAccountStatus contract verification (item d) + R-MEDIUM-2 `_getInspector2AccountStatus` return-shape refactor + optional dim 5 org-scope. **6 R1 v1 folds (EE 0.6.1) preserved as regression pins**: R1-CRITICAL-1 soc2.json titlePattern misalignment closure (4 patterns) + R1-CRITICAL-1 AccessDenied distinct findings + R1-CRITICAL-2 legacy DataSources case normalization + R1-HIGH-2 SUSPENDED/DISABLED Detector Status guard + R1-HIGH-3/4 dead-code drift closures. **No new SDK deps** — `@aws-sdk/client-guardduty` + `@aws-sdk/client-inspector2` + `@aws-sdk/client-ec2` already in optionalDependencies. 7 new soc2.json titlePattern entries from v1 still anchored. v2 tests: +27 (21 base + 6 R1-fold regression pins). Synthetic-mock validation only — no multi-region GuardDuty/Inspector2 paired fixtures yet in operator's internal test infrastructure. | CC7.1 / CC7.2 |
191
- | 1190 | AWS SES Email Integrity Auditor (NEW EE 0.4.7; EXTENDED EE 0.5.0 v2; CONSOLIDATED EE 0.5.2 v2.1; **EXTENDED EE 0.5.3 v3** — Part A DKIM public-key fingerprint capture/pin + Part B in-band DMARC alignment classifier; 5 same-session reviewer folds incl. 1 R-CRITICAL false-CLEAN closure on truncated DKIM keys via new `_stripControlCharsNoTruncate` helper; v2.1 closed — 7 deferred reviewer-fold items closed + new MEDIUM `ses-dkim-dns-partial-with-transients` category + module-load-time disjointness IIFE + silent-loss-class closure on SES classic API quota exhaustion via `cause: "classic-sdk-quota-exhausted"`) | Enterprise | **v2 EE 0.5.0 GROWN dims:** **dim 1 DKIM** — original substrate **PLUS v2 DKIM CNAME DNS resolution promotion**: each `<token>._domainkey.<domain>` CNAME resolved via node:dns/promises + matched against `<token>.dkim.amazonses.com` (case-insensitive per RFC 1035 §2.3.3); four outcomes PASS `ses-dkim-dns-verified` / MEDIUM `ses-dkim-dns-partial` / **HIGH `ses-dkim-dns-missing` (false-CLEAN closure: SES Status=SUCCESS but DNS removed)** / LOW + evidenceGap `ses-dkim-dns-unverifiable`. **dim 2 MailFrom** — original substrate **PLUS v2 DMARC TXT record parser + MailFrom promotion**: RFC 7489 §6.4 tag-list parser + `_dmarc.<identityDomain>` TXT lookup; five outcomes PASS `ses-dmarc-policy-reject` / MEDIUM `ses-dmarc-policy-quarantine` / HIGH `ses-dmarc-policy-none` / HIGH `ses-dmarc-missing` / LOW + evidenceGap `ses-dmarc-unverifiable`. **R-CRITICAL-1 fold (false-CLEAN closure)**: `pct=0` on `p=reject`/`p=quarantine` functionally equivalent to `p=none`; now routes to HIGH `ses-dmarc-policy-none`. **R-HIGH-1 fold (subdomain-takeover false-NEGATIVE closure)**: `sp` subdomain-policy override now evaluated — `p=reject; sp=none` downgrades to HIGH with `dmarcSpWeakens` (subdomain phishing wide open while apex protected). **dim 4 sending-auth policies** — original IAM-policy classifier **PLUS v2 SES classic GetIdentityPolicies parity**: `_loadSesClassicSdk` restored; cross-API discrepancy emits HIGH `ses-classic-policy-discrepancy` (classic-only — canonical false-NEGATIVE class) / MEDIUM (`_canonicalSort` JSON deep-equal ignores whitespace + key-order drift) / INFO (v2-only benign). Conservative on classic SDK unavailable / AccessDenied → LOW + evidenceGap. **v1 dims preserved unchanged:** TLS enforcement (dim 3) + dedicated IP pool (dim 5) + suppression list (dim 6 ZDE — count + reason only). **v2 promoter pattern**: sync v1 classifiers unchanged; async promoters walk collected findings post-classification. **R-HIGH-2 fold**: brittle `inTestMode = !!opts._client` coupling replaced with explicit `_skipV2Promotion` master switch + 3 orthogonal kill-switches. **First plugin in EE to depend on node:dns/promises** for live DNS cross-reference. **8 same-session v2 reviewer folds** (1 CRITICAL + 3 HIGH + 2 MEDIUM + 2 LOW); 6 queued in Pick-up Block. **Real-DNS smoke validation END-TO-END** against production resolvers (`_dmarc.nsasoft.us` parsed correctly: `p=reject, sp=reject, pct=100`; forward-compat `fo=1` tag preserved). Empty-account SESv2 enumeration baseline succeeded end-to-end against <operator-test-account>. **v1 base (preserved):** First plugin in 1190-1199 ID range. Closes the next-highest-priority gap from `tasks/things-to-check.md` AWS SOC 2 audit-canonical compliance checklist after Redis closed in 0.4.6. **6 audit dimensions:** **DKIM enablement + signing status** (CC6.1 / Privacy — HIGH on `SigningEnabled=false`; transient PENDING/TEMPORARY_FAILURE/NOT_STARTED INFO + walkthroughRequired; FAILED MEDIUM on DNS drift; unknown enum LOW + evidenceGap per conservative-classifier-principle) + **custom MailFrom domain alignment** (Privacy substrate — INFO + walkthroughRequired on default amazonses.com / PASS on custom + Status=SUCCESS) + **configuration set TLS enforcement** (C1.1 — REQUIRE PASS / OPTIONAL HIGH SMTP-downgrade-attack window / non-string-but-truthy distinct LOW with `tlsPolicyType` evidence per R-MEDIUM-7 fold) + **identity sending authorization policy permissive principals** (CC6.6 — multi-class wildcard detector covering bare `"*"` / `{AWS:"*"}` / `{Service:"*"}` / `{Federated:"*"}` / `{CanonicalUser:"*"}` / array-form `[*]` per R-HIGH-4 fold + distinct HIGH `ses-sending-auth-notprincipal-allow` per R-CRITICAL-1 fold catching NotPrincipal+Allow wildcard-EQUIVALENT class + LOW + evidenceGap `ses-sending-auth-malformed-statement` per R-HIGH-2 fold) + **dedicated IP pool sending posture** (CC7.1 substrate, account-level — INFO + walkthroughRequired on configured pools / INFO on shared-pool default) + **suppression list state** (CC7.1 deliverability substrate — **ZDE invariant: NEVER reads suppressed-destination email addresses**; count + reason only; verified at run() envelope boundary via sentinel-string assertion per R-LOW-8 fold). Dual API surface discipline: v1 uses SESv2 only (canonical modern API); `@aws-sdk/client-ses` declared in optionalDependencies for v2+ cross-API parity. **11 same-session reviewer folds** — ties single-cycle reviewer-fold record. **CRITICAL-1 closure**: NotPrincipal+Allow false-CLEAN class (matches plugins 1070 + 1150 discipline). **HIGH-4 closure**: `_isWildcardPrincipal` walks every Principal class value (pre-fold only `principal.AWS` inspected, leaking `{Service:"*"}` + `{Federated:"*"}` as silent CLEAN). **No real-AWS smoke against violation-tier fixtures** — operator's internal test infrastructure has NO SES paired fixtures yet (full-stack fixtures deferred to v2 alongside DKIM CNAME DNS resolution + DMARC TXT record parsing); empty-account smoke baseline against <operator-test-account> DID succeed end-to-end. | CC6.1 / CC6.6 / C1.1 / CC7.1 (substrate) / Privacy (substrate) |
185
+ | 1140 | AWS RDS Auditor (v3 — extended in EE 0.4.8) | Enterprise | **10 SOC 2 substrate-evidence dimensions** (v1=3 + v2=4 + v3=3). **v1+v2 (preserved):** Multi-AZ (A1.2) + storage encryption at rest with KMS-key custody classification + **kms:DescribeKey cross-reference promotes UNVERIFIABLE `:key/UUID` ARN shapes to deterministic PASS/MEDIUM** + parameter-group SSL enforcement (postgres rds.force_ssl + mysql require_secure_transport) + BackupRetentionPeriod (7-day baseline) + PubliclyAccessible + IAMDatabaseAuthenticationEnabled + snapshot encryption. **v3 NEW (database audit-logging, EE 0.4.8, v3):dim 8 pgAudit enabled** (postgres-only — `DescribeDBParameters → pgaudit.log` non-empty AND `shared_preload_libraries` contains `pgaudit` token per reviewer fold **false-PASS closure** — Postgres silently ignores the GUC when SPL omits pgaudit; new MEDIUM `rds-pgaudit-misconfigured` category; non-postgres engines = INFO + engine-not-applicable) + **dim 9 CloudWatch Logs exports** (`EnabledCloudwatchLogsExports` engine-dispatched: postgres essential=`postgresql`; mysql/mariadb essential=`error`; oracle essential=`audit`+`trace`; sqlserver essential=`error`; empty=HIGH / partial=MEDIUM / complete=PASS) + **dim 10 CloudWatch Logs retention** (`logs:DescribeLogGroups` enumeration on engine-dispatched prefix per reviewer fold **false-INFO closure**: `/aws/rds/instance/<id>/` for non-Aurora, `/aws/rds/cluster/<DBClusterIdentifier>/` for `aurora-*` engines — pre-fold hard-coded the instance path → 0 log groups on every Aurora node = false-INFO MEDIUM across the whole Aurora fleet; 30-day institutional baseline operator-tunable via `opts.auditLogRetentionPassMinDays` clamped 1..3653). **9 same-session v3 reviewer folds** (HIGH-1 Aurora cluster log-path; MEDIUM-2 pgAudit-SPL cross-check; MEDIUM-3/4/5 cwl-opt-out + retentionDistribution + transient-error distinct categories; LOW-8/9/10 + NIT-12). **Real-AWS smoke END-TO-END against `<operator-test-account>`** (in-place modification of rds-compliant-cluster; cost $0): ALL 3 v3 PASS-path classifiers validated + unmodified rds-violator-db validates HIGH path. **First 0.4.x extension cycle to validate BOTH PASS-path AND HIGH-path classifiers** against real AWS in the same smoke run. | A1.2 / CC6.1 / CC6.6 / C1.1 / CC7.2 / CC7.3 |
186
+ | 1150 | AWS SQS/SNS Auditor (NEW EE 0.4.4 v1; **EXTENDED EE 0.5.1 v2** — 5 → 7 dimensions: CloudWatch alarm coverage on SQS ApproximateAgeOfOldestMessage + SNS NumberOfNotificationsFailed; first plugin-1150 dim to cross an SDK boundary — SQS+SNS → CloudWatch) | Enterprise | First multi-service plugin in EE codebase. **7 dimensions total** (v1: 5; v2 EE 0.5.1 added dims 6 + 7). **v1 dims preserved:** SQS encryption at rest (SqsManagedSseEnabled OR KmsMasterKeyId; four-tier classification) + SQS transit-encryption policy (aws:SecureTransport Deny statement) + SNS topic encryption at rest + SNS topic-policy permissive-Principal (full NotAction-Allow + NotPrincipal-Allow + Resource-scope filtering per plugin 1070 + 1110 precedent) + SQS dead-letter queue presence (dual-mapped A1.2 + CC7.1). **v2 EE 0.5.1 NEW dims:dim 6 — SQS ApproximateAgeOfOldestMessage CloudWatch alarm coverage** (CC7.2 + A1.2 dual-mapped) — per-queue classifier `_classifySqsAgeAlarmCoverage` checks for at least one `AWS/SQS:ApproximateAgeOfOldestMessage` MetricAlarm with the queue's `QueueName` dimension AND **both** `ActionsEnabled=true` AND non-empty `AlarmActions[]`. Four outcomes: PASS `sqs-age-alarm-covered` / MEDIUM `sqs-age-alarm-missing` (silent backlog growth class) / LOW `sqs-age-alarm-actions-disabled` (matching alarm with all disabled OR empty AlarmActions — informational-only) / LOW + evidenceGap `sqs-age-alarm-coverage-unverifiable` (CW SDK unavailable / DescribeAlarms AccessDenied / queue name un-extractable / pagination truncated). **dim 7 — SNS NumberOfNotificationsFailed CloudWatch alarm coverage** (CC7.2 + A1.2 dual-mapped) — per-topic analogue with `AWS/SNS:NumberOfNotificationsFailed` metric + `TopicName` dimension; same four-tier severity ladder. **v2 single-fetch budget pattern** (mirrors plugin 1040): `_enumerateMetricAlarms` paginates `cloudwatch:DescribeAlarms` ONCE per scan; `_buildAlarmIndex` builds per-resource Maps (`sqsAgeByQueueName` + `snsFailureByTopicName`) for O(1) per-resource lookup. Pagination cap default 20 pages × 100 alarms = 2000 alarm ceiling, operator-tunable via `opts.cwAlarmPageCap`. **Soft-degrade contract** — CW SDK load failure routes per-resource classifier to LOW + evidenceGap rather than blocking SQS+SNS primary substrate audit. ** v2 fold (false-CLEAN closure)**: `actionable` requires BOTH `ActionsEnabled=true` AND non-empty `AlarmActions[]` array — CloudWatch fires NO operator paging when AlarmActions=[] even with ActionsEnabled=true; pre-fold an `{ActionsEnabled:true, AlarmActions:[]}` alarm passed as PASS-tier evidence on a structurally broken alarm. Discriminates "all disabled" vs "all empty actions" in remediation narrative. ** v2 fold**: soc2.json PASS-tier titlePatterns narrowed to anchor on `AWS/SQS:ApproximateAgeOfOldestMessage` / `AWS/SNS:NumberOfNotificationsFailed` clauses. **/ v2 folds**: defensive shape guard + multi-alarm collision tests + FIFO end-to-end + corrupted-shape defensive tests. **7 same-session v2 reviewer folds** (1 CRITICAL + 1 HIGH + 2 MEDIUM + 1 LOW + 1 NIT; 6 folded same-session, 1 NIT deferred). **No new SDK dependencies** — `@aws-sdk/client-cloudwatch` already declared in optionalDependencies since EE 0.4.0 (used by plugin 1040). **23 soc2.json titlePattern entries total** (11 v1 + 12 v2: 8 CC7.2 + 4 A1.2 dual-mapped). **Synthetic-mock validation only** this cycle for v2 — real-AWS smoke deferred (no SQS/SNS paired fixtures yet in operator's internal test infrastructure; ship-without per documented gap, EE 0.5.0 SES precedent). Closes the **"messaging monitoring" SOC 2 dimension** per `tasks/things-to-check.md` §4 institutional checklist: *"Track SQS ApproximateAgeOfOldestMessage and SNS delivery failure metrics inside CloudWatch to prove operational monitoring."* | C1.1 / CC6.6 / A1.2 / CC7.1 / CC7.2 |
187
+ | 1160 | AWS VPC Endpoints / PrivateLink Auditor (**NEW EE 0.6.0** — first new plugin since EE 0.4.7; first plugin to audit the PrivateLink isolation boundary; plugin count 20 → 21) | Enterprise | Audits AWS VPC endpoints (Interface + Gateway flavors) against **4 SOC 2 substrate-evidence dimensions** — VPC endpoints govern VPC-to-managed-service traffic without public-internet traversal (PrivateLink primitive). **Complements plugin 1170 SG perimeter** (1170 = layer-4 ingress; 1160 = service-layer perimeter). **Dim 1 — Endpoint policy permissive principals** (CC6.6 segmentation; wildcard-Principal classifier mirroring plugin 1150 SNS topic-policy discipline; NotPrincipal-Allow + Action-sensitivity filter via `_VPCE_SENSITIVE_ACTIONS` frozen Set; unconditional wildcard on sensitive action = CRITICAL — PrivateLink isolation BROKEN at policy layer; WITH Condition = HIGH walkthroughRequired). **Dim 2 — PrivateDNS enabled** (CC6.6; Interface + PrivateDnsEnabled=false = MEDIUM silent-bypass class — clients still resolve service-public hostname → traffic over public internet; Gateway = INFO not-applicable). **Dim 3 — Endpoint state** (A1.2 + CC7.2; `available` = PASS / `failed` = HIGH silent-failure / transient = INFO / unknown enum = LOW + evidenceGap). **Dim 4 — Endpoint type substrate disclosure** (Privacy + CC6.6; INFO substrate evidence per VPC). **2 same-session reviewer folds** ( unknown-type fail-safe defaults to Interface — safer audit path; R-NIT Effect case-insensitivity regression pin). **No new SDK deps** — `@aws-sdk/client-ec2` already declared since EE 0.4.5 (used by plugin 1170 + plugin 1180 v2). 7 new soc2.json titlePattern entries (5 CC6.6 + 2 CC7.2/A1.2 dual-mapped). 57 plugin tests + 2 reviewer-fold pins (59 total). Synthetic-mock validation only — no VPC endpoint paired fixtures yet in operator's internal test infrastructure. | CC6.6 / A1.2 / CC7.2 / Privacy (substrate) |
188
+ | 1170 | AWS EC2 SG Perimeter Auditor (v3.1 — extended in EE 0.6.7 with `_buildSgReferenceGraph` edge-dedup; v3 EE 0.6.6 SG→SG transitive chain reachability; v2 EE 0.4.6 RESTRICTED_PORTS 23-port baseline; v1 EE 0.4.5 base) | Enterprise | Orthogonal evidence to plugin 1023 zero-trust-checker (1023 reads OBSERVED open ports; 1170 reads DECLARED SG policy via DescribeSecurityGroups). **v3 dimensions: 6 v2 dims + 1 NEW v3 transitive-reachability dim.v3 EE 0.6.6 SG→SG transitive chain reachability** — `_buildSgReferenceGraph` builds nodes + directed edges per UserIdGroupPairs reference (cross-VPC edges flagged at edge-build time). `_findPubliclyReachableSgs` identifies SGs with 0.0.0.0/0 or ::/0 ingress as BFS roots. `_walkTransitiveReachability` BFS-walks the graph with cycle defense (per-traversal `visited` Set cloned at each branch), depth cap (default 5, max 20 — operator-tunable via `transitiveChainDepthCap`), per-target chain cap (default 10, max 100 — operator-tunable via `transitiveChainsPerTargetCap`). `_classifyTransitiveReachability` emits per-target findings: **2-hop = HIGH** (direct from public root, one indirection) / **3+ hop = CRITICAL** (operator-blindness principle — deeper chains less likely to be noticed). Cross-VPC edges skipped (out-of-scope for v3 v1 — cross-VPC peering / Transit Gateway is a separate audit surface); surfaced as INFO trailer. **v3 v1 simplifications**: per-hop port-flow tracked but NOT intersected (`walkthroughRequired=true` on every transitive finding — operator walkthrough verifies port-flow alignment across the chain); cross-VPC out of scope. **v3 reviewer fold (EE 0.6.6)**: BFS short-circuits enqueue past per-target cap (closes path-enumeration explosion on hub-and-spoke topologies — pre-fold the BFS marked the target truncated but kept cloning `path` and `visited` Sets and walking past the cap, causing O(paths × depth) heap usage on 200+ SG accounts with fan-out ≥10). **v3 reviewer fold**: depth-cap-hit surfaced separately from per-target-cap (closes silent-deep-truncation false-CLEAN class — pre-fold a graph deeper than `transitiveChainDepthCap` silently truncated without operator-visible signal). New operator opts: `skipTransitiveReachability` / `transitiveChainDepthCap` / `transitiveChainsPerTargetCap` / `transitiveChainSamplesPerFindingCap`. **v3.1 EE 0.6.7 closes the edge-dedup R2-deferred item**: `_buildSgReferenceGraph` now dedupes edges by `(sourceGroupId, targetGroupId)` with `ports` aggregated as array of `{protocol, fromPort, toPort}`. Pre-fold a real-world ALB-fronting-app SG with 3 ingress perms on different ports (80/443/8080) referencing the same source SG emitted 3 distinct edges A→B; BFS treated each as separate chain, inflating `chainCount` 2-5× and exhausting per-target chain caps on noise. Post-fold the BFS sees exactly 1 chain per distinct (source, target) pair. `isCrossVpc` AND-aggregation per the conservative-classifier principle (any same-VPC pair → merged edge same-VPC → walked rather than silently skipped). Classifier port-render accepts both v3.1 array shape and v3 single-object shape (back-compat preserved). **v3.1 review fold**: arrival-order independence locked with 2 regression fixtures + JSDoc tightening. **v3.1 review fold**: partial-render contract on malformed port specs locked with 2 fixtures. **v3.1 review fold**: `_portKeys` scratch lifetime documented (MUST NOT escape). 3 new soc2.json mappings under CC6.6 (transitive-public HIGH `Security Group... shortest = 2 hops` + transitive-public CRITICAL `... shortest = 3+ hops` + INFO truncation trailer `SG→SG transitive reachability walk truncated:`). **v2 EE 0.4.6 preserved**: 6 dimensions — IPv4 0.0.0.0/0 ingress to **RESTRICTED_PORTS (v2: 23 ports per CIS AWS Foundations v3.0)** — SSH/RDP/MS SQL/MySQL/Postgres/Redshift/Redis/Memcached/MongoDB/Elasticsearch/CouchDB/Docker/Kubelet/K8s-API/etcd/Kibana/InfluxDB/Kafka/Consul/ZooKeeper/Vault CRITICAL + IPv6 ::/0 sibling CRITICAL + all-protocol (-1) wildcard CRITICAL + public ingress to non-restricted ports INFO + egress 0.0.0.0/0 INFO + orphan SG (no attached ENI) LOW governance. **v2: `opts.additionalRestrictedPorts` operator-config knob** + **per-SG cardinality cap with rollup trailer** (defends against finding-size DoS on 1000+ SG accounts) + **system-managed-SG name-prefix exclusion list** (ElasticMapReduce- / eks-cluster-sg- / AWSServiceRole / awseb- prefixes excluded from orphan-detection). UserIdGroupPairs rules surfaced as INFO + evidenceGap at v2; **v3 (EE 0.6.6) now closes transitive SG→SG chain analysis** | CC6.6 / CC6.2 |
189
+ | 1180 | AWS ElastiCache Redis Auditor (v2 — extended in EE 0.4.9) | Enterprise | First plugin in 1170-1180 ID range. **6 SOC 2 substrate-evidence dimensions** (v1 unchanged in count; v2 grew dims 2 + 6 in scope). **v1 dims preserved:** transit encryption (TransitEncryptionEnabled wraps RESP in TLS; HIGH on disabled) + Redis AUTH/IAM-auth user groups (PASS on UserGroupIds; MEDIUM no-authentication) + Multi-AZ deployment (HIGH disabled / INFO standalone-not-applicable / INFO+evidenceGap on transient enabling/disabling states) + SnapshotRetentionLimit cadence (HIGH=0 / MEDIUM 1-6 / PASS ≥7; operator-tunable `opts.snapshotRetentionPassMinDays`). Dual API enumeration (DescribeReplicationGroups + DescribeCacheClusters) with inter-API dedup. **v2 GROWN dims (EE 0.4.9, v2):dim 2 at-rest encryption + KMS key custody** — original four-tier ladder (HIGH disabled → MEDIUM AWS-owned-default → MEDIUM `alias/aws/elasticache` → PASS customer-managed CMK + LOW+evidenceGap on `:key/UUID` per conservative-classifier-principle) **PLUS v2 kms:DescribeKey cross-reference promotion** (mirrors plugin 1140 v2): UNVERIFIABLE `:key/UUID` ARN shapes promoted via KeyMetadata.KeyManager to deterministic PASS `elasticache-at-rest-customer-managed-kms-promoted` (CUSTOMER) / MEDIUM `elasticache-at-rest-aws-managed-kms-promoted` (AWS); conservative on AccessDenied/NotFound/unknown KeyManager. **dim 6 subnet routing** — v1 INFO substrate (`elasticache-subnet-group-substrate`) plus **v2 ec2:DescribeRouteTables verifier** that walks the cache subnet group's subnets via elasticache:DescribeCacheSubnetGroups + filtered ec2:DescribeRouteTables, classifying each subnet on Internet Gateway route presence via /^igw-[a-f0-9]+$/i (correctly excludes egress-only eigw-): HIGH `elasticache-subnet-public-route-detected` (with per-subnet `igwDestinationsBySubnet` evidence per review fold) / PASS `elasticache-subnet-private-verified` (all subnets verified IGW-free) / LOW + evidenceGap `elasticache-subnet-main-rt-inheritance` per a review fold false-NEGATIVE closure (default-VPC main-RT typically routes `0.0.0.0/0 → igw-*`) / LOW + evidenceGap `elasticache-subnet-verification-unverifiable` on AccessDenied. **Cross-plugin sister of plugin 1170 SG perimeter** (layer-3 subnet→IGW vs layer-4 SG ingress policy). **7 same-session v2 reviewer folds** (HIGH-1 IGW destination evidence; MEDIUM-2 main-RT-inheritance false-NEGATIVE closure; MEDIUM-3 cache-key naming; LOW-6/7/9/10/11 + NIT-12). **Per-resource caching** prevents N×M API explosion (kmsKeyManagerCache + subnetGroupCache + subnetSetRoutingCache). **No new SDK deps** — @aws-sdk/client-kms + @aws-sdk/client-ec2 reused from EE 0.4.5. **Real-AWS smoke END-TO-END against <operator-test-account>**: review fold escalation demonstrably firing in production (`redis-leaky-cache` → dim 6 LOW main-RT-inheritance). | CC6.1 / CC6.2 / CC6.6 / A1.2 / C1.1 |
190
+ | 1200 | AWS Inspector2 / GuardDuty Enablement Auditor (NEW EE 0.6.1, EXTENDED EE 0.6.2 v2 multi-region + FindingPublishingFrequency + Inspector2 baseline expansion, EXTENDED EE 0.6.3 v3 alerting-destination dim closes substrate-without-sink false-PASS class, EXTENDED EE 0.6.4 v4 EventBridge target verification + multi-failedAccount + trigger uniformity, EXTENDED EE 0.6.5 v5 dead-target companion-LOW + sentinel observability + R-NIT named-constants, **EXTENDED EE 0.6.6 v6** — dead-target probe warm-up (IAM role + EventBridge API destination + CloudWatch Logs); plugin count UNCHANGED at 22 — existing plugin grew ~870 → ~1400 → ~2100 → ~2400 → ~2800 → ~3000 lines) | Enterprise | **v6 EE 0.6.6 dead-target probe warm-up** (closes the 0.6.5 R2-deferred long tail of unverifiable ARN shapes): three new branches in `_probeTargetLiveness` — **IAM role** (`iam:GetRole` on path-stripped role NAME extracted from `arn:aws:iam::ACCOUNT:role/[path/]NAME`; new SDK dep `@aws-sdk/client-iam`) + **EventBridge API destination** (`events:DescribeApiDestination` reuses existing `_EventBridgeSdk`) + **CloudWatch Logs log group** (`logs:DescribeLogGroups` with `logGroupNamePrefix` filter + **exact-name disambiguation guard** `groups.some((g) => g.logGroupName === logGroupName)` so prefix-match siblings don't false-LIVE; new SDK dep `@aws-sdk/client-cloudwatch-logs`). Companion-LOW emission contract unchanged (existing CC7.1 titlePattern is target-type-agnostic). **5 v6 R1 reviewer folds** (0 — clean review pass; 1 + 2 + 2 ): (plugin 1170 v3) BFS short-circuits enqueue past per-target cap + **IAM `NoSuchEntityException` / `NoSuchEntity` lifted into `_DEAD_TARGET_NOTFOUND_ERROR_NAMES` Set** (pre-fold the bare disjunction `err.name === "NoSuchEntityException"` at the IAM catch site bypassed the Set AND silently disabled `_retryOnNotFound` for IAM — the canonical worst-case for AWS eventual consistency with IAM lag 10-30s documented; **9th cumulative recurrence** of the the emit-literal/set-drift class class across the EE codebase; post-fold bare disjunction collapsed to `_isDeadTargetNotFoundError(err)` and eventual-consistency retry restored for IAM) + **IAM partition-routing contract documented** at `_loadIamSdk` (`iam:GetRole` is a global API resolving per-partition — orchestrators wiring `opts._iamClient` must construct a single global IAM client per-partition NOT per-region; passing a commercial region in GovCloud / aws-cn / ISO flips the partition and routes to a wrong endpoint) + **(plugin 1200 v6) API destination ARN regex future-proofed** (trailing `/` made optional in `:api-destination\/([^/]+)` so future AWS ARN shapes without UUID suffix don't false-malformed). **v6.1 EE 0.6.7 closes the CloudWatch Logs probe retry-on-empty parity R2-deferred item**: `_retryOnNotFound` accepts an optional retry-on-result predicate; CWL Logs call site passes a predicate that fires retry when the response carries no exact-name match (covers both empty and prefix-only-sibling responses). **Restructured to two-phase to cap total network calls at 2 on compound paths** — Phase 1 = initial call + thrown-NotFound retry; Phase 2 = result-based retry; phases are MUTUALLY EXCLUSIVE (single retry total). A nested-try design would have layered both retries on compound paths (first-call empty → retry → second-call throws RNF → retry again), producing 3 network calls. The per-call-site outer catch routes a second-call thrown error (NotFound → DEAD; AccessDenied → UNVERIFIABLE). Existing call sites (Lambda / SNS / SQS / IAM / EventBridge API destination) pass only two args; the default `retryOnResultPredicate = null` cleanly skips Phase 2. **v6.1 review fold**: compound-path coverage locked with 2 tests — transient empty → second-call AccessDenied → UNVERIFIABLE / transient empty → second-call thrown RNF → DEAD; both verify total network calls = 2 (drove the two-phase restructure decision). No new soc2.json mappings (companion-LOW pattern target-type-agnostic). v6 tests: +5 (2 IAM retry-regression: transient-NoSuchEntity-retry-succeeds + lowercase-NoSuchEntity-retry-then-DEAD; reviewer-fold regression pins also include 3 plugin 1170 v3 fixtures: hub-and-spoke per-target-cap + depthCapHit-true + depthCapHit-false). **v5 EE 0.6.5 v4-reviewer-cleanup cycle** (closes 4 R2-deferred items from): **Dead-target companion-LOW** — closes the EE 0.6.4 documented limitation. Per-target liveness probes for Lambda (`lambda:GetFunction` on full qualified ARN — alias/version correctness verified server-side) + SNS (`sns:GetTopicAttributes`) + SQS (`sqs:GetQueueUrl` + `GetQueueAttributes` — partition-aware via SDK URL resolution; works on aws-cn / aws-us-gov / aws-iso). New `_probeTargetLiveness` helper with parallel probes via Promise.all + per-target timeout (default 2s; operator-tunable via `deadTargetProbeTimeoutMs`). One-retry on NotFound with 750ms backoff (eventual-consistency defense). New MEDIUM verdict `*-alerting-destination-dead-targets` emitted as companion alongside PASS when at least one Target.Arn points to deleted resource. `deadTargetArnsTotal` + `deadTargetArnsTruncated` for JSON-consumer visibility on 11+ case. IAM role + API destination + CloudWatch Logs target probes deferred to 0.6.6 (3-4 more IAM grants). New operator opt `skipTargetLivenessProbe: true`. **Sentinel observability** — rule shape extended with `targetVerificationReason` (AccessDenied / SdkUnavailable / BeyondCap / SkippedByOpts) stable enum; classifier surfaces `targetVerificationReasonBreakdown` in unverifiable verdict details. **R-NIT named-constants** — `SH_HUB_NOT_ENABLED_ERROR_NAMES` frozen Set replaces 2 bare-string sites in SecurityHub helpers per the emit-literal/set-drift class. **Cross-plugin sessionToken sweep (catalog-wide)** — 18 EE AWS plugins (1020-1200) all thread `sessionToken` through their AWS-SDK credentials block. Closes AssumeRole-style auditor credential gap — auditors using `aws sts assume-role` (canonical cross-account audit pattern) had all auto-loaded clients fail signing pre-fold. **5 v5 R1 reviewer folds** (0 — clean review pass): case-insensitive NotFound matching (defends against future AWS SDK case changes per the AWS string-case normalisation discipline 15× recurrent class) + one-retry on NotFound (eventual-consistency defense; freshly-created resources transiently return NotFound for ~30s) + Lambda probe passes FULL ARN to GetFunction.FunctionName (alias `PROD` pointing to deleted version surfaces as DEAD instead of false-LIVE) + (Explore) parallel probes via Promise.all + per-target timeout + SQS partition-aware via `GetQueueUrl` (pre-fold synthesized `amazonaws.com` URL would have crashed on aws-cn / aws-us-gov / aws-iso partitions) + cap-constant lift to module-level + truncation fields + R-NIT JSDoc accuracy. **R2 reviewer-deferred** (queued for 0.6.6): IAM role + API destination + CloudWatch Logs target liveness probes. 1 new soc2.json mapping rule (CC7.1 companion-LOW dead-target). New SDK deps `@aws-sdk/client-lambda` + `@aws-sdk/client-sns` + `@aws-sdk/client-sqs` (all already in optionalDependencies from prior cycles). v5 tests: +48 (1 R-NIT + 8 sentinel + 20 sessionToken-sweep + 15 dead-target base + 4 -fold regression pins). **v4 EE 0.6.4 reviewer-cleanup cycle** (closes 3 of 4 R2-deferred items from): **EventBridge target verification** — new `_listEventBridgeRuleTargets` helper with defensive NextToken pagination (hard cap 500); per-rule target verification via `events:ListTargetsByRule` (cap default 10 via `opts.targetVerificationRuleCap`; opt-out via `opts.skipEventBridgeTargetVerification`); new MEDIUM verdict `*-alerting-destination-targetless` for sink-less rules (zero Targets — substrate-without-sink at the rule level). **multi-failedAccount surface** — Inspector2 helper return-shape `{accountStatus, accessDenied, failedAccounts: array}` (renamed plural; capped at AWS-documented 100); caller emits one LOW per failed account with per-region emission cap 10 + rollup LOW per region. **trigger uniformity** — GuardDuty alerting-destination trigger gates on `detector.Status === ENABLED` (matches Inspector2 enabled-only semantic). **5 v4 R1 reviewer folds** (0 — clean review pass): cap-skew classifier branch (LOW UNVERIFIABLE not MEDIUM TARGETLESS when cap-exceeded rules could be the actual sink per the conservative-classifier principle) + consolidated `_listEventBridgeRuleTargets` pagination + JSDoc clarity + multi-failedAccount per-region emission cap (10 + rollup LOW) + boundary tests + dead-target documented-limitation note (per-target liveness probes deferred to 0.6.5 companion-LOW; ~6 new IAM grants). **R2 reviewer-deferred** (queued for 0.6.5): sessionToken cross-plugin sweep (18 plugins) + companion-LOW for dead-target ARNs + `targetCount: null` sentinel observability + R-NIT named-constants for InvalidAccessException / ResourceNotFoundException. 1 new soc2.json mapping rule (CC7.1 MEDIUM TARGETLESS). v4 tests: +29 (3 + 6 + 14 base + 6 R1-fold regression pins). **v3 EE 0.6.3 alerting-destination dim (item c)** — closes the substrate-without-sink false-PASS class. Verifies at least one of EventBridge rule (source=`aws.guardduty`/`aws.inspector2`; `_eventBridgeSourceMatches` recognizes string + `{prefix}` + `{wildcard}` content-filter forms case-insensitively, regex-meta escape in wildcard glob defends against operator IaC) AND/OR SecurityHub product subscription (`_shArnMatchesProduct` boundary-anchored helper; constants `/aws/guardduty` + `/aws/inspector2` strict — does NOT match deprecated Inspector Classic). Verdict tiers per service per region: PASS `*-alerting-destination-present` (EB rule present) / MEDIUM `*-alerting-destination-sh-only` (review fold — SH aggregates but doesn't guarantee proactive paging; auditor walkthrough to confirm `aws.securityhub` EventBridge downstream rule) / HIGH `*-alerting-destination-missing` (no path; substrate-without-sink class) / LOW `*-alerting-destination-unverifiable` (AccessDenied / SDK unavailable; conservative classifier). New SDK deps `@aws-sdk/client-eventbridge` + `@aws-sdk/client-securityhub` (optionalDependencies). Operator opt: `skipAlertingDestination: true`. Soft-degrade on auto-load failure → fall back to LOW UNVERIFIABLE. **v3 review fold** — `_getInspector2AccountStatus` returns `{accountStatus, accessDenied, failedAccount}` distinguishing true AccessDenied from empty-body / SDK-unavailable (was `null | <obj>` pre-fold; caller emitted false `_CAT_INS_ACCESSDENIED` LOW on empty body). **v3 item (d) fold** — surfaces AWS-published `failedAccounts[].errorCode + errorMessage` via new `_CAT_INS_FAILED_ACCOUNT` LOW. **v3 R1 reviewer folds applied** (4 total; 1 + 2 + 1 ): SH product ARN substring collision closure (`/aws/inspector` would have matched BOTH Inspector Classic deprecated-2024 AND Inspector2 — false-PASS for stale Classic subscriptions emitting zero findings; boundary-anchored helper + strict `/aws/inspector2` constant) + SH-only PASS narrative split (PASS requires EB rule; SH-only → MEDIUM) + EventBridge content-filter grammar (prefix + wildcard matchers) + source case normalization. **R2 reviewer-deferred** (queued for 0.6.4): EB target verification (events:ListTargetsByRule + IAM grant) + asymmetric trigger uniformity + multi-failedAccount surface + sessionToken support cross-plugin sweep. 5 new soc2.json titlePattern entries (4 CC7.1 + 1 CC7.2 PASS) all anchored to actual emission strings per `[[soc2_titlepattern_anchor_drift]]`. v3 tests: +61 (+8 suites) — 5 + 5 item-(d) + 30 item-(c) base + 21 R1-fold regression pins. **v2 EE 0.6.2 dims preserved** (4 dims; v2 (a) multi-region enumeration via ec2:DescribeRegions + (b) FindingPublishingFrequency check + (e) Inspector2 baseline expansion +lambdaCode +codeRepository per Inspector2 GA 2024+; operator opts `regions[]` / `skipMultiRegion` / `regionListCap` / `gdFrequencyPassFrequency`; closes FedRAMP / StateRAMP / IL5+ false-PASS class for GovCloud + ISO regions via 4-part region regex fold). **v1 EE 0.6.1 base** — 4 active dims (dim 5 org-scope deferred to 0.6.4): Dim 1 GuardDuty Detector enablement per region (CC7.1 — HIGH `gd-not-enabled`) + Dim 2 GuardDuty protection-feature coverage (CC7.1 institutional baseline) + Dim 3 Inspector2 enablement (CC7.1 + CC7.2 — DISABLED/SUSPENDED = HIGH) + Dim 4 Inspector2 scan-target coverage (CC7.1 zero / CC7.2 partial). Plugin 1200 audits AWS GuardDuty + AWS Inspector2 enablement state across **all opted-in regions** — **foundation-layer institutional evidence for CC7.1 detection procedures + CC7.2 monitoring** (an audit pack without managed-threat-detection evidence has no AWS-native anomaly-detection or CVE-detection stream). **v2 EE 0.6.2 GROWN scope** (closes 3 of 4 R2-deferred items from, v1): **(a) Multi-region enumeration** — `ec2:DescribeRegions` enumerates opted-in regions (AllRegions=false defensively); per-region GuardDuty + Inspector2 dispatch; per-region findings carry region tag. Operator opts: `regions: string[]` (filter to subset, validated + deduped + capped 64 default), `skipMultiRegion: true` (cost-sensitive opt-out), `regionListCap` (1..256 clamp). Soft-degrade: EC2 SDK load failure / DescribeRegions AccessDenied → fall back to `config.region` + distinct `_CAT_REGION_ENUM_ACCESSDENIED` LOW finding. Back-compat: legacy single-region opts (`_guardDutyClient` / `_inspector2Client` singular) still respected. **(b) GuardDuty FindingPublishingFrequency check** — CC7.1 detection-latency. `_classifyGuardDutyFrequency` 4 outcomes: PASS `gd-frequency-optimal` / LOW `gd-frequency-suboptimal` / LOW `gd-frequency-unverifiable` (null detector or unknown enum). Operator-tunable: `gdFrequencyPassFrequency` (FIFTEEN_MINUTES / ONE_HOUR / SIX_HOURS; default FIFTEEN_MINUTES). **Ordering-based comparison** via `_GD_FREQUENCY_RANK` map (review fold) — stricter actual = PASS even when operator tuned baseline upward. **(e) Inspector2 baseline expansion** — `lambdaCode` (Lambda code scanning) + `codeRepository` (Inspector2 GitHub/GitLab scanning, GA 2024+) added to `_INS_INSTITUTIONAL_BASELINE_RESOURCES` (was {ec2, ecr, lambda}; now {ec2, ecr, lambda, lambdaCode, codeRepository}). **v1 dims preserved (4 active dims; dim 5 org-scope deferred to 0.6.3):** Dim 1 GuardDuty Detector enablement per region (CC7.1 — HIGH `gd-not-enabled`) + Dim 2 GuardDuty protection-feature coverage (CC7.1 — institutional baseline S3_DATA_EVENTS / EKS_AUDIT_LOGS / EBS_MALWARE_PROTECTION / RDS_LOGIN_EVENTS / LAMBDA_NETWORK_LOGS / RUNTIME_MONITORING) + Dim 3 Inspector2 enablement (CC7.1 + CC7.2 — DISABLED/SUSPENDED = HIGH) + Dim 4 Inspector2 scan-target coverage (CC7.1 zero / CC7.2 partial). **4 same-session R1 v2 reviewer folds** (network-security + Explore in parallel; 0 clean review pass): **region regex GovCloud + ISO support** — pre-fold `^[a-z]{2,}-[a-z]+-[0-9]+$` silently dropped 4-part region IDs (`us-gov-east-1` / `us-iso-east-1` / `us-isob-east-1` / `us-isof-south-1`); operator passing `regions: ["us-gov-east-1"]` got silent skip + false-PASS — institutional-critical for FedRAMP / StateRAMP / IL5+ scope. Post-fold `^[a-z]{2,}(-[a-z]+){1,2}-[0-9]+$` admits 3- AND 4-part IDs. + **frequency ordering not equality** (described above). + **`_REGION_LIST_CAP` defensibility** — pre-fold hardcoded 32 silently truncated 4-part regions (AWS has ~40+ regions in 2026); post-fold default raised to 64 + operator-tunable + explicit truncation warning. + **EC2 client instrumentation** — operator-supplied `_ec2Client` now receives Thread-H AccessDenied counter + throttle-retry contract uniformly. **R2 reviewer-deferred** (queued in / 0.6.3): alerting-destination check (item c — needs `@aws-sdk/client-eventbridge` + `@aws-sdk/client-securityhub` integrations) + BatchGetAccountStatus contract verification (item d) + `_getInspector2AccountStatus` return-shape refactor + optional dim 5 org-scope. **6 R1 v1 folds (EE 0.6.1) preserved as regression pins**: soc2.json titlePattern misalignment closure (4 patterns) + AccessDenied distinct findings + legacy DataSources case normalization + SUSPENDED/DISABLED Detector Status guard + -3/4 dead-code drift closures. **No new SDK deps** — `@aws-sdk/client-guardduty` + `@aws-sdk/client-inspector2` + `@aws-sdk/client-ec2` already in optionalDependencies. 7 new soc2.json titlePattern entries from v1 still anchored. v2 tests: +27 (21 base + 6 R1-fold regression pins). Synthetic-mock validation only — no multi-region GuardDuty/Inspector2 paired fixtures yet in operator's internal test infrastructure. | CC7.1 / CC7.2 |
191
+ | 1190 | AWS SES Email Integrity Auditor (NEW EE 0.4.7; EXTENDED EE 0.5.0 v2; CONSOLIDATED EE 0.5.2 v2.1; **EXTENDED EE 0.5.3 v3** — Part A DKIM public-key fingerprint capture/pin + Part B in-band DMARC alignment classifier; 5 same-session reviewer folds incl. 1 false-CLEAN closure on truncated DKIM keys via new `_stripControlCharsNoTruncate` helper; v2.1 closed — 7 deferred reviewer-fold items closed + new MEDIUM `ses-dkim-dns-partial-with-transients` category + module-load-time disjointness IIFE + silent-loss-class closure on SES classic API quota exhaustion via `cause: "classic-sdk-quota-exhausted"`) | Enterprise | **v2 EE 0.5.0 GROWN dims:dim 1 DKIM** — original substrate **PLUS v2 DKIM CNAME DNS resolution promotion**: each `<token>._domainkey.<domain>` CNAME resolved via node:dns/promises + matched against `<token>.dkim.amazonses.com` (case-insensitive per RFC 1035 §2.3.3); four outcomes PASS `ses-dkim-dns-verified` / MEDIUM `ses-dkim-dns-partial` / **HIGH `ses-dkim-dns-missing` (false-CLEAN closure: SES Status=SUCCESS but DNS removed)** / LOW + evidenceGap `ses-dkim-dns-unverifiable`. **dim 2 MailFrom** — original substrate **PLUS v2 DMARC TXT record parser + MailFrom promotion**: RFC 7489 §6.4 tag-list parser + `_dmarc.<identityDomain>` TXT lookup; five outcomes PASS `ses-dmarc-policy-reject` / MEDIUM `ses-dmarc-policy-quarantine` / HIGH `ses-dmarc-policy-none` / HIGH `ses-dmarc-missing` / LOW + evidenceGap `ses-dmarc-unverifiable`. **review fold (false-CLEAN closure)**: `pct=0` on `p=reject`/`p=quarantine` functionally equivalent to `p=none`; now routes to HIGH `ses-dmarc-policy-none`. **review fold (subdomain-takeover false-NEGATIVE closure)**: `sp` subdomain-policy override now evaluated — `p=reject; sp=none` downgrades to HIGH with `dmarcSpWeakens` (subdomain phishing wide open while apex protected). **dim 4 sending-auth policies** — original IAM-policy classifier **PLUS v2 SES classic GetIdentityPolicies parity**: `_loadSesClassicSdk` restored; cross-API discrepancy emits HIGH `ses-classic-policy-discrepancy` (classic-only — canonical false-NEGATIVE class) / MEDIUM (`_canonicalSort` JSON deep-equal ignores whitespace + key-order drift) / INFO (v2-only benign). Conservative on classic SDK unavailable / AccessDenied → LOW + evidenceGap. **v1 dims preserved unchanged:** TLS enforcement (dim 3) + dedicated IP pool (dim 5) + suppression list (dim 6 ZDE — count + reason only). **v2 promoter pattern**: sync v1 classifiers unchanged; async promoters walk collected findings post-classification. **review fold**: brittle `inTestMode = !!opts._client` coupling replaced with explicit `_skipV2Promotion` master switch + 3 orthogonal kill-switches. **First plugin in EE to depend on node:dns/promises** for live DNS cross-reference. **8 same-session v2 reviewer folds** (1 CRITICAL + 3 HIGH + 2 MEDIUM + 2 LOW); 6 queued in Pick-up Block. **Real-DNS smoke validation END-TO-END** against production resolvers (`_dmarc.nsasoft.us` parsed correctly: `p=reject, sp=reject, pct=100`; forward-compat `fo=1` tag preserved). Empty-account SESv2 enumeration baseline succeeded end-to-end against <operator-test-account>. **v1 base (preserved):** First plugin in 1190-1199 ID range. Closes the next-highest-priority gap from `tasks/things-to-check.md` AWS SOC 2 audit-canonical compliance checklist after Redis closed in 0.4.6. **6 audit dimensions:DKIM enablement + signing status** (CC6.1 / Privacy — HIGH on `SigningEnabled=false`; transient PENDING/TEMPORARY_FAILURE/NOT_STARTED INFO + walkthroughRequired; FAILED MEDIUM on DNS drift; unknown enum LOW + evidenceGap per conservative-classifier-principle) + **custom MailFrom domain alignment** (Privacy substrate — INFO + walkthroughRequired on default amazonses.com / PASS on custom + Status=SUCCESS) + **configuration set TLS enforcement** (C1.1 — REQUIRE PASS / OPTIONAL HIGH SMTP-downgrade-attack window / non-string-but-truthy distinct LOW with `tlsPolicyType` evidence per review fold) + **identity sending authorization policy permissive principals** (CC6.6 — multi-class wildcard detector covering bare `"*"` / `{AWS:"*"}` / `{Service:"*"}` / `{Federated:"*"}` / `{CanonicalUser:"*"}` / array-form `[*]` per review fold + distinct HIGH `ses-sending-auth-notprincipal-allow` per review fold catching NotPrincipal+Allow wildcard-EQUIVALENT class + LOW + evidenceGap `ses-sending-auth-malformed-statement` per review fold) + **dedicated IP pool sending posture** (CC7.1 substrate, account-level — INFO + walkthroughRequired on configured pools / INFO on shared-pool default) + **suppression list state** (CC7.1 deliverability substrate — **ZDE invariant: NEVER reads suppressed-destination email addresses**; count + reason only; verified at run envelope boundary via sentinel-string assertion per review fold). Dual API surface discipline: v1 uses SESv2 only (canonical modern API); `@aws-sdk/client-ses` declared in optionalDependencies for v2+ cross-API parity. **11 same-session reviewer folds** — ties single-cycle reviewer-fold record. **CRITICAL-1 closure**: NotPrincipal+Allow false-CLEAN class (matches plugins 1070 + 1150 discipline). **HIGH-4 closure**: `_isWildcardPrincipal` walks every Principal class value (pre-fold only `principal.AWS` inspected, leaking `{Service:"*"}` + `{Federated:"*"}` as silent CLEAN). **No real-AWS smoke against violation-tier fixtures** — operator's internal test infrastructure has NO SES paired fixtures yet (full-stack fixtures deferred to v2 alongside DKIM CNAME DNS resolution + DMARC TXT record parsing); empty-account smoke baseline against <operator-test-account> DID succeed end-to-end. | CC6.1 / CC6.6 / C1.1 / CC7.1 (substrate) / Privacy (substrate) |
192
192
  | 1210 | AWS EC2 Instance Auditor (**NEW EE 0.13.1** — first new plugin since 1200; plugin count 24 → 25; the AWS producer for CIS-Hardened-Image detection + EC2 instance-level + EBS-encryption coverage) | Enterprise | Audits EC2 instances (orthogonal to plugin 1170 which audits the SG perimeter policy). **Multi-region** via ec2:DescribeRegions (single-region fallback emits an evidence-gap). Dimensions: **IMDSv1 enabled** (CC6.1 — MEDIUM when an IAM instance profile is attached / LOW without; **IMDSv2 hop-limit > 1** re-opens container credential theft) + **EBS volume unencrypted** (C1.1 + CIS 3.11 — HIGH; resolves every attached BlockDeviceMappings volume via DescribeVolumes) + **account default-EBS-encryption disabled** (C1.1 preventive — GetEbsEncryptionByDefault) + **public-IP exposure** incl. secondary-ENI/EIP + IPv6 GUA (CC6.6 substrate, INFO) + **instance-store (ephemeral) volume** evidence-gap. **DIM 4 — AMI inventory** → result.cisImageInventory (the producer feed that makes CIS-Hardened-Image detection LIVE on Safeguards 4.1/4.2/4.6; Azure 1022 + GCP 1021 feed the same contract). Conservative classifier: LOW + evidenceGap on indeterminate metadata; AccessDenied → INFO + evidenceGap (never silent-PASS); terminated/shutting-down instances skipped. Survived 3 review rounds / 5 adversarial skill lenses (network-security-audit + CIS + IAM-effective-permissions + soc2-evidence + cloud-plugin-false-negatives). `@aws-sdk/client-ec2` reused. | CC6.1 / C1.1 / CC6.6 |
193
193
  | 1220 | Azure Storage Account Data-Protection Auditor (**NEW EE 0.13.2** — Move C-2; **+2 dims EE 0.13.3** — Move C-2.1; plugin count 25 → 26; first dedicated Azure auditor beyond the multi-purpose 1022 scanner) | Enterprise | Audits the Azure Storage Account data-protection surface across **7 dims** — **orthogonal to plugin 1022** which owns the network-exposure dims (no double-emission; mirrors the AWS 1020 S3-scanner + 1120 S3-lifecycle two-plugin split). (1) **HTTPS-only transit** (`enableHttpsTrafficOnly` — HIGH on plaintext HTTP; CC6.7) + (2) **minimum TLS version** (< TLS1_2 → MEDIUM; CC6.7) + (3) **Shared Key authorization** (`allowSharedKeyAccess` — bypasses Azure AD identity; CC6.1; Azure field-default discipline: absent = ENABLED, never silent-PASS) + (4) **infrastructure (double) encryption** (`requireInfrastructureEncryption`; C1.1) + (5) **encryption key source incl. CMK reachability + rotation** (`encryption.keyVaultProperties` — keySource=Microsoft.Keyvault PASS only when the key is currently resolvable + auto-rotating; a disabled/revoked/version-pinned CMK degrades, not silent-PASS; C1.1) + (6) **blob recoverability** (soft-delete + versioning via the secondary `blobServices.getServiceProperties` path — A1.2; EE 0.13.3) + (7) **per-container anonymous public access** (account-toggle-aware via `blobContainers.list` — `publicAccess=Blob/Container` + allowBlobPublicAccess=true → HIGH effective exposure; C1.1; EE 0.13.3). Conservative classifier: indeterminate field / AccessDenied / secondary-path failure → evidence-gap (never silent-PASS); `for await` pagination. Single-subscription scope surfaced explicitly. Built + reviewed through the cloud-plugin-false-negatives lens. `@azure/arm-storage` + `@azure/identity`. | CC6.7 / CC6.1 / C1.1 / A1.2 |
194
194
  | 1221 | Azure NSG Perimeter Auditor (**NEW EE 0.14.0** — Move C-2.2; **UDP lane EE 0.14.1**; plugin count 26 → 27; the Azure analog of AWS plugin 1170) | Enterprise | A CC6.6 network-segmentation perimeter auditor for Azure Network Security Groups — **non-overlapping-by-depth with plugin 1022's flat per-rule NSG lint** (no double-emission of a verdict; mirrors the AWS 1023-observed / 1170-declared two-plugin precedent). Evaluates each NSG's inbound rules in **Azure priority order** (first match wins; DenyAllInbound default): (1) **all-protocol (`*`) public Allow** — every port reachable from the public internet + (2) **public-source (`*`/`0.0.0.0/0`/`Internet`) to a restricted TCP port** (SSH/RDP/MSSQL/MySQL/Postgres/Redis/Memcached/MongoDB/Elasticsearch/CouchDB/SMB/WinRM/Oracle/Docker/Kubelet) + (3) **`::/0` IPv6-wildcard to a restricted port** (the dimension 1022's flat lint misses) + **(2u/3u) public-source / `::/0` to a restricted UDP service** (DNS/TFTP/rpcbind/NTP/NetBIOS/SNMP/CLDAP/IKE/Syslog/IPMI/OpenVPN/MSSQL-Monitor/SSDP/IPsec-NAT-T/Memcached — closes the public-UDP false negative, **EE 0.14.1**) + (4) **public→non-restricted port** INFO substrate + (5) **PASS substrate** when no public restricted exposure. **Attachment-aware severity** via the read-only `nsg.subnets[]`/`networkInterfaces[]` back-references — attached → CRITICAL (effective exposure); orphaned → MEDIUM (latent). Per-transport effective priority/deny-override resolution + port-range expansion + `0.0.0.0/1` split-range coverage + service-tag/ASG-source normalization (VirtualNetwork/AzureLoadBalancer/ASG = not public). Conservative classifier: denied/indeterminate listAll → evidence-gap; one malformed NSG degrades per-resource (never aborts the scan); `for await` pagination; single-subscription scope explicit. Built + reviewed through the cloud-plugin-false-negatives lens (EE 0.14.0 SHIP-WITH-FOLDS 2 LOW; EE 0.14.1 UDP lane SHIP-WITH-FOLDS 2 MED + 1 LOW, all folded). `@azure/arm-network` + `@azure/identity`. | CC6.6 |