The challenge
Arcata Cloud was four weeks from a public launch and a SOC 2 Type 1 audit. Their security posture had grown organically alongside the product over two years, fast iteration, "we'll fix it when we have time," all the things every Series B has done. The CTO wanted an outside team to find the gaps before the auditor did.
The launch deadline was non-negotiable. So was the SOC 2 timeline, the largest enterprise customer in their pipeline had it as a contractual prerequisite. Failing the audit would mean either delaying launch or losing the customer.
How we approached it
Two phases. First two weeks: comprehensive threat-model and audit across code, API, infrastructure, and identity. Last two weeks: prioritized fixes, we worked alongside their team in a shared Slack channel, pairing on the highest-severity findings.
The threat-model came first deliberately. About half of the audit findings traced back to assumptions surfaced in the workshop, assumptions nobody had ever written down, much less stress-tested.
What we shipped
Audit phase (weeks 1–2)
- Threat-modeling workshop with engineering. Full STRIDE pass on every key asset: user sessions, payment webhooks, admin API, audit logs, backup files.
- Application security audit. Manual review augmented with Semgrep custom rules; full coverage of authentication, authorization, and data-handling code paths.
- IaC audit using Checkov. Surfaced 47 misconfigurations across Terraform, over-permissive IAM, public S3 buckets, missing encryption-at-rest on three databases.
- Dependency scan with Trivy + npm audit. Identified 12 outdated dependencies with known CVEs.
- Secrets scan with Gitleaks. Found two leaked AWS keys in old commits (rotated immediately).
- 14-page security report formatted for the SOC 2 auditor's expected evidence shape.
Hardening phase (weeks 3–4)
- Two critical fixes shipped first. A hardcoded API key in the client bundle and a JWT signing secret weak enough to brute-force, both shipped within 48 hours of discovery.
- Secrets migration. All environment-variable secrets moved to HashiCorp Vault; runtime fetch with short-lived tokens.
- IAM least-privilege overhaul. 213 IAM policies tightened; admin role split into three role-specific personas; access reviews scheduled monthly.
- API hardening. Rate limits added to all authenticated endpoints; idempotency keys required on all state-changing operations.
- DevSecOps wiring. SAST (Semgrep) and IaC scan (Checkov) added to CI; dependency scan (Trivy) runs on every push to main.
Outcomes
- 26 findings total (2 critical, 7 high, 12 medium, 5 low).
- 100% of high and critical issues resolved before launch. Mediums and lows ticketed for the next quarter with named owners.
- 0 critical CVEs at public launch.
- SOC 2 Type 1 passed on first attempt with zero engineering-side observations. The auditor specifically called out the threat-model documentation as exceeding expectations.
- Internal team trained on the new patterns; recurring quarterly review cadence established.
- The enterprise customer signed.
What we'd repeat
The threat-modeling workshop was the highest-leverage hour of the engagement. About half of the audit findings traced back to assumptions surfaced in the workshop, assumptions that had never been written down, much less stress-tested. If we ran this engagement again in two weeks instead of four, we'd still spend the first day on threat-modeling.
The other lesson: prioritize ruthlessly. We resisted the temptation to fix everything; we shipped the criticals, the highs, and the medium-but-easy items. The mediums-but-hard items went into the backlog with named owners. Four weeks isn't enough to fix everything that's wrong, but it is enough to make sure nothing critical ships.