attackmap 0.6.4__py3-none-any.whl

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 (91) hide show
  1. attackmap/__init__.py +2 -0
  2. attackmap/analyzer.py +449 -0
  3. attackmap/analyzer_contracts.py +194 -0
  4. attackmap/analyzers.py +1003 -0
  5. attackmap/anomalies.py +612 -0
  6. attackmap/asset_model.py +245 -0
  7. attackmap/attack_taxonomy.py +133 -0
  8. attackmap/auth_protocol.py +702 -0
  9. attackmap/authz.py +1695 -0
  10. attackmap/bench.py +467 -0
  11. attackmap/cli.py +1474 -0
  12. attackmap/config_scanner.py +389 -0
  13. attackmap/context_pack.py +82 -0
  14. attackmap/contracts.py +201 -0
  15. attackmap/control_model.py +280 -0
  16. attackmap/crossrepo.py +356 -0
  17. attackmap/crypto.py +240 -0
  18. attackmap/cve.py +717 -0
  19. attackmap/defensive_review.py +647 -0
  20. attackmap/detection_opportunities.py +1221 -0
  21. attackmap/detections/__init__.py +491 -0
  22. attackmap/detections/bola.yml +57 -0
  23. attackmap/detections/cloud.yml +609 -0
  24. attackmap/detections/injection.yml +167 -0
  25. attackmap/detections/secrets.yml +48 -0
  26. attackmap/detections/sigma.py +511 -0
  27. attackmap/detections/ssrf.yml +98 -0
  28. attackmap/detections/weakness.yml +62 -0
  29. attackmap/detections/webhook.yml +45 -0
  30. attackmap/detections/workflow.yml +121 -0
  31. attackmap/diagrams.py +237 -0
  32. attackmap/diff.py +301 -0
  33. attackmap/exploitability.py +493 -0
  34. attackmap/fingerprint.py +91 -0
  35. attackmap/fleet.py +370 -0
  36. attackmap/gitref.py +129 -0
  37. attackmap/graph.py +26 -0
  38. attackmap/handler_auth.py +639 -0
  39. attackmap/handler_span.py +62 -0
  40. attackmap/hunt_harness.py +505 -0
  41. attackmap/insights.py +701 -0
  42. attackmap/llm_review.py +846 -0
  43. attackmap/lockfiles.py +521 -0
  44. attackmap/mass_assignment.py +543 -0
  45. attackmap/md.py +175 -0
  46. attackmap/merge.py +333 -0
  47. attackmap/models.py +1284 -0
  48. attackmap/plugins_lock.py +114 -0
  49. attackmap/popular_packages.py +193 -0
  50. attackmap/progress.py +258 -0
  51. attackmap/recon_models.py +31 -0
  52. attackmap/recon_to_analysis.py +149 -0
  53. attackmap/redact.py +220 -0
  54. attackmap/report.py +424 -0
  55. attackmap/review_eval.py +335 -0
  56. attackmap/review_json.py +308 -0
  57. attackmap/review_prompts.py +796 -0
  58. attackmap/route_auth_fusion.py +474 -0
  59. attackmap/safe_fs.py +285 -0
  60. attackmap/sarif.py +373 -0
  61. attackmap/sbom.py +418 -0
  62. attackmap/scanner.py +1379 -0
  63. attackmap/sdk/__init__.py +278 -0
  64. attackmap/sdk/contracts.py +17 -0
  65. attackmap/sdk/fs.py +156 -0
  66. attackmap/sdk/models.py +59 -0
  67. attackmap/secrets_history.py +161 -0
  68. attackmap/security_overlay.py +71 -0
  69. attackmap/srcpaths.py +301 -0
  70. attackmap/suggest.py +394 -0
  71. attackmap/supply_chain.py +688 -0
  72. attackmap/suppress.py +740 -0
  73. attackmap/taint.py +1540 -0
  74. attackmap/taint_flow.py +1419 -0
  75. attackmap/taint_sinks.py +431 -0
  76. attackmap/taint_sinks.yaml +308 -0
  77. attackmap/taint_sources.py +396 -0
  78. attackmap/taxonomy.py +465 -0
  79. attackmap/threat_model.py +3441 -0
  80. attackmap/topology.py +316 -0
  81. attackmap/triage.py +151 -0
  82. attackmap/weaknesses.py +365 -0
  83. attackmap/webhardening.py +479 -0
  84. attackmap/webhook_verification.py +1067 -0
  85. attackmap/workflow_scanner.py +964 -0
  86. attackmap-0.6.4.dist-info/METADATA +226 -0
  87. attackmap-0.6.4.dist-info/RECORD +91 -0
  88. attackmap-0.6.4.dist-info/WHEEL +5 -0
  89. attackmap-0.6.4.dist-info/entry_points.txt +2 -0
  90. attackmap-0.6.4.dist-info/licenses/LICENSE +21 -0
  91. attackmap-0.6.4.dist-info/top_level.txt +1 -0
