Audit Findings Where the Severity Ranking Is Backwards
A security review of a 30-engineer company produces four findings. (1) Every application instance carries the same IAM role with s3:* on all buckets, including the bucket holding nightly database dumps. (2) Database passwords are baked into container images stored in a registry that any engineer can pull from. (3) All engineers hold administrator console access to the production account, using long-lived access keys, with no MFA enforced. (4) Production and staging share one cloud account and one VPC. The auditors rate finding 3 critical and finding 4 low, and the company has 30 days before a customer audit.
1. Rank the findings by actual risk and explain where the auditors' severity ranking is wrong.
Read the worked answer
Rank by exploitability times blast radius, not by how alarming the label sounds.
My order: 2, 3, 4, 1.
- (2) Credentials in images - highest. Anyone who can pull the image can read the production database password. That includes every engineer, any CI runner with registry access, and any leaked or misconfigured pull credential. The secret cannot be rotated without rebuilding and redeploying every image, so the practical response time to a leak is hours to days. This is a live credential in a widely readable artifact.
- (3) Long-lived admin keys, no MFA - critical, and the auditors are right about that one. But note why: it is not the console access alone, it is that a single phished or committed key yields durable, unphishable-by-MFA administrator access. Long-lived keys cannot be re-scoped after theft; they remain valid until someone notices.
- (4) Shared production and staging account - the ranking error. Calling this low is the mistake. It is not a direct exploit, so a checklist-driven review scores it low, but it destroys the boundary that makes every other control meaningful. Staging is where engineers experiment, where CI deploys freely, and where permissive roles accumulate. If staging and production share an account and a VPC, then a compromise or a careless script in staging is a production compromise. Findings 1 and 3 become far worse because of finding 4. This should be high.
- (1) Overbroad instance role - high, capped by (4). s3:* on all buckets from every instance means any SSRF or dependency exploit on any instance yields the database dumps. The mitigating factor is that it requires code execution on an instance rather than a pull.
The general principle to state: auditors often score findings independently. Real risk is correlated - the shared account is the multiplier that turns three medium findings into one systemic exposure.
2. Design the target identity and secrets model, and describe the migration steps from the current state.
Read the worked answer
Target model - three separate problems, three separate answers.
Workload identity:
- One role per workload, not one role for all instances. Scope S3 access to specific bucket prefixes and specific actions; add bucket-policy conditions so the dump bucket is readable only by the backup role, from a known network path.
- Remove every static access key. Workloads obtain short-lived credentials from the platform identity service. Short-lived credentials are the control that makes a leak survivable.
- Deny by default via service control policies at the account level, so a misconfigured role cannot grant itself broad access.
Secrets:
- Secrets live in a secrets manager with automatic rotation, injected at runtime as environment or file mounts, never baked into an image layer.
- The registry becomes immutable and scanning-gated: block pushes containing detected secrets, and use lifecycle rules to delete vulnerable image manifests from history.
- Databases get per-application users with least-privilege grants, so a leaked credential is not automatically a full-database credential.
Human identity:
- Federated single sign-on with enforced MFA; permission sets scoped to read-only by default.
- Production write access only through a break-glass role with an approval step, a time limit, and session logging. No standing administrator.
Migration steps, ordered by exploitability:
- Rotate the database passwords and purge affected images from the registry (including manifests in history). This is hours, not weeks, and it removes the live exposure.
- Move injection to runtime; add the CI secret scanner so the hole does not reopen.
- Replace long-lived keys with workload identity; find remaining keys by scanning access-key usage and disable anything unused for 90 days.
- Enforce MFA through policy, which takes effect on next sign-in.
- Separate accounts per environment, with centralised logging in a dedicated account. This is the long pole, so in the interim isolate the VPCs, split roles per environment, and remove any cross-environment trust.
3. You have 30 days. What do you do first, and how do you prove it worked rather than just closing the tickets?
Read the worked answer
Days 1–7: remove live credentials. Rotate database passwords and delete the affected images from the registry, including manifests and cached layers. Until this is done, everything else is decoration - the exposure is a working password in a readable artifact.
Days 1–14: kill the standing privilege. Replace long-lived keys with workload identity for the highest-traffic services, disable unused keys, and enforce MFA via policy. These are cheap, fast, and irreversible in the right direction.
Days 8–30: draw boundaries. Full account separation is a large migration. In 30 days, do the parts that actually bound the blast radius: separate roles and credentials per environment, remove cross-environment trust, restrict network paths between staging and production, and put service control policies in place at the account level. Move the dump bucket to its own account or at minimum its own tightly scoped role.
Proving it worked - evidence, not ticket status:
- Credential proof: a secret scan across the entire registry history returns zero findings, and a pipeline run attempting to bake a credential is blocked.
- Key proof: access-key usage telemetry shows no active long-lived keys for human or workload identities, and IAM Access Analyzer shows no external or unused-permission findings of the original kind.
- Boundary proof: an adversarial test - run from a staging instance's credentials, attempt to read the production dump bucket and reach the production database. It must fail on both counts. This is the test that demonstrates finding 4 is closed in substance rather than in an org chart.
- Privilege proof: a sample of engineers attempts a production write without break-glass and is denied, with the request logged and an approver recorded.
Say what is not done. Account separation will not fully land in 30 days. Tell the auditors and the customer the interim controls, the residual risk, and the dated plan - an honest gap with a boundary around it is far stronger than a claim that all four findings are closed.