NSAuditor AI EE 0.3.6 Ships — Full SOC 2 IAM Shadow-Admin Evidence-Integrity Sweep
EE 0.3.6 closes federated trust, NotAction privesc, and AccessDenied false-clean classes — and ships per-hop statement-index pointers for SOC 2 auditors.
LAS VEGAS, NV — May 11, 2026 — Nsasoft US LLC today announced the immediate availability of NSAuditor AI Enterprise Edition (EE) v0.3.6. The release ships through npm under restricted-access distribution and pairs with Community Edition v0.1.38 on npm. Auditors evaluating SOC 2 evidence MUST verify the CE version recorded in evidence artifacts is ≥ 0.1.37 (the security-fix floor). EE 0.3.5 and CE 0.1.37 are explicitly deprecated on npm with pointers to current versions.
EE 0.3.6 consolidates five distinct SOC 2 CC6.1 evidence-quality improvements shipped on 2026-05-10 across a single development sprint. Coverage matrix unchanged at 8 covered / 5 partial / 34 OOS — this release is entirely about evidence quality and auditor-actionable signals on existing controls.
1. Federated identity providers are no longer invisible to the BFS
EE 0.3.4 shipped institutional-grade transitive shadow-admin path detection. EE 0.3.5 added complete evidence-trail provenance. Both worked correctly — but both were AWS-IAM-principal-centric. _assumeRoleTrustsPrincipal only inspected principalSpec.AWS. The Federated: principal type was silently ignored.
The miss: SSO-via-SAML is the dominant assumption pattern in modern enterprises. ANY customer using Okta, Azure AD, Google Workspace, or GitHub Actions OIDC federation had an undetectable shadow-admin class. A role with Principal: { Federated: "arn:aws:iam::A:saml-provider/Okta" } is a real human-walkable edge from any user authenticated via the Okta IdP — but it never surfaced in shadow-admin paths.
EE 0.3.6 closes the gap. The new _detectFederatedTrustRoles(roles) helper emits per-role INFO-tier records under result.federatedTrustRoles[]:
{
"roleName": "OktaAdmins",
"roleArn": "arn:aws:iam::111111111111:role/OktaAdmins",
"severity": "info",
"category": "federated_trust",
"samlProviderArns": ["arn:aws:iam::111111111111:saml-provider/Okta"],
"hasUnconstrainedStatement": true,
"detail": "Role assumable via federated identity (at least one statement has NO Condition — unconstrained federated trust)..."
}
Records distinguish SAML providers from OIDC providers from well-known string IdPs (cognito-identity, Google, Amazon, Facebook). The crossAccount: true flag fires when the SAML/OIDC provider account ID differs from the role’s account ID — the canonical adversarial pattern (attacker creates IdP in their account, victim’s role trusts it). expectedProviderKinds tagging excludes ubiquitous intentional providers (GitHub Actions OIDC, Cognito) from the warning’s primary count while preserving the full inventory in evidence packs.
2. NotAction-encoded trust statements no longer evade detection
NotAction Allow statements are legitimate AWS IAM constructs. Allow + NotAction: ["iam:GetRole"] + Principal: AWS: <user-arn> grants every action EXCEPT iam:GetRole to that user — including sts:AssumeRole. Pre-0.3.6 four trust-evaluator helpers (_assumeRoleTrustsPrincipal, _detectWildcardTrustRoles, _detectFederatedTrustRoles, _assumeRoleTrustsService) each used raw actions.some(...) patterns that silently returned false on NotAction-encoded trust. An attacker writing such a statement evaded BFS detection entirely.
EE 0.3.6 refactors all four helpers to use the existing NotAction-aware _actionMatches(stmt, action) helper — which has been correct for years for action-level analysis but was never plumbed into the trust-evaluator path. Single unified semantic across the codebase. A BFS-level integration test pins that an attacker’s NotAction-encoded trust against a specific victim user now produces a shadow-admin path.
3. AccessDenied on permission-needed APIs surfaces structurally
A misconfigured auditor IAM role missing iam:GetPolicyVersion, ListAttachedRolePolicies, or any other read permission would produce a scan with an empty findings array on the denied API. The scan completed. The report said “no findings.” The auditor accepted the evidence. Worst possible SOC 2 Type-II audit outcome.
EE 0.3.6 ships an SDK-client instrumentation layer that captures every permission-class error (AccessDenied | AccessDeniedException | UnauthorizedOperation | AuthorizationError) at a single point. The result surfaces a frozen summary.scanCoverage.accessDeniedByApi map:
{
"scanCoverage": {
"accessDeniedByApi": {
"GetPolicyVersion": 14,
"ListAttachedRolePolicies": 7,
"ListGroupsForUser": 3
}
}
}
And a warnings[] entry: “Scan coverage is PARTIAL: 24 permission-denied error(s) across 3 AWS API(s). An empty findings array on these APIs is NOT equivalent to ‘no findings’ — the scan never got authoritative answers. Re-run with the AWS-managed IAMReadOnlyAccess policy attached to the auditor principal for complete SOC 2 evidence coverage.”
The implementation wraps the IAM SDK client’s send() method via Object.create(Object.getPrototypeOf(iam)) + Object.assign — preserving the AWS SDK v3 prototype chain (config, middlewareStack, destroy() remain accessible) — not via a {...iam} spread that would drop those properties. Zero existing catch sites needed changes.
4. Per-hop statement-index pointers for direct remediation
EE 0.3.5 emitted [via policy: <arn1>, <arn2>; inline: <name1>] aggregate suffixes — auditors knew WHICH policies contributed but not WHICH STATEMENT inside the policy granted the action enabling each hop. A 15-statement policy meant reading every statement to find the one to revoke. At scale, this became the dominant cost of IAM remediation.
EE 0.3.6 ships per-hop statement-index pointers in a new pathEvidenceByPath field:
{
"userName": "alice",
"shadowAdminPaths": ["alice → developers (group) → admin-role (role) [via policy: arn:aws:iam::123:policy/DevopsAdminGrant]"],
"pathEvidenceByPath": {
"alice → developers (group) → admin-role (role) [via policy: arn:aws:iam::123:policy/DevopsAdminGrant]": [
{ "policyArn": "arn:aws:iam::123:policy/AliceGroupMembership", "statementIndex": 0, "hop": 1 },
{ "policyArn": "arn:aws:iam::123:policy/DevopsAdminGrant", "statementIndex": 3, "hop": 2 }
]
}
}
The auditor’s remediation workflow goes from “open policy → read 15 statements → find one to revoke” to “open policy → jump to statement N.” For SOC 2 Type-II evidence at organizational scale, this is the single biggest auditor-workflow improvement of the release.
The gating contract is precise: pathEvidence is only emitted when BOTH statement index AND policy identifier are present. Bare-document policy fixtures (used heavily in unit-test paths) produce no pathEvidence — backward-compat preserved without test churn. ZDE-safe: only ARN strings, policy names, integer indexes, integer hops flow through. A sentinel test pins that policy body content never leaks through conclude().
5. Conditional-trust triage signal for legitimate SaaS-vendor patterns
A role with Condition: { StringEquals: { "sts:ExternalId": "datadog-tenant-abc" } } on its assumeRolePolicy is a Datadog cross-account integration — a legitimate, scoped, vendor-verified pattern. Pre-0.3.6 BFS treated this identically to an unconditional Principal: { AWS: "*" } wildcard trust. Same with AWS Marketplace seller roles, AWS Organizations management account roles, and every SaaS-vendor cross-account pattern. Auditors paid the triage cost on every one.
EE 0.3.6 ships a [conditional trust — verify] suffix in the path string AND a structured conditionalHopsByPath map per finding:
{
"shadowAdminPaths": [
"alice → developers (group) → datadog-monitoring-role (role) [via policy: arn:aws:iam::123:policy/DatadogIntegration; conditional trust — verify]"
],
"conditionalHopsByPath": {
"alice → developers (group) → datadog-monitoring-role (role) [via policy: arn:aws:iam::123:policy/DatadogIntegration; conditional trust — verify]": [2]
}
}
The “unconditional wins” semantic is conservative by design: if a role has ANY unconditional matching trust statement, the path is NOT flagged conditional (the trust is reachable without the auditor needing to verify any Condition). Only paths where EVERY contributing trust match was Condition-scoped get the triage signal.
Validation evidence
Test counts:
tests/aws_iam_auditor.test.mjs: 249/249 (+94 new since 0.3.5 baseline)- Targeted regression (IAM + compliance engine + S3/Azure/GCP plugins + coverage doc + SOC 2 renderer): 526/526
- Zero pre-existing tests modified — backward-compat preserved via boolean shims and gating contracts on every new field
Reviewer cycles:
- 5 same-session reviewer cycles, parallel general + network-security lens each round
- 36 reviewer folds total (0 ship-blocked, 0 deferred CRITICAL)
- 2 post-fold CRITICALs caught and folded in the C.1.1 cycle
Adversarial input handling:
- Statement index bounded (
MAX_STATEMENT_INDEX = 10_000) - Federated provider value length bounded (
MAX_FEDERATED_VALUE_LENGTH = 2048) - Anchored ARN regex rejects substring-match attacks
- Control-char strip + Unicode separator strip (U+2028, U+2029, ZWSP/ZWNJ/ZWJ/BOM)
Effect: Denystatements explicitly excluded from trust detection
Zero Data Exfiltration (ZDE) maintained: Sentinel tests pin that policy body content does NOT leak through conclude() for either pathEvidence or conditional-trust outputs. All new fields are identifiers (ARN strings, policy names) or numbers (statement indexes, hop counts) — no policy bodies, no Condition operator values, no Resource ARNs from inside policies.
Security advisory: CE 0.1.37 floor
EE 0.3.6 inherits the CE 0.1.37 security-fix floor from the 0.3.5 release window. Pre-0.1.37 CE silently bypassed the MCP auth check + license verification via the published bin shim. SOC 2 evidence generated from MCP-routed responses under pre-0.1.37 CE would fail audit. Auditors evaluating SOC 2 evidence MUST verify the CE version recorded in evidence artifacts is ≥ 0.1.37.
What an auditor receives
Per finding (when applicable):
- Principal chain string (
alice → developers (group) → admin-role (role)) [via policy: <arn1>, <arn2>; inline: <name1>; conditional trust — verify]suffixpartialProvenance: falseANDprovenanceComplete: truestrict flagspathEvidenceByPath: per-hop statement-index pointers for direct remediationconditionalHopsByPath: per-hop conditional-trust flags for triage prioritization
Per scan (top-level):
result.federatedTrustRoles[]: per-role IdP inventory with SAML/OIDC classification, cross-account flagging, expected-provider taggingresult.summary.scanCoverage.accessDeniedByApi: per-API permission-coverage mapresult.policyFetchErrors[]: per-ARN fetch-failure detailresult.warnings[]: human-readable triage signals (Provenance is PARTIAL, Scan coverage is PARTIAL, SCP context not evaluated, Federated identity trusts detected)
Availability
EE 0.3.6 ships through npm as @nsasoft/nsauditor-ai-ee@0.3.6 (restricted access — Pro/Enterprise license required). The package layers on top of the open-source nsauditor-ai CE engine; no fork, no parallel installation, no module-instance fragmentation.
npm install -g nsauditor-ai@0.1.38 @nsasoft/nsauditor-ai-ee@0.3.6
nsauditor-ai license install <KEY>
nsauditor-ai scan --host aws --plugins 030 --compliance soc2 --out evidence.json
Resources
- npm package:
@nsasoft/nsauditor-ai-ee@0.3.6(restricted; requires Pro/Enterprise license) - CE pairing:
nsauditor-ai@0.1.38(public; MIT; security-fix floor: ≥ 0.1.37) - Pricing & licensing: nsauditor.com/ai/pricing · nsauditor.com/ai/enterprise
Press & analyst contact
Nsasoft US LLC — press@nsasoft.us · nsasoft.us
For SOC 2 audit-team trials with custom IAM scenarios or federated-identity-heavy environments, contact enterprise@nsasoft.us. EE 0.3.6’s Federated/SAML/OIDC support specifically targets the Okta/Azure AD/Google Workspace federation patterns that previously required manual policy-by-policy auditor review.



