cloud-audit 2.2.0__tar.gz → 2.3.0__tar.gz

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.
Files changed (166) hide show
  1. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/CHANGELOG.md +182 -16
  2. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/PKG-INFO +28 -3
  3. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/README.md +26 -1
  4. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/ROADMAP.md +7 -3
  5. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/pyproject.toml +7 -2
  6. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/server.json +2 -2
  7. cloud_audit-2.3.0/src/cloud_audit/blast_radius.py +1257 -0
  8. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/src/cloud_audit/cli.py +383 -5
  9. cloud_audit-2.3.0/src/cloud_audit/graph.py +543 -0
  10. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/src/cloud_audit/models.py +7 -0
  11. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/src/cloud_audit/providers/aws/threat_feed/ses_phishing.py +57 -46
  12. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/src/cloud_audit/providers/aws/threat_feed/trufflehog_ua.py +30 -15
  13. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/src/cloud_audit/reports/compliance_html.py +21 -2
  14. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/src/cloud_audit/reports/html.py +29 -0
  15. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/src/cloud_audit/reports/templates/report.html.j2 +7 -3
  16. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/src/cloud_audit/scanner.py +62 -0
  17. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/tests/aws/threat_feed/test_ses_phishing.py +96 -32
  18. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/tests/aws/threat_feed/test_trufflehog_ua.py +18 -0
  19. cloud_audit-2.3.0/tests/test_blast_radius.py +629 -0
  20. cloud_audit-2.3.0/tests/test_graph.py +297 -0
  21. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/.cloud-audit.example.yml +0 -0
  22. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/.github/FUNDING.yml +0 -0
  23. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  24. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  25. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
  26. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/.github/dependabot.yml +0 -0
  27. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/.github/workflows/ci.yml +0 -0
  28. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/.github/workflows/docs.yml +0 -0
  29. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/.github/workflows/example-scan.yml +0 -0
  30. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/.github/workflows/release.yml +0 -0
  31. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/.gitignore +0 -0
  32. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/.mcp.json +0 -0
  33. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/.pre-commit-hooks.yaml +0 -0
  34. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/CODEOWNERS +0 -0
  35. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/CODE_OF_CONDUCT.md +0 -0
  36. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/CONTRIBUTING.md +0 -0
  37. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/Dockerfile +0 -0
  38. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/LICENSE +0 -0
  39. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/Makefile +0 -0
  40. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/SECURITY.md +0 -0
  41. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/action.yml +0 -0
  42. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/assets/demo.gif +0 -0
  43. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/assets/logo-nobg.png +0 -0
  44. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/assets/logo.png +0 -0
  45. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/assets/report-preview.png +0 -0
  46. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/assets/social-preview.png +0 -0
  47. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/examples/daily-scan-with-diff.yml +0 -0
  48. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/examples/github-actions.yml +0 -0
  49. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/examples/post-deploy-scan.yml +0 -0
  50. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/mkdocs.yml +0 -0
  51. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/overrides/main.html +0 -0
  52. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/scripts/generate_demo_gif.py +0 -0
  53. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/scripts/generate_report_screenshot.py +0 -0
  54. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/src/cloud_audit/__init__.py +0 -0
  55. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/src/cloud_audit/__main__.py +0 -0
  56. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/src/cloud_audit/compliance/__init__.py +0 -0
  57. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/src/cloud_audit/compliance/engine.py +0 -0
  58. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/src/cloud_audit/compliance/frameworks/bsi_c5_2020.json +0 -0
  59. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/src/cloud_audit/compliance/frameworks/cis_aws_v3.json +0 -0
  60. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/src/cloud_audit/compliance/frameworks/hipaa_security.json +0 -0
  61. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/src/cloud_audit/compliance/frameworks/iso27001_2022.json +0 -0
  62. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/src/cloud_audit/compliance/frameworks/nis2_directive.json +0 -0
  63. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/src/cloud_audit/compliance/frameworks/soc2_type2.json +0 -0
  64. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/src/cloud_audit/config.py +0 -0
  65. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/src/cloud_audit/correlate.py +0 -0
  66. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/src/cloud_audit/cost_model.py +0 -0
  67. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/src/cloud_audit/diff.py +0 -0
  68. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/src/cloud_audit/history.py +0 -0
  69. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/src/cloud_audit/mcp_server.py +0 -0
  70. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/src/cloud_audit/providers/__init__.py +0 -0
  71. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/src/cloud_audit/providers/aws/__init__.py +0 -0
  72. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/src/cloud_audit/providers/aws/checks/__init__.py +0 -0
  73. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/src/cloud_audit/providers/aws/checks/account.py +0 -0
  74. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/src/cloud_audit/providers/aws/checks/backup.py +0 -0
  75. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/src/cloud_audit/providers/aws/checks/bedrock.py +0 -0
  76. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/src/cloud_audit/providers/aws/checks/cloudtrail.py +0 -0
  77. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/src/cloud_audit/providers/aws/checks/cloudwatch.py +0 -0
  78. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/src/cloud_audit/providers/aws/checks/config_.py +0 -0
  79. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/src/cloud_audit/providers/aws/checks/ec2.py +0 -0
  80. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/src/cloud_audit/providers/aws/checks/ecs.py +0 -0
  81. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/src/cloud_audit/providers/aws/checks/efs.py +0 -0
  82. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/src/cloud_audit/providers/aws/checks/eip.py +0 -0
  83. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/src/cloud_audit/providers/aws/checks/guardduty.py +0 -0
  84. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/src/cloud_audit/providers/aws/checks/iam.py +0 -0
  85. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/src/cloud_audit/providers/aws/checks/inspector.py +0 -0
  86. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/src/cloud_audit/providers/aws/checks/kms.py +0 -0
  87. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/src/cloud_audit/providers/aws/checks/lambda_.py +0 -0
  88. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/src/cloud_audit/providers/aws/checks/rds.py +0 -0
  89. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/src/cloud_audit/providers/aws/checks/s3.py +0 -0
  90. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/src/cloud_audit/providers/aws/checks/sagemaker.py +0 -0
  91. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/src/cloud_audit/providers/aws/checks/secrets.py +0 -0
  92. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/src/cloud_audit/providers/aws/checks/securityhub.py +0 -0
  93. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/src/cloud_audit/providers/aws/checks/ssm.py +0 -0
  94. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/src/cloud_audit/providers/aws/checks/vpc.py +0 -0
  95. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/src/cloud_audit/providers/aws/checks/waf.py +0 -0
  96. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/src/cloud_audit/providers/aws/iam_analyzer.py +0 -0
  97. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/src/cloud_audit/providers/aws/iam_trust_graph.py +0 -0
  98. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/src/cloud_audit/providers/aws/provider.py +0 -0
  99. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/src/cloud_audit/providers/aws/threat_feed/__init__.py +0 -0
  100. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/src/cloud_audit/providers/aws/threat_feed/cloudtrail_tampering.py +0 -0
  101. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/src/cloud_audit/providers/aws/threat_feed/cryptomining_role.py +0 -0
  102. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/src/cloud_audit/providers/aws/threat_feed/datazone_overgrant.py +0 -0
  103. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/src/cloud_audit/providers/aws/threat_feed/lambda_function_url.py +0 -0
  104. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/src/cloud_audit/providers/aws/threat_feed/mmdsv1_in_use.py +0 -0
  105. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/src/cloud_audit/providers/aws/threat_feed/quarantine_policy.py +0 -0
  106. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/src/cloud_audit/providers/aws/threat_feed/roles_anywhere_abuse.py +0 -0
  107. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/src/cloud_audit/providers/aws/threat_feed/whoami_confusion.py +0 -0
  108. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/src/cloud_audit/providers/base.py +0 -0
  109. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/src/cloud_audit/py.typed +0 -0
  110. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/src/cloud_audit/reports/__init__.py +0 -0
  111. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/src/cloud_audit/reports/compliance_markdown.py +0 -0
  112. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/src/cloud_audit/reports/diff_markdown.py +0 -0
  113. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/src/cloud_audit/reports/markdown.py +0 -0
  114. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/src/cloud_audit/reports/sarif.py +0 -0
  115. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/src/cloud_audit/root_cause.py +0 -0
  116. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/src/cloud_audit/simulate.py +0 -0
  117. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/tests/__init__.py +0 -0
  118. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/tests/aws/__init__.py +0 -0
  119. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/tests/aws/test_bedrock.py +0 -0
  120. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/tests/aws/test_cis_checks.py +0 -0
  121. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/tests/aws/test_cloudtrail.py +0 -0
  122. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/tests/aws/test_cloudwatch.py +0 -0
  123. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/tests/aws/test_config.py +0 -0
  124. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/tests/aws/test_ec2.py +0 -0
  125. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/tests/aws/test_ecs.py +0 -0
  126. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/tests/aws/test_eip.py +0 -0
  127. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/tests/aws/test_guardduty.py +0 -0
  128. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/tests/aws/test_iam.py +0 -0
  129. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/tests/aws/test_iam_analyzer.py +0 -0
  130. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/tests/aws/test_iam_trust_graph.py +0 -0
  131. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/tests/aws/test_kms.py +0 -0
  132. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/tests/aws/test_lambda.py +0 -0
  133. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/tests/aws/test_rds.py +0 -0
  134. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/tests/aws/test_s3.py +0 -0
  135. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/tests/aws/test_sagemaker.py +0 -0
  136. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/tests/aws/test_secrets.py +0 -0
  137. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/tests/aws/test_ssm.py +0 -0
  138. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/tests/aws/test_vpc.py +0 -0
  139. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/tests/aws/threat_feed/__init__.py +0 -0
  140. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/tests/aws/threat_feed/test_cloudtrail_tampering.py +0 -0
  141. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/tests/aws/threat_feed/test_cryptomining_role.py +0 -0
  142. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/tests/aws/threat_feed/test_datazone_overgrant.py +0 -0
  143. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/tests/aws/threat_feed/test_lambda_function_url.py +0 -0
  144. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/tests/aws/threat_feed/test_mmdsv1_in_use.py +0 -0
  145. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/tests/aws/threat_feed/test_quarantine_policy.py +0 -0
  146. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/tests/aws/threat_feed/test_roles_anywhere_abuse.py +0 -0
  147. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/tests/aws/threat_feed/test_whoami_confusion.py +0 -0
  148. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/tests/conftest.py +0 -0
  149. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/tests/test_cli.py +0 -0
  150. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/tests/test_cli_scan.py +0 -0
  151. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/tests/test_compliance_frameworks.py +0 -0
  152. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/tests/test_config.py +0 -0
  153. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/tests/test_correlate.py +0 -0
  154. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/tests/test_cost_model.py +0 -0
  155. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/tests/test_diff.py +0 -0
  156. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/tests/test_history.py +0 -0
  157. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/tests/test_html.py +0 -0
  158. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/tests/test_markdown.py +0 -0
  159. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/tests/test_mcp_server.py +0 -0
  160. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/tests/test_models.py +0 -0
  161. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/tests/test_provider.py +0 -0
  162. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/tests/test_root_cause.py +0 -0
  163. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/tests/test_sarif.py +0 -0
  164. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/tests/test_scanner.py +0 -0
  165. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/tests/test_simulate.py +0 -0
  166. {cloud_audit-2.2.0 → cloud_audit-2.3.0}/tests/test_soc2_framework.py +0 -0
