Six Weeks to Launch: What Ships, What Waits, What Blocks
You are the first security hire at a 40-engineer startup six weeks from launching a B2B analytics product on AWS. Production, staging, and developer sandboxes all live in one account. Developers have IAM users with long-lived access keys, and the CI system uses an access key that was committed to a private repository - it has been rotated once, after a scare. The Terraform state bucket has versioning but no encryption requirement and a bucket policy granting the whole account access. Root has no MFA.
A contractor's container image containing a .env file with a production database password was pushed to a public registry 11 days ago and pulled 200 times before it was deleted.
The board wants a SOC 2 Type II report within 12 months. The CTO's position is that "we'll fix it after launch," and the head of engineering wants nothing that slows deploys.
1. Pick the three changes you would make before launch and justify them by blast radius and reversibility.
Read the worked answer
1. Rotate the leaked database credential and check what it touched. This is not optional and has zero deploy cost. The password has been public for 11 days and pulled 200 times; assume it has been used. Rotate it now, then read database logs for the last 11 days for connections from unexpected sources, unusual query volumes, or schema enumeration. Blast radius: everything the credential could reach. Reversibility: trivially safe - a new password breaks nothing that is configured correctly, and anything that does break was a hidden dependency you needed to find anyway.
2. Enable root MFA and attach organization-level guardrails. Root without MFA plus a public-registry habit is a compounding risk. Set up an AWS Organization with a minimal set of service control policies: deny public S3 ACLs and policies, deny public ECR repositories, deny root user activity except break-glass. Blast radius: the whole estate, which is exactly why it must be centralized and not left to individual developers. Reversibility: an SCP can be detached in minutes, but a public bucket cannot be un-leaked.
3. Replace the CI access key with short-lived OIDC role assumption. Long-lived keys committed to source are the recurring root cause of your two previous scares. Blast radius: production deployment rights. Reversibility: moderate - run the new role in parallel before flipping, and keep the old key disabled rather than deleted for a week.
What waits: full multi-account separation and a landing zone. High value, larger lift, and it can follow launch behind the guardrails - provided it is on the register with a date and an owner.
2. How do you remove long-lived CI credentials without slowing deploys?
Read the worked answer
The engineering objection is about friction, so the answer has to be measurably frictionless - ideally the pipeline file changes once and developers change nothing.
Mechanism. Use the CI provider's OIDC integration to assume an IAM role. Scope the role's trust policy tightly: specific repository, specific branch or environment, specific workflow. Then scope the permissions: a deploy role for production that can update the specific services, and a separate read-only role for pull-request checks. No single role with * that every workflow shares.
Rollout that does not block anyone.
- Create the roles and a reference workflow first; do not touch existing pipelines.
- Migrate one non-production pipeline, run both auth paths side by side for a week.
- Move production, then disable - not delete - the old keys so a rollback takes one click.
- Delete after two clean weeks.
Close the source of the problem. Enable secret scanning with push protection on every repository, add a secret scanner to the pipeline, and add a pre-commit hook. The last key was committed and then rotated "after a scare" - without push protection the next one is a matter of time, whether or not this migration succeeds.
Measure it. Track deploy time before and after and report the number. If the CTO's objection was speed, evidence retires the objection better than argument does.
3. How do you decide what goes in the risk register versus what blocks launch, and how do you present that to a CTO who wants to ship?
Read the worked answer
Use one test: can this be exploited by someone outside the company, today, with no additional mistake? If yes, it blocks. If it requires a future mistake or insider access, it goes on the register with a date.
Blockers: the leaked credential (already exposed - treat as compromised until logs say otherwise), root without MFA, public ECR allowed. Each is externally reachable or already leaked, and each is cheap to fix. Blocking on cheap, high-impact items is defensible; blocking on expensive architecture is not, and it is what teaches leadership to route around you.
Register with owners and dates: shared production/dev account, no encryption requirement on the Terraform state bucket, no security review in the contractor workflow, no centralized logging. Each gets a named owner, a target quarter, and a stated risk in business terms.
Present it as a schedule, not a lecture. "These three ship in a week and remove the paths an attacker would actually use. These five are on a plan through Q2." Tie the register to SOC 2: shared production and dev, and missing logging, will both come up as findings, so fixing them is launch-adjacent work, not a distraction.
Document acceptance. If the CTO overrules a blocker, record it in writing with the residual risk stated plainly. Your job is to make the trade-off visible, not to pretend it is not happening.