# AttackGraph AI comparison report

> **Synthetic configuration JSON.** Static analysis of declared facts. No configuration was deployed or executed, and no represented account was contacted. Amazon Bedrock is called only to explain results.

| Field | Value |
|---|---|
| Generated | 2026-10-16T10:30:54Z |
| Analysis ID | `56bc16da787997e8` |
| Engine | 0.1.0 |
| Security model | `attackgraph-rules-v1` |
| Schema | 1.0 |
| Baseline | `demo-baseline` · Baseline\: CI deploys with the app runtime role · file baseline\.json · sha256 `0b074dd0c9453890` · synthetic: true |
| Proposal | `demo-proposed` · Proposed\: PassRole widened to the deployment admin role · file proposed\.json · sha256 `123474de9e9eb0be` · synthetic: true |
| Coverage | complete |

## Result

**1 new high-risk finding in the proposal.**

- High-risk findings: baseline 0, proposal 1
- Added 1, removed 0, unchanged 0, inconclusive 0
- Severity is a demo rubric (reachable privileged role or readable protected object = High), not CVSS or an AWS rating.

## Coverage

- **Baseline: complete.** Rule A: direct S3 object read: 2 established, 2 blocked, 0 unresolved; Rule B: role use through a Lambda workload: 1 established, 2 blocked, 0 unresolved.
- **Proposal: complete.** Rule A: direct S3 object read: 2 established, 4 blocked, 0 unresolved; Rule B: role use through a Lambda workload: 2 established, 2 blocked, 0 unresolved.

- Candidates are evaluated for every subject that is reachable\, or possibly reachable\, from an entry principal\.
- Rule A evaluates S3 objects that are protected or named in an expected\-access check\, plus objects with a declared s3\_get\_object fact\.

## Configuration changes

| Fact | Statement | Baseline | Proposal | Pointer (proposal) |
|---|---|---|---|---|
| `f-ci-pass-deploy-admin` | p\-ci\-deployer can pass role r\-deploy\-admin to Lambda \(iam\:PassRole\) (newly enabled grant) | false | true | `/facts/1` |

## Findings

| Status | Severity | Finding | Baseline | Proposal |
|---|---|---|---|---|
| Added | High | p\-ci\-deployer can use privileged role r\-deploy\-admin | unreachable | reachable |

### Added · High · p\-ci\-deployer can use privileged role r\-deploy\-admin

- Finding ID: `finding/p-ci-deployer/r-deploy-admin/privileged_role_use`
- Impact: privileged role use; target classification `privileged_role`
- Baseline: unreachable; proposal: reachable

Witness in the proposal snapshot:

1. p\-ci\-deployer runs code as r\-deploy\-admin through Lambda workload l\-build\-hook \(Rule B\): candidate `B:p-ci-deployer->r-deploy-admin@l-build-hook` is **true**

   | Prerequisite | State | Evidence | JSON pointer |
   |---|---|---|---|
   | p\-ci\-deployer can pass role r\-deploy\-admin to Lambda \(iam\:PassRole\) | true | `f-ci-pass-deploy-admin` **CHANGED** | `/facts/1` |
   | p\-ci\-deployer can create Lambda workload l\-build\-hook | true | `f-ci-create-build-hook` | `/facts/2` |
   | p\-ci\-deployer can invoke Lambda workload l\-build\-hook | true | `f-ci-invoke-build-hook` | `/facts/3` |
   | p\-ci\-deployer controls the code of l\-build\-hook | true | `f-ci-controls-build-hook-code` (scenario assumption) | `/facts/4` |
   | r\-deploy\-admin trust policy allows the Lambda service | true | `f-deploy-admin-trusts-lambda` | `/facts/6` |
   | p\-ci\-deployer\, r\-deploy\-admin and l\-build\-hook are in the same synthetic account | true | derived | `/nodes/0/account_id`, `/nodes/2/account_id`, `/nodes/3/account_id` |
   | policy restrictions are declared resolved for this scenario | true | derived | `/coverage/policy_controls` |

Assumptions:
- Entry principal p\-ci\-deployer is treated as controlled by the party proposing the change\. This is a scenario assumption\, not an inferred compromise\.
- p\-ci\-deployer controls the code of l\-build\-hook \(scenario assumption\, fact f\-ci\-controls\-build\-hook\-code\)\.
- Declared facts stand for resolved synthetic model inputs\; they are not evidence that AWS would authorise the same request in a real account\.

## Expected-access checks

| Check | Relationship | Baseline | Proposal |
|---|---|---|---|
| `ea-ci-reads-build-artifacts` | `p-ci-deployer` object read `o-build-artifacts` | pass | pass |
| `ea-ci-deploys-app-runtime` | `p-ci-deployer` role use `r-app-runtime` | pass | pass |

## Fix simulation

| Candidate | Removes | Remaining high-risk | Expected access failing | Coverage after | Rank |
|---|---|---|---|---|---|
| `revoke/f-ci-pass-deploy-admin` | `finding/p-ci-deployer/r-deploy-admin/privileged_role_use` | 0 | 0 | complete | 1 |

No fix was simulated in this session.

## AI explanations

No AI explanation was requested for this analysis.

## Nodes

| ID | Kind | Account | Label (display only) |
|---|---|---|---|
| `l-build-hook` | Lambda workload | `syn-app-prod` | Post\-build hook function |
| `o-build-artifacts` | S3 object | `syn-app-prod` | artifacts\/release\.zip |
| `o-customer-export` | S3 object | `syn-app-prod` | exports\/customers\.csv |
| `p-ci-deployer` | Principal | `syn-app-prod` | CI deploy user \(build pipeline\) |
| `r-app-runtime` | Role | `syn-app-prod` | App runtime execution role |
| `r-deploy-admin` | Role | `syn-app-prod` | Deployment admin role |

## Limitations

- Input is hand-authored synthetic configuration JSON. Terraform, CloudFormation and raw IAM policies are not parsed.
- Only two rule families are modelled: direct S3 object reads (Rule A) and role use through a Lambda workload (Rule B).
- Permissions boundaries, SCPs, resource policies, conditions and explicit denies are not evaluated; the fixture declares whether their effect is already reflected in its facts.
- Complete coverage means complete for the declared synthetic model, not for an AWS account.
- Fix candidates are single revocations of newly enabled grants. They are not a minimum cut and do not prove that real business workflows keep working.
- The AI explanation is generated text. Identifier checks do not prove its prose is true; the deterministic evidence is authoritative.