@@ -7,11 +7,177 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [2.3.0] - 2026-05-15
11
+
12
+ ### Added
13
+
14
+ - **Blast Radius CLI** - new `cloud-audit blast-radius --resource <id>` command
15
+ that walks outward from a single AWS resource and shows what an attacker
16
+ could reach if THAT resource were compromised. Pure in-memory analysis
17
+ against a saved scan - zero AWS API calls at blast-radius time.
18
+
19
+ Seed resource types supported:
20
+ - EC2 instance (short id `i-XXX`)
21
+ - IAM Role / IAM User (full ARN)
22
+ - Lambda function (full ARN)
23
+ - S3 bucket (full ARN)
24
+ - Secrets Manager secret (full ARN)
25
+
26
+ Expansion rules:
27
+ - Compute -> attached IAM role (via attack chain `viz_steps` from AC-01,
28
+ AC-02, AC-05 etc.) -> reachable identities and data
29
+ - Identity -> admin impact node when `escalation_paths` indicate admin
30
+ - Identity -> AssumeRole chain targets from `iam_trust_graph`
31
+ - Identity (admin) -> S3 buckets / Secrets Manager secrets present in
32
+ findings as candidate exfiltration targets
33
+
34
+ Output formats (`--format`):
35
+ - `tree` (default) - Rich tree in CLI with color-coded node types
36
+ - `json` - BlastRadiusGraph v1.0 schema, the wire-format contract with
37
+ cloud-audit-demo's 3D visualization (camelCase fields preserved on purpose)
38
+ - `mermaid` - Mermaid `graph TD` diagram with per-type styling
39
+ - `markdown` - compact summary for PRs or reports
40
+
41
+ Bounds:
42
+ - `--max-depth N` (default 5) caps BFS hops
43
+ - `--max-nodes N` (default 50) caps total nodes in the graph
44
+
45
+ Pure CLI, no Neo4j, no Docker, no SaaS account. Built on top of the
46
+ existing `iam_trust_graph` (524 lines, AssumeRole BFS), `iam_analyzer`
47
+ (706 lines, 60 escalation methods catalog), `correlate` (1574 lines,
48
+ 31 attack-chain rules with `VizStep`s), and `cost_model` so the
49
+ same fixes you see in `scan` show up under the same finding ids in the
50
+ blast-radius output. Documented in `docs/features/blast-radius.md`.
51
+
52
+ - **`exposure` command** - new `cloud-audit exposure` rolls up findings by
53
+ blast-impact heuristic (which identities/data would compound on the next
54
+ hop). Complements `blast-radius` (single-seed) with an account-wide view.
55
+
56
+ ### Changed
57
+
58
+ - **`ScanReport.security_graph`** - new optional field (`dict[str, object] | None`).
59
+ Populated by the scanner for blast-radius / exposure consumers. Backwards-
60
+ compatible: existing parsers that don't know the field will keep working
61
+ thanks to `default=None`.
62
+
63
+ ### Fixed
64
+
65
+ Nine issues addressed by the pre-release security audit (`SECURITY-AUDIT-2026-05-15.md`):
66
+
67
+ - **SEC-001** - Mermaid output now HTML-entity escapes user-controlled node
68
+ labels (`<`, `>`, `&`, `"`, `\`, plus brackets, braces, pipes). Without this,
69
+ a crafted scan label `</text>` would break out of the Mermaid SVG context
70
+ when the diagram is rendered in a GitHub README.
71
+ - **SEC-002** - `_make_id` collision protection: when a sanitised candidate id
72
+ exceeds 120 chars, a SHA-256(prefix + value) suffix is appended so two
73
+ long-but-different inputs cannot collide post-truncation (CWE-345 / CWE-1023).
74
+ - **SEC-003** - AssumeRole cycle (A->B->A) no longer re-emits the seed role
75
+ as a lateral target node. ARN-level dedup (`visited_arns`) catches the
76
+ cross-prefix duplicate that graph-id dedup alone misses.
77
+ - **SEC-004** - `_find_execution_role_for_lambda` now refuses to return a
78
+ role belonging to a different function (CWE-697 narrow-match): scan with
79
+ chain for `fnA` and query for `fnB` returns `None`, not `fnA`'s role.
80
+ - **SEC-005** - `--max-depth` and `--max-nodes` are clamped to safe bounds
81
+ (1..25 and 1..10_000) instead of accepting unbounded user input (DoS).
82
+ - **SEC-006** - `--format tree` + `--output FILE` returns an error instead of
83
+ silently writing ANSI escape sequences to disk (CWE-684).
84
+ - **SEC-007** - Exception handler in the CLI wraps `OSError` with a friendly
85
+ message instead of leaking a full Python traceback to stderr.
86
+ - **SEC-008** - Rich console rendering of node lines escapes Rich markup
87
+ (`[red]...[/]`) found inside scan labels so a crafted scan can't recolor
88
+ the terminal output.
89
+ - **SEC-009** - Scanner persists `escalation_paths` to the saved scan so
90
+ blast-radius can read them without re-running the IAM analyzer.
91
+
92
+ Plus pre-release follow-ups from the second security pass:
93
+
94
+ - **F-S2-01** - HTML report templates (`report.html.j2`, `compliance_html.py`)
95
+ now strip non-`http(s)` URL schemes from `finding.cost_estimate.source_url`
96
+ and `finding.remediation.doc_url`. Without this, a `javascript:` URL in a
97
+ crafted scan JSON would execute when the user clicks the link in the
98
+ rendered HTML report.
99
+ - **F-S2-02** - All `--output` writers refuse to follow pre-existing symlinks
100
+ (TOCTOU symlink attack protection on shared CI runners). The CLI raises a
101
+ clear error instead of silently clobbering the symlink target.
102
+ - **F-S2-03** - Markdown output (`--format markdown`) now escapes markdown
103
+ control characters in user-controlled labels so a crafted resource name
104
+ cannot inject `[link](javascript:...)` into the rendered report.
105
+ - **F-S2-04** - `_resolve_role_arn` falls back to `report.all_findings` when
106
+ the role isn't present in `escalation_paths` (an EC2 with an attached
107
+ admin role but no separate escalation path previously returned a
108
+ seed-only blast graph - now resolves and reports Account Takeover).
109
+ - **F-S2-05** - BFS `--max-depth=1` now surfaces Account Takeover for an
110
+ EC2 seed with an attached admin role (was off-by-one: compute->role
111
+ linkage previously consumed the depth budget).
112
+ - **F-S2-06** - Fix/detection matching no longer uses bare `endswith(label)`
113
+ for short labels - now requires a `/` or `:` boundary, eliminating false
114
+ positives where label `"admin"` matched `super-admin`.
115
+
116
+ ### Tests
117
+
118
+ - 786 -> 812 (+26 net). New regression tests in `tests/test_blast_radius.py`
119
+ and `tests/test_graph.py` cover: resource-type detection (8 regex patterns),
120
+ empty-scan seed-only behaviour, IAM role -> impact node, EC2 with attached
121
+ role linkage, Lambda with execution role, max-depth and max-nodes
122
+ enforcement, Rich tree render, Mermaid `graph TD` shape, JSON schema
123
+ spot-checks (top-level fields, camelCase preservation, node + edge type
124
+ enums), fixes and detections pulled from findings, and a full
125
+ `TestSecurityRegression` class for SEC-001 through SEC-009.
126
+
127
+ ### Schema contract
128
+
129
+ The JSON output is the schema documented in
130
+ `cloud-audit-demo/src/types/blast-radius.ts` (`BlastRadiusGraph` v1.0).
131
+ Field names are camelCase by intent because the demo's TypeScript types
132
+ are the consumer. A per-file ruff exemption in `pyproject.toml` documents
133
+ this trade-off.
134
+
135
+ ## [2.2.1] - 2026-05-12
136
+
137
+ ### Changed
138
+
139
+ - **TF-001 (SES phishing setup)** - severity escalation logic rewritten.
140
+ HIGH now requires BOTH out-of-sandbox AND a burst of >=2 recent
141
+ identity verifications in the same account scan. The previous
142
+ "email identity without matching domain" escalation has been removed:
143
+ it modeled the wrong attacker behaviour. Wiz's September 2025 research
144
+ documented attackers *"adding multiple domains as verified identities
145
+ using the CreateEmailIdentity API"* in quick succession - a burst
146
+ pattern, not a single typosquat email. The new logic matches what
147
+ the source incident actually documented.
148
+
149
+ - **TF-004 (leaked-creds scanner UA)** - removed `cloudgrappler` and
150
+ `detention-dodger` from the user-agent signature list. Both are
151
+ Permiso DEFENSIVE tools - their UA appearing in CloudTrail means a
152
+ defender is running them against the account, not that the account
153
+ is under attack. The detector now only matches OFFENSIVE scanner
154
+ signatures (`trufflehog`, `gitleaks`, `noseyparker`, `secretscanner`).
155
+ Module docstring updated with an explicit detection caveat: scanners
156
+ using stock AWS SDK / boto3 / aws-cli default user-agents look
157
+ identical to legitimate traffic and will not trigger this pattern.
158
+
159
+ - **TF-004 references** - replaced a fabricated TruffleHog blog URL in
160
+ the references list with the verified BleepingComputer / Kaspersky
161
+ May 2026 SES abuse coverage and the official TruffleHog GitHub repo.
162
+
163
+ ### Tests
164
+
165
+ - 742 -> 747 (+5 net). New regression tests:
166
+ - `test_email_no_matching_domain_does_not_escalate` (TF-001) proves
167
+ the removed typosquat heuristic does not return.
168
+ - `test_burst_out_of_sandbox_escalates_to_high` and
169
+ `test_burst_in_sandbox_stays_medium` cover the new escalation rule.
170
+ - `test_burst_only_counts_recent_identities` verifies the burst
171
+ counter respects the 14-day window.
172
+ - `test_cloudgrappler_ua_not_flagged` and
173
+ `test_detention_dodger_ua_not_flagged` (TF-004) prove defensive
174
+ tools are now excluded.
175
+
10
176
  ## [2.2.0] - 2026-05-12
11
177
 
12
178
  ### Added
13
179
 
14
- - **Threat Feed v1** new `cloud-audit threat-feed` command and a dedicated
180
+ - **Threat Feed v1** - new `cloud-audit threat-feed` command and a dedicated
15
181
  detector pipeline (`providers/aws/threat_feed/`) that flags ACTIVE abuse
16
182
  indicators rather than misconfiguration. Each pattern has a versioned
17
183
  `TF-XXX` ID, maps to the new `Category.THREAT`, and carries external
@@ -20,44 +186,44 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
20
186
 
21
187
  Ten patterns shipped:
22
188
 
23
- - `TF-001-ses-phishing-setup` (MEDIUM/HIGH) SES email/domain identities
189
+ - `TF-001-ses-phishing-setup` (MEDIUM/HIGH) - SES email/domain identities
24
190
  verified within the last 14 days, with severity escalating when an
25
191
  out-of-sandbox account hosts a typosquat-style email identity that has
26
192
  no matching domain identity. Tracks the Wiz May 2025 + BleepingComputer
27
193
  May 2026 SES abuse campaigns.
28
- - `TF-002-lambda-function-url-persistence` (HIGH/CRITICAL) Lambda
194
+ - `TF-002-lambda-function-url-persistence` (HIGH/CRITICAL) - Lambda
29
195
  functions exposed via `AuthType=NONE` Function URLs, escalating to
30
196
  CRITICAL when the execution role grants admin-class permissions
31
197
  (matching the role profile of the Nov-Dec 2025 cryptomining campaign).
32
- - `TF-003-quarantine-policy` (CRITICAL) IAM principals with
198
+ - `TF-003-quarantine-policy` (CRITICAL) - IAM principals with
33
199
  `AWSCompromisedKeyQuarantineV1/V2/V3` attached. AWS auto-attaches these
34
200
  after detecting credential exposure (typically a public GitHub commit).
35
- - `TF-004-trufflehog-ua-cloudtrail` (CRITICAL) `sts:GetCallerIdentity`
201
+ - `TF-004-trufflehog-ua-cloudtrail` (CRITICAL) - `sts:GetCallerIdentity`
36
202
  calls in the last 24h whose user-agent matches known leaked-credentials
37
203
  discovery scanners (TruffleHog, gitleaks, CloudGrappler, DetentionDodger,
38
204
  NoseyParker). Confirmed credential validation by an external scanner.
39
- - `TF-005-cryptomining-role` (HIGH/CRITICAL) IAM roles created within
205
+ - `TF-005-cryptomining-role` (HIGH/CRITICAL) - IAM roles created within
40
206
  the last 48 hours that carry broad compute managed policies (EC2 Full,
41
207
  PowerUser, Admin, ECS Full, Lambda Full). Escalates to CRITICAL when
42
208
  the same role also has SES sending permissions (mining + email-spam
43
209
  combo from the documented late-2025 campaign cluster).
44
- - `TF-006-mmdsv1-in-use` (HIGH/CRITICAL) EC2 instances where
210
+ - `TF-006-mmdsv1-in-use` (HIGH/CRITICAL) - EC2 instances where
45
211
  `HttpTokens != required` (IMDSv1 still callable) and Bedrock AgentCore
46
- agents on `metadataVersion=v1` (CRITICAL addresses Unit 42 'Cracks in
212
+ agents on `metadataVersion=v1` (CRITICAL - addresses Unit 42 'Cracks in
47
213
  the Bedrock' research and the Feb 2026 MMDSv2 default).
48
- - `TF-007-whoami-confusion` (MEDIUM) IAM roles trusted by CI/CD
214
+ - `TF-007-whoami-confusion` (MEDIUM) - IAM roles trusted by CI/CD
49
215
  identities (codebuild service principals, GitHub OIDC, GitLab OIDC,
50
- Buildkite federation) that have a broad EC2 managed policy attached
216
+ Buildkite federation) that have a broad EC2 managed policy attached -
51
217
  the precondition for the Datadog Feb 2025 whoAMI confusion attack.
52
- - `TF-008-cloudtrail-tampering` (HIGH/CRITICAL) CloudTrail trails with
53
- `IsLogging=False` (CRITICAL canonical post-credential-theft attacker
218
+ - `TF-008-cloudtrail-tampering` (HIGH/CRITICAL) - CloudTrail trails with
219
+ `IsLogging=False` (CRITICAL - canonical post-credential-theft attacker
54
220
  behaviour, AiTM phishing follow-on per Datadog March 2026) or with a
55
- populated `LatestDeliveryError` (HIGH S3 destination broken).
56
- - `TF-009-roles-anywhere-abuse` (HIGH/MEDIUM) IAM Roles Anywhere trust
221
+ populated `LatestDeliveryError` (HIGH - S3 destination broken).
222
+ - `TF-009-roles-anywhere-abuse` (HIGH/MEDIUM) - IAM Roles Anywhere trust
57
223
  anchors with `sourceType=CERTIFICATE_BUNDLE` instead of the recommended
58
224
  AWS_ACM_PCA. Anyone able to issue a chain-valid cert can mint AWS
59
225
  credentials (fwd:cloudsec 2025 'Let's Encrypt for AWS Console').
60
- - `TF-010-datazone-overgrant` (HIGH) `AmazonDataZoneFullAccess` attached
226
+ - `TF-010-datazone-overgrant` (HIGH) - `AmazonDataZoneFullAccess` attached
61
227
  to non-admin principals (the "easy" onboarding policy that bridges
62
228
  identity, Glue catalog, and S3 storage in a single grant).
63
229
 
@@ -172,7 +338,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
172
338
  - AC-29: Unpatched Instance Exposed to Internet (CRITICAL)
173
339
  - AC-30: Unpatched Instances Without Vulnerability Scanning (HIGH)
174
340
  - AC-31: Internet-Exposed Without WAF or Flow Logs (HIGH)
175
- - AC-32: CloudTrail Blind Spot Alarms Non-Functional (HIGH)
341
+ - AC-32: CloudTrail Blind Spot - Alarms Non-Functional (HIGH)
176
342
  - AC-33: All-Public VPC Without Network Segmentation (HIGH)
177
343
  - 3 new service modules: AWS Backup, Amazon Inspector, AWS WAF
178
344
  - 67 new tests for framework validation (412 total)
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cloud-audit
3
- Version: 2.2.0
4
- Summary: Open-source AWS security scanner. Threat Feed v1 (10 active-abuse patterns from 2025-2026 incidents), 64 IAM escalation methods, What-If simulator, security trends, AI-SPM (Bedrock/SageMaker), 6 compliance frameworks, 31 attack chain rules, breach cost estimation, and MCP server. Every finding includes CLI + Terraform remediation.
3
+ Version: 2.3.0
4
+ Summary: Open-source AWS security scanner. Blast Radius CLI (forward BFS from arbitrary resource), Threat Feed v1 (10 active-abuse patterns from 2025-2026 incidents), 64 IAM escalation methods, What-If simulator, security trends, AI-SPM (Bedrock/SageMaker), 6 compliance frameworks, 31 attack chain rules, breach cost estimation, and MCP server. Every finding includes CLI + Terraform remediation.
5
5
  Project-URL: Homepage, https://haitmg.pl/cloud-audit/
6
6
  Project-URL: Documentation, https://haitmg.pl/cloud-audit/
7
7
  Project-URL: Source, https://github.com/gebalamariusz/cloud-audit
@@ -57,7 +57,7 @@ Description-Content-Type: text/markdown
57
57
  </p>
58
58
 
59
59
  <p align="center">
60
- Open-source CLI scanner that helps you decide what to fix first &mdash;<br>
60
+ Open-source CLI scanner that helps you decide what to fix first -<br>
61
61
  not just what's wrong.
62
62
  </p>
63
63
 
@@ -101,6 +101,31 @@ Uses your default AWS credentials and region. Try without an AWS account:
101
101
  cloud-audit demo
102
102
  ```
103
103
 
104
+ ### NEW in v2.3: Blast Radius CLI
105
+
106
+ Walk outward from a single AWS resource and show what an attacker could reach
107
+ if THAT resource were compromised. Pure offline analysis against a saved scan -
108
+ zero AWS API calls at blast-radius time. Seed any EC2 instance, IAM role/user,
109
+ Lambda function, S3 bucket, or Secrets Manager secret.
110
+
111
+ ```bash
112
+ # Quick view: tree of reachable identities + data + impact
113
+ cloud-audit blast-radius --resource i-0abc123def456
114
+
115
+ # JSON for the blast-audit visualizer (https://blast-audit.haitmg.pl)
116
+ cloud-audit blast-radius --resource arn:aws:iam::123456789012:role/deploy \
117
+ --format json --output blast.json
118
+
119
+ # Mermaid diagram for docs / slides
120
+ cloud-audit blast-radius --resource i-0abc123 --format mermaid
121
+
122
+ # Markdown summary for PR comments
123
+ cloud-audit blast-radius --resource i-0abc123 --format markdown
124
+ ```
125
+
126
+ See [docs/features/blast-radius.md](docs/features/blast-radius.md) for the
127
+ expansion rules, JSON schema (BlastRadiusGraph v1.0), and risk score heuristic.
128
+
104
129
  ### NEW in v2.2: Threat Feed
105
130
 
106
131
  Detect ACTIVE abuse patterns from 2025-2026 incidents (cryptomining campaigns,
@@ -10,7 +10,7 @@
10
10
  </p>
11
11
 
12
12
  <p align="center">
13
- Open-source CLI scanner that helps you decide what to fix first &mdash;<br>
13
+ Open-source CLI scanner that helps you decide what to fix first -<br>
14
14
  not just what's wrong.
15
15
  </p>
16
16
 
@@ -54,6 +54,31 @@ Uses your default AWS credentials and region. Try without an AWS account:
54
54
  cloud-audit demo
55
55
  ```
56
56
 
57
+ ### NEW in v2.3: Blast Radius CLI
58
+
59
+ Walk outward from a single AWS resource and show what an attacker could reach
60
+ if THAT resource were compromised. Pure offline analysis against a saved scan -
61
+ zero AWS API calls at blast-radius time. Seed any EC2 instance, IAM role/user,
62
+ Lambda function, S3 bucket, or Secrets Manager secret.
63
+
64
+ ```bash
65
+ # Quick view: tree of reachable identities + data + impact
66
+ cloud-audit blast-radius --resource i-0abc123def456
67
+
68
+ # JSON for the blast-audit visualizer (https://blast-audit.haitmg.pl)
69
+ cloud-audit blast-radius --resource arn:aws:iam::123456789012:role/deploy \
70
+ --format json --output blast.json
71
+
72
+ # Mermaid diagram for docs / slides
73
+ cloud-audit blast-radius --resource i-0abc123 --format mermaid
74
+
75
+ # Markdown summary for PR comments
76
+ cloud-audit blast-radius --resource i-0abc123 --format markdown
77
+ ```
78
+
79
+ See [docs/features/blast-radius.md](docs/features/blast-radius.md) for the
80
+ expansion rules, JSON schema (BlastRadiusGraph v1.0), and risk score heuristic.
81
+
57
82
  ### NEW in v2.2: Threat Feed
58
83
 
59
84
  Detect ACTIVE abuse patterns from 2025-2026 incidents (cryptomining campaigns,
@@ -1,6 +1,6 @@
1
1
  # Roadmap
2
2
 
3
- > Current version: **v2.0.0** (April 2026)
3
+ > Current version: **v2.3.0** (May 2026)
4
4
 
5
5
  ## Completed
6
6
 
@@ -73,13 +73,17 @@
73
73
 
74
74
  ## What's Next
75
75
 
76
+ ### v2.3.0 -- Blast Radius CLI (shipped May 2026)
77
+
78
+ - **Blast Radius CLI** (MVP) -- `cloud-audit blast-radius --resource <id>` walks outward from a single AWS resource (EC2, IAM Role/User, Lambda, S3 bucket, secret) and reports what an attacker could reach if that resource were compromised. Tree, JSON (BlastRadiusGraph v1.0 schema), Mermaid, and Markdown output. Pure in-memory, no AWS calls at blast-radius time. Built on the existing IAM trust graph + escalation catalog. 26 new tests, 812 total. Includes a full pre-release security pass (SEC-001 through SEC-009 plus F-S2-01 through F-S2-06 hardening — URL scheme allowlisting in HTML reports, symlink-safe writes, markdown injection escape, cycle dedup in BFS).
79
+
76
80
  ### v3.0.0 -- Security Graph & Exposure Analysis (target: June 2026)
77
81
 
78
82
  **1. Security Graph + Effective Exposure Score**
79
83
  In-memory graph (networkx) modeling all resource relationships: VPC routing, subnets, security groups, EC2 instances, IAM roles, policies, S3 buckets, RDS instances. BFS/DFS from internet nodes to high-value targets. Per-resource "effective exposure score" combining network reachability + identity privilege + data sensitivity. Output: "3 paths from internet to production database."
80
84
 
81
- **2. Blast Radius Analysis**
82
- `cloud-audit blast-radius --resource i-0abc123` shows the full impact zone if a specific resource is compromised: IAM role access, network reach, lateral movement paths, data at risk, breach cost estimate. The inverse of attack path analysis.
85
+ **2. Blast Radius Analysis (full v3.0.0 expansion)**
86
+ MVP shipped in v2.3.0. Remaining for v3.0.0: network reachability (VPC peering, TGW, on-prem CIDR), cross-account propagation, permission boundary / SCP semantic evaluation, data classification (PII / PCI / PHI tagging on buckets), expanded storytelling templates, HTML report integration, MCP server `compute_blast_radius` tool.
83
87
 
84
88
  **3. NHI (Non-Human Identity) Audit + Data Perimeter Scanner**
85
89
  Full inventory of all non-human identities: IAM users with access keys, IAM roles, OIDC providers, Lambda/ECS/CodeBuild execution roles. Aging, rotation, privilege scoring, trust chain mapping. Data perimeter: RCPs, VPC endpoint policies, aws:SourceOrgID conditions, snapshot sharing.
@@ -4,8 +4,8 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "cloud-audit"
7
- version = "2.2.0"
8
- description = "Open-source AWS security scanner. Threat Feed v1 (10 active-abuse patterns from 2025-2026 incidents), 64 IAM escalation methods, What-If simulator, security trends, AI-SPM (Bedrock/SageMaker), 6 compliance frameworks, 31 attack chain rules, breach cost estimation, and MCP server. Every finding includes CLI + Terraform remediation."
7
+ version = "2.3.0"
8
+ description = "Open-source AWS security scanner. Blast Radius CLI (forward BFS from arbitrary resource), Threat Feed v1 (10 active-abuse patterns from 2025-2026 incidents), 64 IAM escalation methods, What-If simulator, security trends, AI-SPM (Bedrock/SageMaker), 6 compliance frameworks, 31 attack chain rules, breach cost estimation, and MCP server. Every finding includes CLI + Terraform remediation."
9
9
  readme = "README.md"
10
10
  license = "MIT"
11
11
  requires-python = ">=3.10"
@@ -81,6 +81,11 @@ select = ["E", "F", "I", "N", "W", "UP", "S", "B", "A", "C4", "SIM", "TCH", "RUF
81
81
  "src/cloud_audit/reports/compliance_markdown.py" = ["E501"]
82
82
  "src/cloud_audit/cli.py" = ["TC003"]
83
83
  "src/cloud_audit/mcp_server.py" = ["TC003"]
84
+ # Blast radius uses camelCase field names to match the BlastRadiusGraph v1.0
85
+ # wire-format contract shared with cloud-audit-demo (TypeScript types).
86
+ # Renaming would break the JSON output schema consumers depend on.
87
+ "src/cloud_audit/blast_radius.py" = ["N815"]
88
+ "tests/test_blast_radius.py" = ["S101", "N803", "N806", "N815"]
84
89
  # Threat-feed modules and tests intentionally use boto3-style CamelCase
85
90
  # kwargs (UserName, RoleName, FunctionName, EmailIdentity) to match the
86
91
  # AWS API surface they wrap. N803 (lower_snake_case argument) is wrong here.
@@ -8,12 +8,12 @@
8
8
  "url": "https://github.com/gebalamariusz/cloud-audit",
9
9
  "source": "github"
10
10
  },
11
- "version": "2.0.1",
11
+ "version": "2.3.0",
12
12
  "packages": [
13
13
  {
14
14
  "registryType": "pypi",
15
15
  "identifier": "cloud-audit",
16
- "version": "2.0.1",
16
+ "version": "2.3.0",
17
17
  "transport": {
18
18
  "type": "stdio"
19
19
  },