▣ Dashcam

Single-skill workshop · Data protection

Dashcam — catch PII before it leaves the building

RoadWitness (fictional dashcam rideshare app) is about to hand four artifacts to a third-party LLM vendor and a staging environment. None of it has been through a PII scrub step. Find and de-identify what's in each, using the operator that matches where it's going.

Setup (do this once)

1. Open a terminal. 2. cd ~/dashcam. 3. Start the agent: claude. 4. Paste each prompt below, in order, in the same chat, so it remembers. Type only the prompt text — no quotes.

~15–20 min. Do the CORE phases (1, 2) for the main story. DEEP phases (3, 4) cover the reversible-masking and image-redaction cases — run them for the full skill, or save for later. No agent? Terminal fallback commands are at the bottom. Full setup: Setup page.

Phase 1 Core

Support tickets — free text and structured PII

Paste this, then Enter:

Using anonymizing-pii-with-microsoft-presidio, find the PII in data/support-tickets.json and de-identify it. This is going to a third-party LLM vendor for triage — one-way redaction, no need to reverse it. Show me what entity types you found and what operator you applied to each.

You will see: a Presidio AnalyzerEngine/BatchAnalyzerEngine run finding an SSN and a credit-card number pasted into ticket bodies, then redact/mask applied.

Checkpoint — on track when you see

The SSN 078-05-1120 in ticket RW-TICKET-10412 and the card number 4111 1111 1111 1111 in RW-TICKET-10413 both detected and redacted, plus the batch run covering all 4 ticket records, not just one.

Reveal the answer

analyzer.analyze() flags US_SSN and CREDIT_CARD (plus PERSON/EMAIL_ADDRESS on every ticket). Since this is a one-way hand-off to a vendor, the right operators are redact or mask, not encrypt — there's no need to reverse it.

Phase 2 Core

The vendor-handoff chat — a custom recognizer

Same chat:

Now check data/vendor-handoff-chat.txt — a Slack export about to be forwarded to the same vendor. Find every piece of PII in it, including anything Presidio's built-in recognizers would miss, and de-identify it.

You will see: an IBAN and an IP address caught by built-in recognizers, plus a driver ID (RW-DRV-048213) that Presidio does not know about out of the box.

Checkpoint — on track when you see

The agent notices RW-DRV-###### isn't a built-in entity and writes a PatternRecognizer for it (RW-DRV-\d{6}), rather than only catching the IBAN and IP and calling it done.

Reveal the answer

Built-ins catch GB29 NWBK 6016 1331 9268 19 (IBAN) and 203.0.113.44 (IP). The driver ID needs a custom Pattern(name="driver_id", regex=r"RW-DRV-\d{6}", score=0.85) registered as a PatternRecognizer — the point of this phase is noticing the gap, not just running the defaults.

Phase 3 Deep

Driver records — the reversible case

Same chat:

data/driver-records-export.json is going to a staging environment where QA needs to join it back to real records later. De-identify the PII, but pick the right operator for THAT destination, not the same one you used for the vendor hand-offs.

You will see: the agent choosing encrypt/decrypt with a key, not a one-way hash or redact, because staging QA needs a reversible mapping.

Checkpoint — on track when you see

An explicit reason for using OperatorConfig("encrypt", {"key": ...}) instead of redact/mask/hash — tied to "QA needs to join it back," not just "this file has PII too."

Reveal the answer

Every driver record's email, phone, and payout_iban get encrypted with a shared key; a DeanonymizeEngine call with the same key proves the round-trip. This is the one artifact in the set where a one-way operator would be the wrong answer.

Phase 4 Deep

The dashcam frame — image redaction

Same chat:

data/dashcam-frame-0417.png gets auto-uploaded to cloud storage after every trip. Use presidio-image-redactor to find and redact any PII burned into the image itself, then save a redacted copy.

You will see: OCR-based detection finding the driver name, plate number, phone, and driver ID printed on the trip-summary overlay burned into the frame, then a redacted image written to disk.

Checkpoint — on track when you see

The agent installs/uses ImageRedactorEngine specifically — not the text AnalyzerEngine/AnonymizerEngine from the earlier phases — since this is OCR-based image redaction, a different engine entirely.

Reveal the answer

ImageRedactorEngine().redact(image, fill) finds "Priya Nakamura," "7XKQ192," "212-555-0198," and "RW-DRV-048213" via OCR on the overlay card and paints over them, saving dashcam-frame-0417_redacted.png.

Terminal fallbacks (no agent)

Presidio installed locally (see Setup for the pip/venv steps):

python3 -c "
from presidio_analyzer import AnalyzerEngine
a = AnalyzerEngine()
print(a.analyze(text=open('data/vendor-handoff-chat.txt').read(), language='en'))
"

Authorized & lawful use only. All data is synthetic and self-contained; no live systems are touched. Promotes the open-source Anthropic Cybersecurity Skills library (Apache-2.0); not affiliated with Anthropic PBC or Microsoft. The headline skill, anonymizing-pii-with-microsoft-presidio, is from an open, unmerged PR against upstream (mukul975/Anthropic-Cybersecurity-Skills#141), vendored locally until it lands.