Finding Public Cloud Exposure with AI: S3 Buckets and IAM
Public buckets and over-broad IAM are the top cloud breach causes. Here's how I use AI to audit S3 policies and IAM grants for accidental public access and wildcard permissions.
- #security
- #hardening
- #aws
- #iam
- #ai
Almost every headline cloud breach comes down to two things: a storage bucket that was public when it shouldn’t have been, or an IAM permission that was broader than anyone intended. Neither requires a sophisticated attacker. They require someone, at some point, clicking “make public” to unblock a demo, or writing "Action": "*" because figuring out the exact permissions was tedious.
I’ve reviewed enough AWS accounts to know that finding these takes patience and a clear head, because the policy JSON is verbose and the logic — Allow vs Deny, explicit vs implicit, resource scoping — is fiddly. That’s precisely the kind of tedious, pattern-heavy review I now hand to AI. Strictly defensive: find the exposure so I can close it. Here’s how.
The two failure modes that cause breaches
Cloud exposure clusters tightly:
- Public S3 buckets —
Principal: "*"in a bucket policy, a public ACL, or Block Public Access turned off. - Wildcard IAM actions —
"Action": "*"or"s3:*"where a handful of specific actions would do. - Wildcard resources —
"Resource": "*"granting a permission across every resource in the account instead of one. - Missing condition keys — a grant that could be safe with an
aws:SourceIporaws:PrincipalOrgIDcondition but has none. - Confused-deputy gaps — cross-account trust policies without an
ExternalIdcondition.
These are all visible in JSON, but reading IAM JSON correctly is genuinely tiring, and tiredness is where the Resource: "*" slips past. The model doesn’t get tired.
Export policies for review — read-only, no secrets
Pull the policy documents and public-access status using read-only calls. None of this requires or should include credentials in the prompt:
# Bucket policy and public-access block status
aws s3api get-bucket-policy --bucket my-bucket --query Policy --output text
aws s3api get-public-access-block --bucket my-bucket
# A specific role's inline and attached policies
aws iam get-role-policy --role-name app-role --policy-name app-inline
aws iam list-attached-role-policies --role-name app-role
I feed the model the resulting policy JSON. The account ID I usually redact to a placeholder — the model reasons about structure, not your actual account number.
An IAM and S3 audit prompt
I scope the prompt to exposure and over-permission, and ask for ranked findings:
You are a cloud security auditor reviewing AWS IAM and S3 policy JSON.
Find security issues ONLY, ranked by severity:
1. Public access: any Principal "*" allow, public ACL, or disabled
Block Public Access on a bucket.
2. Wildcard actions: "*" or service-wide ("s3:*") grants that should
be a specific list of actions.
3. Wildcard resources: "Resource": "*" where the grant should target
specific ARNs.
4. Missing safety conditions: grants that should have aws:SourceIp,
aws:PrincipalOrgID, or (for cross-account trust) ExternalId.
5. Cross-account trust without an ExternalId (confused-deputy risk).
For each, name the statement, explain what it exposes, and give the
least-privilege alternative as a description (not full rewritten JSON).
<paste policy JSON, account ID redacted>
Run this against a typical “we’ll tighten it later” policy and the model immediately flags the combination that causes real damage:
{
"Effect": "Allow",
"Action": "s3:*",
"Resource": "*"
}
That single statement grants every S3 action on every bucket in the account. The model will recommend narrowing both the action list and the resource ARN — and importantly, it’ll explain that an explicit Deny elsewhere can still override an Allow, which is the kind of IAM nuance humans forget.
Pro Tip: Ask the model to evaluate the policy assuming the credential is already leaked: “If an attacker had this role’s keys, what could they reach?” That blast-radius framing turns an abstract Resource: "*" into a concrete, prioritized risk and makes it obvious which grants to tighten first.
Tighten toward least privilege
The fix is always the same shape — name the exact actions and the exact resources:
{
"Effect": "Allow",
"Action": ["s3:GetObject", "s3:PutObject"],
"Resource": "arn:aws:s3:::my-bucket/uploads/*"
}
And turn Block Public Access back on at the bucket and account level so a stray ACL can’t re-expose data:
aws s3api put-public-access-block --bucket my-bucket \
--public-access-block-configuration \
BlockPublicAcls=true,IgnorePublicAcls=true,\
BlockPublicPolicy=true,RestrictPublicBuckets=true
The AI proposes the least-privilege shape well, but I never apply a generated IAM policy without testing it against the workload — an over-tightened policy breaks the application, and IAM’s evaluation logic (explicit deny, permission boundaries, SCPs) can produce surprises. Verify, then apply.
Make exposure review continuous
Cloud config drifts daily as people ship. I fold this audit into the same continuous-review habit as everything else, the way our code review dashboard flags risky diffs — here, policy changes get audited before they land. This builds directly on least-privilege IAM policies with AI, which goes deeper on authoring tight grants from scratch. For the review I use Claude or ChatGPT with the prompt above.
Defensive, verified, and credential-free
The model is a fast junior cloud auditor: it parses verbose IAM JSON without fatigue and reliably catches the wildcard-action-plus-wildcard-resource combinations that cause breaches. But it can misjudge whether a broad grant is intentional, and it can be wrong about how SCPs or permission boundaries interact with a given policy — so I verify every tightening against the actual workload before applying. Above all, I never paste real access keys, secret keys, or session tokens into a prompt. Policy documents and redacted account IDs are all the model needs; the credentials never leave AWS.
Conclusion
Public buckets and wildcard IAM cause the breaches, and both come from a tired human skipping a tedious review. An AI auditor makes that review fast, repeatable, and blast-radius-aware — while you stay the human who tests the tightened policy, understands the deny logic, and keeps every real credential out of the prompt. Make it part of your standing security and hardening practice, backed by a reusable prompt library.
Download the Free 500-Prompt DevOps AI Toolkit
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.