A World-Readable Billing Bucket and a CI/CD Key With AdministratorAccess
A researcher emails your public security@ alias: the bucket acme-prod-billing-exports is world-readable and contains about 40,000 PDF invoices from the past eight months. You confirm it. CloudTrail is enabled with default 90-day retention; S3 server access logging is off. GuardDuty has raised anomalous-behaviour findings for an access key belonging to a CI/CD service account, which holds AdministratorAccess through a group. The same key is used by build jobs in three AWS accounts. This account is one of twelve in an organization. Legal asks whether notification is required. There is no CISO available and you are on call.
1. Give your containment sequence for the bucket and the key. Explain why you would not simply delete the key.
Read the worked answer
Sequence: stop the exposure, stop the credential, then look for what the actor built.
- Block Public Access at both the account and bucket level, and remove the offending bucket policy or ACL. This is reversible, takes seconds, and immediately closes the exposure. Fix cause after you fix exposure.
- Deactivate the access key rather than deleting it. Deactivation stops use instantly while keeping the key ID resolvable for correlation with CloudTrail and GuardDuty findings. Deleting destroys nothing forensically in CloudTrail (the ID persists in logs) but removes your ability to re-enable quickly if you discover it was a false positive, and it removes the clean 'when did it stop' timestamp. Deactivate now, delete after the investigation closes.
- Rotate the CI/CD secret in all three accounts, and move that pipeline to short-lived OIDC-based credentials so there is no long-lived key to steal again.
- Hunt for persistence created by the key before you finish containment:
CreateAccessKey,CreateUser,CreateLoginProfile,AttachUserPolicy, role trust-policy changes, new Lambda functions, new EC2 instances or launch templates, and any resource-policy change granting cross-account access. An identity with AdministratorAccess that has been used anomalously may already have a second identity. - Repeat step 1 across the other eleven accounts - the pattern that created a public bucket in one account usually exists in more.
The ordering principle: exposure and credential first (minutes), persistence second (hours), root-cause and policy third (days).
2. S3 access logging is off and CloudTrail S3 data events are likely not enabled. How do you determine whether the invoices were actually read, and what do you tell legal?
Read the worked answer
Be honest about the limit: you may not be able to prove reads at all, and the notification decision must not depend on proving them.
What you can still check:
- Whether CloudTrail data events for S3 were ever enabled on this trail (check the trail's event selectors). If they were, you have
GetObjectrecords. - AWS Config history for the bucket policy - the timestamp when public access was introduced narrows the exposure window.
- GuardDuty S3 protection findings, which sometimes flag anomalous object access patterns.
- VPC Flow Logs or an S3 gateway endpoint, if objects were fetched from inside the VPC.
- If the bucket sat behind CloudFront, the distribution's access logs.
- The researcher's own records, and any public index or cache that referenced the bucket.
What you should not do is treat LastModified or ETag values as evidence of reads - they are not.
Message to legal, stated plainly: the objects were publicly reachable for a period we can bound approximately, but anonymous reads are not logged and cannot be reconstructed; exposure must be assumed. That framing lets counsel apply the regulatory clock from the date of awareness rather than waiting for proof that will never arrive. Provide the count and data categories (names, addresses, amounts, possibly tax IDs) so they can judge severity.
3. Legal asks: do we have to notify, and who owns the misconfiguration? Frame the notification decision and the shared-responsibility question.
Read the worked answer
Notification framing (counsel decides; you supply the facts):
- The data categories are the trigger. Invoices with names, addresses, and amounts are personal data in most regimes; a public exposure of personal data generally starts a regulatory clock running from awareness, not from proof of access. In the EU/UK that is 72 hours.
- Provide counsel three facts: exposure window (bounded), data categories, and the fact that reads are unprovable. Let them decide on customers, regulators, and timeline; your job is to make the facts unambiguous and timestamped.
- Preserve the researcher's email and reply courteously with a single point of contact. Do not speculate about scope in writing before you have the facts.
- If the invoices include any payment instrument data, the card brands' rules add a separate obligation, and that is not counsel's call alone - it is the acquirer's.
Shared responsibility, stated correctly: AWS is responsible for the security of the cloud - the physical infrastructure, the hypervisor, managed-service internals. The customer is responsible for security in the cloud - bucket policy, ACLs, IAM, and enabling the logging that would have answered the question you just could not answer. A world-readable bucket is a customer-side control failure, full stop. Saying otherwise in a report will damage credibility with the regulator and the researcher alike.
Control gap worth naming: no S3 public-access guardrail at the organization level, no data-event logging, no automated public-bucket detection. That is the finding behind the finding.