Read-only security audit, live remediation, cost analysis, and a prod-bucket structure review for the Rulebook production account.
A read-only audit surfaced several critical exposures. Most were remediated live; a few items are scoped for follow-up by the engineering team.
The dangerous, internet-facing exposures (world-writable buckets, a public credential leak, no audit logging, no MFA) are closed. Human access is now centralised in IAM Identity Center (SSO) with MFA enforced — only one break-glass IAM admin remains. What's left is disciplined cleanup: a scoped service role for the app, a public RDS lockdown, and a prod-bucket restructure to fix the app's own data hygiene.
Severity-ranked. "Done" items were remediated live during the audit window.
| # | Finding | Severity | Action | Status |
|---|---|---|---|---|
| 1 | Public credential leak — *.env files (EMAIL + PASSWORD) anonymously downloadable from the public prod bucket | CRITICAL | Explicit public-read Deny on *.env; password rotation required | FIXED |
| 2 | World-writable prod buckets — Principal:"*" s3:* (read/write/delete) | CRITICAL | Reduced to s3:GetObject only | DONE |
| 3 | Wide-open security group — all ports 0–65535 to 0.0.0.0/0 | CRITICAL | Confirmed unattached → deleted | DONE |
| 4 | Prod RDS publicly accessible — Postgres reachable from the internet | CRITICAL | Needs DB connection source identified before SG lockdown | PENDING |
| 5 | No audit logging — zero CloudTrail anywhere | HIGH | Multi-region org-audit-trail + encrypted/versioned log bucket; log validation on | DONE |
| 6 | No MFA on any IAM user | HIGH | EnforceMFA attached to all users (deny-until-enrolled) | DONE |
| 7 | No password policy | HIGH | 14-char min, complexity, 90-day rotation, no reuse of last 5 | DONE |
| 8 | Over-privileged users (S3FullAccess etc.) | MEDIUM | DenyDestructiveActions on all non-admins; scoped down devops & dev users | DONE |
| 9 | App uses human admin keys as its service identity (leaked in chat) | MEDIUM | Scoped service role planned; rotate keys | PENDING |
EnforceMFA policy denies all actions without an MFA session — confirmed by it (correctly) blocking even an admin access-key call during the audit.The single most urgent finding. Closed during the audit; one follow-up remains on the team.
monthly_mail.env and weekly_mail.env sat at the root of stock-rulebook-prod, whose bucket policy grants Principal:"*" s3:GetObject on /*. Both files (containing EMAIL + PASSWORD) were anonymously downloadable — verified HTTP 200 — and had been since 2024/2025.
Deny s3:GetObject on *.env for all principals except the account.Pulled live from AWS Cost Explorer. ~50% of the bill is recoverable, with a zero-risk subset to start.
| Month | Total (incl. tax) | Note |
|---|---|---|
| Mar 2026 | $324.54 | |
| Apr 2026 | $300.84 | |
| May 2026 | $317.63 | |
| Jun 2026 | $376.07 | Breached $350 budget · ~$313 ex-tax |
| Jul (forecast) | ~$326 | Cost Explorer projection |
| Service | Jun $ | Driver |
|---|---|---|
| EC2 – Compute | $118.45 | 3 always-on instances, 0% commitment |
| ECS (Fargate) | $89.84 | prod backend workload |
| RDS | $36.38 | db.t3.small, ~4% CPU |
| VPC | $30.19 | 6 public IPv4 + data |
| EC2 – Other | $18.19 | EBS 158 GB + snapshots |
| ELB | $15.81 | 1 ALB |
| Action | Saved/mo | Risk |
|---|---|---|
| Compute Savings Plan (EC2 + Fargate) | ~$70 | 1-yr commit |
FileZilla_server t3.large → t3.micro (0.2% CPU) | ~$55 | none |
Core-PSR t4g.xlarge → t4g.large (verify 86% bursts) | ~$49 | low |
| Drop unused public IPv4 (of 6) | ~$11–18 | none |
| RDS Reserved Instance | ~$11 | 1-yr commit |
Monitoring t4g.small → t4g.micro | ~$6 | none |
stock-rulebook-prodThe app uses one public bucket as a junk drawer. This is a code/convention issue, not just housekeeping — and it's what hid the credential leak.
fee_* exchange schedules) sits beside logs/, api-logs/, assets/, demo/, evals/, feedback-tasks/.FTP_users/, Testing_FTP/, and a stock-rulebook-staging/ prefix — test/FTP/staging data living inside public prod.nasdaq_gemx/ + nasdaqgemx/, nasdaq_ise/ + nasdaqise/, nasdaq_mrx/ + nasdaqmrx/, nasdaq_phlx/ + nasdaqphlx// → wrong path concatenation on write.FTP_users/, Testing_FTP/ vs lowercase-snake elsewhere.V_1 (62 KB, unclear), the .env files.*.env + rotate the leaked password.…-data (private), …-assets (only this is public, via CloudFront OAC), …-logs (private + lifecycle expiry). Evict test/demo/FTP/staging from prod.What's done, what's owned by the team, and the priority order.
| Priority | Item | Owner | Status |
|---|---|---|---|
| NOW | Rotate the leaked email password (was world-readable) | Lead Eng | TODO |
| DAY 1 | Scoped rulebook-annotation-svc role; swap app creds off admin keys; re-enable MFA on admin; rotate admin keys | DevOps | TODO |
| DAY 1 | RDS public-access lockdown (identify connection source first) | DevOps | TODO |
| WEEK | Prod bucket restructure + fix key convention & path bug | App team | TODO |
| WEEK | Cost: zero-risk right-sizing (~$76/mo), then Savings Plan + RDS RI | DevOps | TODO |
| DONE | IAM Identity Center (SSO) migration — Developer/DevOps permission sets, 4 users assigned, MFA-always-required; all redundant IAM users deleted (only muhamdasim break-glass admin remains) | — | ✓ |
| DONE | RDS 30-day backups · S3 lifecycle + Object Lock on backups · CloudTrail · public-write removal · .env leak block · Developer read access broadened | — | ✓ |