@@ -0,0 +1,609 @@
1
+ # Cloud and Kubernetes misconfiguration rules (#351), keyed by the
2
+ # CloudMisconfig rule ids (#334). Each rule watches the control plane for the
3
+ # risky setting being applied: the Kubernetes API audit log for workloads and
4
+ # RBAC, CloudTrail for AWS resources. Every selection needs the risky
5
+ # attribute itself (privileged: true, a 0.0.0.0/0 range, roleRef
6
+ # cluster-admin), never a bare event name.
7
+ #
8
+ # Audit and CloudTrail events nest arrays (containers, rules, ipRanges). The
9
+ # field paths below are the dotted, array-flattened names most pipelines
10
+ # produce (Elastic, Splunk spath, Sentinel parse_json). Kubernetes rules on
11
+ # requestObject need audit level Request or RequestResponse for these
12
+ # resources. Map the names to your pipeline.
13
+
14
+ templates:
15
+ k8s-privileged-workload:
16
+ date: "2026-10-12"
17
+ title: "Kubernetes workload created or changed with a privileged container"
18
+ description: >-
19
+ A pod or workload controller (including CronJob job templates and
20
+ init or ephemeral containers) is created or updated with a container
21
+ running privileged (full access to the node). AttackMap found
22
+ privileged containers in ${locations} (rule ${rule_id}); applying such a
23
+ spec is the step that hands an attacker in the container the node.
24
+ logsource: {product: kubernetes, service: audit}
25
+ fields_required: [verb, objectRef.resource, objectRef.namespace, objectRef.name, user.username, requestObject.spec.containers.securityContext.privileged, requestObject.spec.template.spec.containers.securityContext.privileged, requestObject.spec.jobTemplate.spec.template.spec.containers.securityContext.privileged]
26
+ detection:
27
+ selection_write:
28
+ verb: [create, update, patch]
29
+ objectRef.resource: [pods, deployments, daemonsets, statefulsets, replicasets, replicationcontrollers, jobs, cronjobs]
30
+ priv_any:
31
+ - requestObject.spec.containers.securityContext.privileged: true
32
+ - requestObject.spec.initContainers.securityContext.privileged: true
33
+ - requestObject.spec.ephemeralContainers.securityContext.privileged: true
34
+ - requestObject.spec.template.spec.containers.securityContext.privileged: true
35
+ - requestObject.spec.template.spec.initContainers.securityContext.privileged: true
36
+ - requestObject.spec.template.spec.ephemeralContainers.securityContext.privileged: true
37
+ - requestObject.spec.jobTemplate.spec.template.spec.containers.securityContext.privileged: true
38
+ - requestObject.spec.jobTemplate.spec.template.spec.initContainers.securityContext.privileged: true
39
+ - requestObject.spec.jobTemplate.spec.template.spec.ephemeralContainers.securityContext.privileged: true
40
+ condition: selection_write and priv_any
41
+ falsepositives:
42
+ - CNI, CSI and monitoring agents that need privileged mode (exclude their namespaces, e.g. kube-system)
43
+ level: high
44
+ test_events:
45
+ positive:
46
+ - verb: create
47
+ objectRef.resource: daemonsets
48
+ objectRef.namespace: default
49
+ user.username: alice
50
+ requestObject.spec.template.spec.containers.securityContext.privileged: true
51
+ negative:
52
+ - verb: create
53
+ objectRef.resource: deployments
54
+ objectRef.namespace: default
55
+ user.username: alice
56
+ requestObject.spec.template.spec.containers.securityContext.privileged: false
57
+ - verb: get
58
+ objectRef.resource: pods
59
+ requestObject.spec.containers.securityContext.privileged: true
60
+
61
+ k8s-privilege-escalation-workload:
62
+ date: "2026-10-12"
63
+ title: "Kubernetes workload allows privilege escalation or adds dangerous capabilities"
64
+ description: >-
65
+ A pod or workload controller is created or updated with
66
+ allowPrivilegeEscalation true or a container capability that breaks
67
+ isolation (SYS_ADMIN, NET_ADMIN, SYS_PTRACE, SYS_MODULE, ALL).
68
+ AttackMap found this in ${locations} (rule ${rule_id}).
69
+ logsource: {product: kubernetes, service: audit}
70
+ fields_required: [verb, objectRef.resource, objectRef.namespace, user.username, requestObject.spec.containers.securityContext.allowPrivilegeEscalation, requestObject.spec.containers.securityContext.capabilities.add]
71
+ detection:
72
+ selection_write:
73
+ verb: [create, update, patch]
74
+ objectRef.resource: [pods, deployments, daemonsets, statefulsets, replicasets, replicationcontrollers, jobs, cronjobs]
75
+ esc_flag:
76
+ - requestObject.spec.containers.securityContext.allowPrivilegeEscalation: true
77
+ - requestObject.spec.initContainers.securityContext.allowPrivilegeEscalation: true
78
+ - requestObject.spec.ephemeralContainers.securityContext.allowPrivilegeEscalation: true
79
+ - requestObject.spec.template.spec.containers.securityContext.allowPrivilegeEscalation: true
80
+ - requestObject.spec.template.spec.initContainers.securityContext.allowPrivilegeEscalation: true
81
+ - requestObject.spec.template.spec.ephemeralContainers.securityContext.allowPrivilegeEscalation: true
82
+ - requestObject.spec.jobTemplate.spec.template.spec.containers.securityContext.allowPrivilegeEscalation: true
83
+ - requestObject.spec.jobTemplate.spec.template.spec.initContainers.securityContext.allowPrivilegeEscalation: true
84
+ - requestObject.spec.jobTemplate.spec.template.spec.ephemeralContainers.securityContext.allowPrivilegeEscalation: true
85
+ esc_cap:
86
+ - requestObject.spec.containers.securityContext.capabilities.add: [SYS_ADMIN, NET_ADMIN, SYS_PTRACE, SYS_MODULE, DAC_READ_SEARCH, ALL]
87
+ - requestObject.spec.initContainers.securityContext.capabilities.add: [SYS_ADMIN, NET_ADMIN, SYS_PTRACE, SYS_MODULE, DAC_READ_SEARCH, ALL]
88
+ - requestObject.spec.ephemeralContainers.securityContext.capabilities.add: [SYS_ADMIN, NET_ADMIN, SYS_PTRACE, SYS_MODULE, DAC_READ_SEARCH, ALL]
89
+ - requestObject.spec.template.spec.containers.securityContext.capabilities.add: [SYS_ADMIN, NET_ADMIN, SYS_PTRACE, SYS_MODULE, DAC_READ_SEARCH, ALL]
90
+ - requestObject.spec.template.spec.initContainers.securityContext.capabilities.add: [SYS_ADMIN, NET_ADMIN, SYS_PTRACE, SYS_MODULE, DAC_READ_SEARCH, ALL]
91
+ - requestObject.spec.template.spec.ephemeralContainers.securityContext.capabilities.add: [SYS_ADMIN, NET_ADMIN, SYS_PTRACE, SYS_MODULE, DAC_READ_SEARCH, ALL]
92
+ - requestObject.spec.jobTemplate.spec.template.spec.containers.securityContext.capabilities.add: [SYS_ADMIN, NET_ADMIN, SYS_PTRACE, SYS_MODULE, DAC_READ_SEARCH, ALL]
93
+ - requestObject.spec.jobTemplate.spec.template.spec.initContainers.securityContext.capabilities.add: [SYS_ADMIN, NET_ADMIN, SYS_PTRACE, SYS_MODULE, DAC_READ_SEARCH, ALL]
94
+ - requestObject.spec.jobTemplate.spec.template.spec.ephemeralContainers.securityContext.capabilities.add: [SYS_ADMIN, NET_ADMIN, SYS_PTRACE, SYS_MODULE, DAC_READ_SEARCH, ALL]
95
+ condition: selection_write and 1 of esc_*
96
+ falsepositives:
97
+ - Network and storage agents that need NET_ADMIN or SYS_ADMIN (exclude their namespaces)
98
+ level: medium
99
+ test_events:
100
+ positive:
101
+ - verb: create
102
+ objectRef.resource: pods
103
+ requestObject.spec.containers.securityContext.capabilities.add: SYS_ADMIN
104
+ negative:
105
+ - verb: create
106
+ objectRef.resource: pods
107
+ requestObject.spec.containers.securityContext.capabilities.add: NET_BIND_SERVICE
108
+
109
+ k8s-host-access-workload:
110
+ date: "2026-10-12"
111
+ title: "Kubernetes workload mounts a host path or shares a host namespace"
112
+ description: >-
113
+ A pod or workload controller is created or updated with a hostPath
114
+ volume or hostNetwork / hostPID / hostIPC, which give the container
115
+ the node's files or namespaces. AttackMap found this in ${locations}
116
+ (rule ${rule_id}).
117
+ logsource: {product: kubernetes, service: audit}
118
+ fields_required: [verb, objectRef.resource, objectRef.namespace, user.username, requestObject.spec.volumes.hostPath.path, requestObject.spec.hostNetwork, requestObject.spec.hostPID, requestObject.spec.hostIPC]
119
+ detection:
120
+ selection_write:
121
+ verb: [create, update, patch]
122
+ objectRef.resource: [pods, deployments, daemonsets, statefulsets, replicasets, replicationcontrollers, jobs, cronjobs]
123
+ host_path:
124
+ - requestObject.spec.volumes.hostPath.path|startswith: /
125
+ - requestObject.spec.template.spec.volumes.hostPath.path|startswith: /
126
+ - requestObject.spec.jobTemplate.spec.template.spec.volumes.hostPath.path|startswith: /
127
+ host_namespace:
128
+ - requestObject.spec.hostNetwork: true
129
+ - requestObject.spec.hostPID: true
130
+ - requestObject.spec.hostIPC: true
131
+ - requestObject.spec.template.spec.hostNetwork: true
132
+ - requestObject.spec.template.spec.hostPID: true
133
+ - requestObject.spec.template.spec.hostIPC: true
134
+ - requestObject.spec.jobTemplate.spec.template.spec.hostNetwork: true
135
+ - requestObject.spec.jobTemplate.spec.template.spec.hostPID: true
136
+ - requestObject.spec.jobTemplate.spec.template.spec.hostIPC: true
137
+ condition: selection_write and 1 of host_*
138
+ falsepositives:
139
+ - Node agents (log shippers, CNI, node exporters) that read the host by design; exclude their namespaces
140
+ level: high
141
+ test_events:
142
+ positive:
143
+ - verb: create
144
+ objectRef.resource: daemonsets
145
+ requestObject.spec.template.spec.volumes.hostPath.path: /var/run/docker.sock
146
+ - verb: patch
147
+ objectRef.resource: deployments
148
+ requestObject.spec.template.spec.hostNetwork: true
149
+ negative:
150
+ - verb: create
151
+ objectRef.resource: deployments
152
+ requestObject.spec.template.spec.hostNetwork: false
153
+ - verb: delete
154
+ objectRef.resource: daemonsets
155
+ requestObject.spec.template.spec.volumes.hostPath.path: /var/log
156
+
157
+ k8s-exposed-service:
158
+ date: "2026-10-12"
159
+ title: "Kubernetes Service exposed outside the cluster"
160
+ description: >-
161
+ A Service is created or changed to type LoadBalancer or NodePort,
162
+ which publishes it outside the cluster. AttackMap found exposed
163
+ services in ${locations} (rule ${rule_id}).
164
+ logsource: {product: kubernetes, service: audit}
165
+ fields_required: [verb, objectRef.resource, objectRef.namespace, objectRef.name, user.username, requestObject.spec.type]
166
+ detection:
167
+ selection:
168
+ verb: [create, update, patch]
169
+ objectRef.resource: services
170
+ requestObject.spec.type: [LoadBalancer, NodePort]
171
+ condition: selection
172
+ falsepositives:
173
+ - Ingress controllers and intended public services; exclude them by namespace and name
174
+ level: low
175
+ test_events:
176
+ positive:
177
+ - verb: create
178
+ objectRef.resource: services
179
+ requestObject.spec.type: LoadBalancer
180
+ negative:
181
+ - verb: create
182
+ objectRef.resource: services
183
+ requestObject.spec.type: ClusterIP
184
+
185
+ k8s-rbac-wildcard-grant:
186
+ date: "2026-10-12"
187
+ title: "Kubernetes Role or ClusterRole granting wildcard verbs or resources"
188
+ description: >-
189
+ A Role or ClusterRole is created or changed with "*" in its verbs or
190
+ resources. AttackMap found wildcard RBAC rules in ${locations} (rule
191
+ ${rule_id}).
192
+ logsource: {product: kubernetes, service: audit}
193
+ fields_required: [verb, objectRef.resource, objectRef.name, user.username, requestObject.rules.verbs, requestObject.rules.resources]
194
+ detection:
195
+ selection_write:
196
+ verb: [create, update, patch]
197
+ objectRef.resource: [roles, clusterroles]
198
+ wildcard_verbs:
199
+ requestObject.rules.verbs|re: ^\*$
200
+ wildcard_resources:
201
+ requestObject.rules.resources|re: ^\*$
202
+ condition: selection_write and 1 of wildcard_*
203
+ falsepositives:
204
+ - The built-in cluster-admin and admin roles when the cluster is bootstrapped or upgraded (user system:apiserver)
205
+ level: high
206
+ test_events:
207
+ positive:
208
+ - verb: create
209
+ objectRef.resource: clusterroles
210
+ user.username: alice
211
+ requestObject.rules.verbs: "*"
212
+ negative:
213
+ - verb: create
214
+ objectRef.resource: clusterroles
215
+ user.username: alice
216
+ requestObject.rules.verbs: get
217
+
218
+ k8s-rbac-escalation-grant:
219
+ date: "2026-10-12"
220
+ title: "Kubernetes RBAC grant of escalate, bind or impersonate"
221
+ description: >-
222
+ A Role or ClusterRole is created or changed to allow escalate, bind or
223
+ impersonate, the verbs that let a subject grant itself more rights.
224
+ AttackMap found such rules in ${locations} (rule ${rule_id}).
225
+ logsource: {product: kubernetes, service: audit}
226
+ fields_required: [verb, objectRef.resource, objectRef.name, user.username, requestObject.rules.verbs]
227
+ detection:
228
+ selection:
229
+ verb: [create, update, patch]
230
+ objectRef.resource: [roles, clusterroles]
231
+ requestObject.rules.verbs: [escalate, bind, impersonate]
232
+ condition: selection
233
+ falsepositives:
234
+ - Cluster bootstrap and operators that manage RBAC (user system:apiserver, OLM)
235
+ level: high
236
+ test_events:
237
+ positive:
238
+ - verb: patch
239
+ objectRef.resource: roles
240
+ requestObject.rules.verbs: impersonate
241
+ negative:
242
+ - verb: patch
243
+ objectRef.resource: roles
244
+ requestObject.rules.verbs: list
245
+
246
+ k8s-pod-exec:
247
+ date: "2026-10-12"
248
+ title: "Service account opens an exec or attach session in a Kubernetes pod"
249
+ description: >-
250
+ A service account (not a person) opens an exec or attach session in a
251
+ pod (pods/exec, pods/attach). kubectl 1.30 and later exec over
252
+ WebSocket, which reaches the API server as a GET and is recorded with
253
+ verb get; older clients use create. AttackMap found RBAC rules that grant
254
+ this broadly in ${locations} (rule ${rule_id}); with them, a stolen
255
+ service-account token runs commands in other workloads. Workloads
256
+ rarely exec into each other, so this is a strong signal.
257
+ logsource: {product: kubernetes, service: audit}
258
+ fields_required: [verb, objectRef.resource, objectRef.subresource, objectRef.namespace, objectRef.name, user.username]
259
+ detection:
260
+ selection:
261
+ verb: [create, get]
262
+ objectRef.resource: pods
263
+ objectRef.subresource: [exec, attach]
264
+ user.username|startswith: "system:serviceaccount:"
265
+ condition: selection
266
+ falsepositives:
267
+ - CI/CD or debugging tools that exec through a service account (exclude them by name)
268
+ level: high
269
+ test_events:
270
+ positive:
271
+ - verb: create
272
+ objectRef.resource: pods
273
+ objectRef.subresource: exec
274
+ user.username: system:serviceaccount:web:default
275
+ - verb: get
276
+ objectRef.resource: pods
277
+ objectRef.subresource: exec
278
+ user.username: system:serviceaccount:ci:runner
279
+ negative:
280
+ - verb: create
281
+ objectRef.resource: pods
282
+ objectRef.subresource: exec
283
+ user.username: alice@example.com
284
+ - verb: get
285
+ objectRef.resource: pods
286
+ objectRef.subresource: log
287
+ user.username: system:serviceaccount:web:default
288
+
289
+ k8s-cluster-admin-binding:
290
+ date: "2026-10-12"
291
+ title: "Kubernetes binding to the cluster-admin role"
292
+ description: >-
293
+ A RoleBinding or ClusterRoleBinding to cluster-admin is created or
294
+ changed. AttackMap found cluster-admin bindings in ${locations} (rule
295
+ ${rule_id}).
296
+ logsource: {product: kubernetes, service: audit}
297
+ fields_required: [verb, objectRef.resource, objectRef.name, user.username, requestObject.roleRef.name, requestObject.subjects.name]
298
+ detection:
299
+ selection:
300
+ verb: [create, update, patch]
301
+ objectRef.resource: [clusterrolebindings, rolebindings]
302
+ requestObject.roleRef.name: cluster-admin
303
+ condition: selection
304
+ falsepositives:
305
+ - Cluster bootstrap (user system:apiserver) and managed-cluster admin setup
306
+ level: high
307
+ test_events:
308
+ positive:
309
+ - verb: create
310
+ objectRef.resource: clusterrolebindings
311
+ requestObject.roleRef.name: cluster-admin
312
+ negative:
313
+ - verb: create
314
+ objectRef.resource: clusterrolebindings
315
+ requestObject.roleRef.name: view
316
+
317
+ k8s-secret-enumeration:
318
+ date: "2026-10-12"
319
+ title: "Kubernetes secrets listed or watched by a non-system user"
320
+ description: >-
321
+ A list or watch of secrets by a user or service account outside the
322
+ control plane. AttackMap found roles granting broad secret access in
323
+ ${locations} (rule ${rule_id}); bulk reads are how a stolen token is
324
+ turned into every credential in the namespace or cluster.
325
+ logsource: {product: kubernetes, service: audit}
326
+ fields_required: [verb, objectRef.resource, objectRef.namespace, user.username]
327
+ detection:
328
+ selection:
329
+ verb: [list, watch]
330
+ objectRef.resource: secrets
331
+ filter_control_plane:
332
+ user.username|startswith: ["system:kube-", "system:node:", "system:serviceaccount:kube-system:"]
333
+ condition: selection and not filter_control_plane
334
+ falsepositives:
335
+ - Operators and controllers that cache secrets (cert-manager, external-secrets, Helm); exclude their service accounts
336
+ level: low
337
+ test_events:
338
+ positive:
339
+ - verb: list
340
+ objectRef.resource: secrets
341
+ user.username: system:serviceaccount:web:default
342
+ negative:
343
+ - verb: list
344
+ objectRef.resource: secrets
345
+ user.username: system:kube-controller-manager
346
+ - verb: get
347
+ objectRef.resource: configmaps
348
+ user.username: alice
349
+
350
+ aws-security-group-open-ingress:
351
+ date: "2026-10-12"
352
+ title: "AWS security group opened to the whole internet"
353
+ description: >-
354
+ An ingress rule allowing 0.0.0.0/0 or ::/0 is added to a security
355
+ group. AttackMap found publicly reachable network rules in
356
+ ${locations} (rule ${rule_id}).
357
+ logsource: {product: aws, service: cloudtrail}
358
+ fields_required: [eventSource, eventName, userIdentity.arn, sourceIPAddress, requestParameters.groupId, requestParameters.ipPermissions.items.ipRanges.items.cidrIp, requestParameters.ipPermissions.items.ipv6Ranges.items.cidrIpv6]
359
+ detection:
360
+ selection:
361
+ eventSource: ec2.amazonaws.com
362
+ eventName: AuthorizeSecurityGroupIngress
363
+ open_v4:
364
+ requestParameters.ipPermissions.items.ipRanges.items.cidrIp: 0.0.0.0/0
365
+ open_v6:
366
+ requestParameters.ipPermissions.items.ipv6Ranges.items.cidrIpv6: "::/0"
367
+ condition: selection and 1 of open_*
368
+ falsepositives:
369
+ - Load balancer security groups that are public by design (ports 80/443)
370
+ level: medium
371
+ test_events:
372
+ positive:
373
+ - eventSource: ec2.amazonaws.com
374
+ eventName: AuthorizeSecurityGroupIngress
375
+ requestParameters.ipPermissions.items.ipRanges.items.cidrIp: 0.0.0.0/0
376
+ negative:
377
+ - eventSource: ec2.amazonaws.com
378
+ eventName: AuthorizeSecurityGroupIngress
379
+ requestParameters.ipPermissions.items.ipRanges.items.cidrIp: 10.0.0.0/8
380
+
381
+ aws-rds-publicly-accessible:
382
+ date: "2026-10-12"
383
+ title: "AWS RDS database made publicly accessible"
384
+ description: >-
385
+ An RDS instance or cluster is created or modified with
386
+ PubliclyAccessible true. AttackMap found publicly accessible databases
387
+ in ${locations} (rule ${rule_id}).
388
+ logsource: {product: aws, service: cloudtrail}
389
+ fields_required: [eventSource, eventName, userIdentity.arn, requestParameters.dBInstanceIdentifier, requestParameters.publiclyAccessible]
390
+ detection:
391
+ selection:
392
+ eventSource: rds.amazonaws.com
393
+ eventName: [CreateDBInstance, ModifyDBInstance, CreateDBCluster, ModifyDBCluster, RestoreDBInstanceFromDBSnapshot]
394
+ requestParameters.publiclyAccessible: true
395
+ condition: selection
396
+ falsepositives:
397
+ - Databases deliberately public behind other controls (rare; document them)
398
+ level: high
399
+ test_events:
400
+ positive:
401
+ - eventSource: rds.amazonaws.com
402
+ eventName: ModifyDBInstance
403
+ requestParameters.publiclyAccessible: true
404
+ negative:
405
+ - eventSource: rds.amazonaws.com
406
+ eventName: ModifyDBInstance
407
+ requestParameters.publiclyAccessible: false
408
+
409
+ aws-instance-public-ip:
410
+ date: "2026-10-12"
411
+ title: "AWS EC2 instance launched with a public IP address"
412
+ description: >-
413
+ RunInstances with a network interface that associates a public IP.
414
+ AttackMap found instances with public addresses in ${locations} (rule
415
+ ${rule_id}).
416
+ logsource: {product: aws, service: cloudtrail}
417
+ fields_required: [eventSource, eventName, userIdentity.arn, requestParameters.networkInterfaceSet.items.associatePublicIpAddress]
418
+ detection:
419
+ selection:
420
+ eventSource: ec2.amazonaws.com
421
+ eventName: RunInstances
422
+ requestParameters.networkInterfaceSet.items.associatePublicIpAddress: true
423
+ condition: selection
424
+ falsepositives:
425
+ - Bastion hosts and public-facing instances by design; exclude by subnet or tag
426
+ level: low
427
+ test_events:
428
+ positive:
429
+ - eventSource: ec2.amazonaws.com
430
+ eventName: RunInstances
431
+ requestParameters.networkInterfaceSet.items.associatePublicIpAddress: true
432
+ negative:
433
+ - eventSource: ec2.amazonaws.com
434
+ eventName: RunInstances
435
+ requestParameters.networkInterfaceSet.items.associatePublicIpAddress: false
436
+
437
+ aws-s3-made-public:
438
+ date: "2026-10-12"
439
+ title: "AWS S3 Block Public Access weakened or public ACL applied"
440
+ description: >-
441
+ A bucket's (or the account's) Block Public Access configuration is
442
+ deleted or set with any of its four protections off, or a public
443
+ canned ACL is applied. AttackMap found publicly readable storage in
444
+ ${locations} (rule ${rule_id}).
445
+ logsource: {product: aws, service: cloudtrail}
446
+ fields_required: [eventSource, eventName, userIdentity.arn, requestParameters.bucketName, requestParameters.x-amz-acl, requestParameters.PublicAccessBlockConfiguration.BlockPublicAcls, requestParameters.PublicAccessBlockConfiguration.IgnorePublicAcls, requestParameters.PublicAccessBlockConfiguration.BlockPublicPolicy, requestParameters.PublicAccessBlockConfiguration.RestrictPublicBuckets]
447
+ detection:
448
+ selection_s3:
449
+ eventSource: [s3.amazonaws.com, s3-control.amazonaws.com]
450
+ block_removed:
451
+ eventName: [DeleteBucketPublicAccessBlock, DeleteAccountPublicAccessBlock, DeletePublicAccessBlock]
452
+ block_weakened:
453
+ - eventName: [PutBucketPublicAccessBlock, PutAccountPublicAccessBlock, PutPublicAccessBlock]
454
+ requestParameters.PublicAccessBlockConfiguration.BlockPublicAcls: false
455
+ - eventName: [PutBucketPublicAccessBlock, PutAccountPublicAccessBlock, PutPublicAccessBlock]
456
+ requestParameters.PublicAccessBlockConfiguration.IgnorePublicAcls: false
457
+ - eventName: [PutBucketPublicAccessBlock, PutAccountPublicAccessBlock, PutPublicAccessBlock]
458
+ requestParameters.PublicAccessBlockConfiguration.BlockPublicPolicy: false
459
+ - eventName: [PutBucketPublicAccessBlock, PutAccountPublicAccessBlock, PutPublicAccessBlock]
460
+ requestParameters.PublicAccessBlockConfiguration.RestrictPublicBuckets: false
461
+ public_acl:
462
+ eventName: [PutBucketAcl, PutObjectAcl, CreateBucket]
463
+ requestParameters.x-amz-acl: [public-read, public-read-write]
464
+ condition: selection_s3 and (block_removed or block_weakened or public_acl)
465
+ falsepositives:
466
+ - Static-website buckets that are public by design
467
+ level: high
468
+ test_events:
469
+ positive:
470
+ - eventSource: s3.amazonaws.com
471
+ eventName: PutBucketAcl
472
+ requestParameters.x-amz-acl: public-read
473
+ - eventSource: s3.amazonaws.com
474
+ eventName: DeleteBucketPublicAccessBlock
475
+ - eventSource: s3.amazonaws.com
476
+ eventName: PutBucketPublicAccessBlock
477
+ requestParameters.PublicAccessBlockConfiguration.BlockPublicAcls: true
478
+ requestParameters.PublicAccessBlockConfiguration.IgnorePublicAcls: true
479
+ requestParameters.PublicAccessBlockConfiguration.BlockPublicPolicy: false
480
+ requestParameters.PublicAccessBlockConfiguration.RestrictPublicBuckets: true
481
+ negative:
482
+ - eventSource: s3.amazonaws.com
483
+ eventName: PutBucketAcl
484
+ requestParameters.x-amz-acl: private
485
+ - eventSource: s3.amazonaws.com
486
+ eventName: PutBucketPublicAccessBlock
487
+ requestParameters.PublicAccessBlockConfiguration.BlockPublicAcls: true
488
+ requestParameters.PublicAccessBlockConfiguration.IgnorePublicAcls: true
489
+ requestParameters.PublicAccessBlockConfiguration.BlockPublicPolicy: true
490
+ requestParameters.PublicAccessBlockConfiguration.RestrictPublicBuckets: true
491
+
492
+ aws-s3-public-policy:
493
+ date: "2026-10-12"
494
+ title: "AWS S3 bucket policy with a wildcard principal"
495
+ description: >-
496
+ PutBucketPolicy with a statement whose principal is "*" (anyone).
497
+ AttackMap found publicly readable storage in ${locations} (rule
498
+ ${rule_id}). Flattened policy fields can't tie the principal to its
499
+ statement's effect, so a Deny statement with Principal "*" (the
500
+ common aws:SecureTransport guard) also matches; check the Effect.
501
+ logsource: {product: aws, service: cloudtrail}
502
+ fields_required: [eventSource, eventName, userIdentity.arn, requestParameters.bucketName, requestParameters.bucketPolicy.Statement.Principal, requestParameters.bucketPolicy.Statement.Principal.AWS, requestParameters.bucketPolicy.Statement.Effect]
503
+ detection:
504
+ selection:
505
+ eventSource: s3.amazonaws.com
506
+ eventName: PutBucketPolicy
507
+ wildcard_principal:
508
+ - requestParameters.bucketPolicy.Statement.Principal|re: ^\*$
509
+ - requestParameters.bucketPolicy.Statement.Principal.AWS|re: ^\*$
510
+ condition: selection and wildcard_principal
511
+ falsepositives:
512
+ - Deny statements with Principal "*" (for example requiring TLS); review the policy's Allow statements
513
+ - Static-website buckets that are public by design
514
+ level: medium
515
+ test_events:
516
+ positive:
517
+ - eventSource: s3.amazonaws.com
518
+ eventName: PutBucketPolicy
519
+ requestParameters.bucketPolicy.Statement.Principal: "*"
520
+ requestParameters.bucketPolicy.Statement.Effect: Allow
521
+ negative:
522
+ - eventSource: s3.amazonaws.com
523
+ eventName: PutBucketPolicy
524
+ requestParameters.bucketPolicy.Statement.Principal.AWS: arn:aws:iam::123456789012:role/reader
525
+
526
+ aws-eks-public-endpoint:
527
+ date: "2026-10-12"
528
+ title: "AWS EKS cluster API endpoint made public"
529
+ description: >-
530
+ An EKS cluster is reconfigured with endpointPublicAccess true, or
531
+ created without endpointPublicAccess false (the API endpoint is public
532
+ by default). AttackMap found public cluster endpoints in ${locations}
533
+ (rule ${rule_id}).
534
+ logsource: {product: aws, service: cloudtrail}
535
+ fields_required: [eventSource, eventName, userIdentity.arn, requestParameters.name, requestParameters.resourcesVpcConfig.endpointPublicAccess, requestParameters.resourcesVpcConfig.publicAccessCidrs]
536
+ detection:
537
+ selection_eks:
538
+ eventSource: eks.amazonaws.com
539
+ made_public:
540
+ eventName: [CreateCluster, UpdateClusterConfig]
541
+ requestParameters.resourcesVpcConfig.endpointPublicAccess: true
542
+ public_by_default:
543
+ eventName: CreateCluster
544
+ requestParameters.resourcesVpcConfig.endpointPublicAccess: null
545
+ condition: selection_eks and (made_public or public_by_default)
546
+ falsepositives:
547
+ - Clusters with a public endpoint restricted by publicAccessCidrs; check the CIDRs
548
+ level: medium
549
+ test_events:
550
+ positive:
551
+ - eventSource: eks.amazonaws.com
552
+ eventName: UpdateClusterConfig
553
+ requestParameters.resourcesVpcConfig.endpointPublicAccess: true
554
+ - eventSource: eks.amazonaws.com
555
+ eventName: CreateCluster
556
+ requestParameters.name: main
557
+ negative:
558
+ - eventSource: eks.amazonaws.com
559
+ eventName: UpdateClusterConfig
560
+ requestParameters.resourcesVpcConfig.endpointPublicAccess: false
561
+ - eventSource: eks.amazonaws.com
562
+ eventName: CreateCluster
563
+ requestParameters.resourcesVpcConfig.endpointPublicAccess: false
564
+ - eventSource: eks.amazonaws.com
565
+ eventName: UpdateClusterConfig
566
+ requestParameters.name: main
567
+
568
+ data:
569
+ # Rule id -> the templates that detect it. `platforms` limits a template to
570
+ # records on those platforms; `resource_types` (AWS) to Terraform resource
571
+ # types (the part of `resource` before the first dot). Kinds with no entry
572
+ # (unencrypted storage, unpinned images, Dockerfile issues, missing
573
+ # security contexts, ...) have no control-plane event to watch; the
574
+ # coverage table shows them as not covered. Launch templates and launch
575
+ # configurations are left out: their public-IP flag isn't in RunInstances'
576
+ # request, and their own create calls aren't mapped yet.
577
+ mapping:
578
+ privileged-container:
579
+ - {template: k8s-privileged-workload, platforms: [kubernetes, helm]}
580
+ privilege-escalation-allowed:
581
+ - {template: k8s-privilege-escalation-workload, platforms: [kubernetes, helm]}
582
+ dangerous-capability:
583
+ - {template: k8s-privilege-escalation-workload, platforms: [kubernetes, helm]}
584
+ host-path-mount:
585
+ - {template: k8s-host-access-workload, platforms: [kubernetes, helm]}
586
+ host-namespace-shared:
587
+ - {template: k8s-host-access-workload, platforms: [kubernetes, helm]}
588
+ exposed-service:
589
+ - {template: k8s-exposed-service, platforms: [kubernetes, helm]}
590
+ rbac-wildcard:
591
+ - {template: k8s-rbac-wildcard-grant, platforms: [kubernetes, helm, terraform]}
592
+ - {template: k8s-pod-exec, platforms: [kubernetes, helm, terraform]}
593
+ rbac-escalation:
594
+ - {template: k8s-rbac-escalation-grant, platforms: [kubernetes, helm, terraform]}
595
+ - {template: k8s-pod-exec, platforms: [kubernetes, helm, terraform]}
596
+ cluster-admin-binding:
597
+ - {template: k8s-cluster-admin-binding, platforms: [kubernetes, helm, terraform]}
598
+ rbac-secret-access:
599
+ - {template: k8s-secret-enumeration, platforms: [kubernetes, helm, terraform]}
600
+ public-network-access:
601
+ - {template: aws-security-group-open-ingress, platforms: [aws], resource_types: [aws_security_group, aws_security_group_rule, aws_vpc_security_group_ingress_rule]}
602
+ - {template: aws-rds-publicly-accessible, platforms: [aws], resource_types: [aws_db_instance, aws_rds_cluster, aws_rds_cluster_instance]}
603
+ - {template: aws-instance-public-ip, platforms: [aws], resource_types: [aws_instance]}
604
+ public-data-access:
605
+ - {template: aws-s3-made-public, platforms: [aws], resource_types: [aws_s3_bucket, aws_s3_bucket_acl, aws_s3_bucket_public_access_block, aws_s3_account_public_access_block]}
606
+ - {template: aws-s3-public-policy, platforms: [aws], resource_types: [aws_s3_bucket, aws_s3_bucket_policy]}
607
+ - {template: aws-rds-publicly-accessible, platforms: [aws], resource_types: [aws_db_instance, aws_rds_cluster, aws_rds_cluster_instance]}
608
+ public-cluster-endpoint:
609
+ - {template: aws-eks-public-endpoint, platforms: [aws], resource_types: [aws_eks_cluster]}