full-lifecycle security lab
S.H.I.E.L.D. Identity Registry
A synthetic-PII "crown jewels" registry, built then really attacked, detected, forensicated, and governed, phase by phase, with evidence committed at every step. All data is fictional by design: 70 Marvel characters, fake SSNs, non-dialable phone numbers.
Owner's note: this project is explicitly "in the works." All 12 planned phases are done and the repo has had three further hardening sessions on top of that; even so, the risk register below lists real, currently-open items, on purpose. This page states status honestly rather than rounding up to "finished."
The problem
Most security portfolios show one discipline at a time — a pentest here, a SIEM rule there. This lab frames a full lifecycle around one small, realistic target instead: a REST registry holding "PII" for 70 fictional characters, standing in for an organization's crown-jewel identity data. The goal was to run every phase a real security engineer needs — build, secure, attack, detect, respond, govern — on a system I actually control, and commit the evidence for each phase rather than describe it after the fact.
The approach
FastAPI + PostgreSQL registry API, Keycloak for OIDC/RBAC (two roles: analyst read-with-redaction, director full access), Dockerized with segmented networks, TLS via mkcert, Terraform + LocalStack standing in for AWS S3 so there's no real cloud billing risk. An "AI tier" adds Presidio-based PII redaction and a local Ollama-backed RAG assistant over the same registry data.
- Build & secure: the registry API, RBAC, and infrastructure, containerized and network-segmented from the start.
- Attack: real IDOR walk and SQL injection scripts against the live API. A simple OR-based SQLi payload was blocked by RBAC redaction; a UNION-based one defeated it completely, an explicit lesson about not overgeneralizing from one blocked technique.
- Detect: 5 Sigma detection rules with CI-gated pytest assertions, 3 wired to a live Elastic stack (Elasticsearch/Kibana/Filebeat) and verified to fire against a live replay of the attacks above.
- Forensicate: a NIST 800-61 incident-response report plus real container memory forensics, including a documented finding that the textbook tool (Volatility3) doesn't apply cleanly to containers and a different approach was needed to recover a real SSN from live process memory.
- Purple-team replay: the red-team attacks re-run live against the running stack and scored against the detections honestly: 3 of 6 techniques fully detected, 1 partial, 2 with no coverage yet.
- Govern: a 12-item scored risk register (likelihood × impact) tracked to source evidence for every item, a Statement of Applicability, a DPIA, and a docker-bench-security hardening audit.
The AI-security track runs alongside: Presidio-based PII redaction on the retrieval side (so redacted text never reaches the model prompt for the lower-privilege role) plus an output-filter guardrail, then a quantified garak red-team pass (3 probe families, 767 base prompts / 1,536 generations) against the live assistant, and a small adversarial-ML exercise (ART) running both an evasion attack and a label-flipping poisoning run against a toy classifier trained on the registry data.
Tech stack
Key results
- The redaction-defeating UNION-based SQLi was found by the red-team phase and fixed with a parameterized query, then verified by re-running both the blocked and the successful payload.
- A public LocalStack S3 bucket leaking the full registry CSV was found, remediated (bucket-owner-enforced, public-access block, least-privilege IAM), and re-verified with a checkov re-scan (17 → 6 failing checks).
- The garak pass confirmed the retrieval-side PII redaction holds at adversarial scale: zero real SSN/phone values leaked across 1,536 generations, while still surfacing a narrow partial system-prompt leak in 8 outputs.
- Phase 11 added a full browser login flow (authorization-code + PKCE, signed session cookie) layered alongside the original API path without breaking it.
Known limitations, from the project's own risk register. The underlying IDOR (no per-record ownership check) is unfixed by design: only a rate limit was added, so a patient slow attacker can still walk the whole registry. Retrieval-side PII protection covers only the two fields ever treated as role-gated (SSN, phone); other fields aren't redacted for the lower-privilege role. Two of five Sigma rules aren't wired to a live log source yet. The garak pass tested 3 of garak's ~30+ probe families, one role, capped variants. It's bounded on purpose, not exhaustive, and the project's own report says not to cite it as proof of safety against everything.