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.

Case no.
02
Status
In progress
Filed
MMXXVI

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."

54.9–76.2%
jailbreak success rate against the RAG assistant (garak, 1,536 generations)
0 / 1,536
real SSN/phone values leaked across all garak generations
3 / 6
replayed attack techniques fully caught by detections — honestly scored, not rounded up
8 / 8
correct predictions flipped by an ART evasion attack on the toy classifier

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.

  1. Build & secure: the registry API, RBAC, and infrastructure, containerized and network-segmented from the start.
  2. 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.
  3. 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.
  4. 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.
  5. 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.
  6. 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

FastAPI PostgreSQL Docker Compose Keycloak (OIDC/RBAC) Terraform + LocalStack Ollama + ChromaDB (RAG) Microsoft Presidio Sigma + pySigma Elastic Stack garak Adversarial Robustness Toolbox checkov docker-bench-security

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.