> ## Documentation Index
> Fetch the complete documentation index at: https://docs.declaw.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# SSN-specific redaction

> Verify that US Social Security Numbers in dashed format (123-45-6789) are properly redacted in outbound HTTP traffic.

## Use case

Regression probe for the custom Presidio `PatternRecognizer` registered
for `US_SSN`. Presidio's built-in SSN recognizer scores bare dashed
format (`123-45-6789`) well below the default threshold, so Declaw
ships a custom recognizer that fires at a lower confidence. This
example uses httpbin.org/post as an echo mirror to verify that SSN
patterns are caught and redacted before reaching the upstream.

## What you'll learn

* Configuring `PIIConfig` with `rehydrate_response=False` so the echo
  response shows exactly what the upstream received
* Using httpbin.org/post as a zero-dependency mirror for redaction tests
* Verifying that SSN, email, and person-name PII types are all redacted

## Prerequisites

<Snippet file="snippets/env-setup.mdx" />

## Code walkthrough

Create a security policy with PII redaction enabled and rehydration
disabled. Rehydration must be off so the echoed response shows the
raw redacted tokens:

```python theme={null}
from declaw import (
    ALL_TRAFFIC,
    AuditConfig,
    NetworkPolicy,
    PIIConfig,
    Sandbox,
    SecurityPolicy,
)

POLICY = SecurityPolicy(
    pii=PIIConfig(
        enabled=True,
        types=["ssn", "email", "person_name", "credit_card", "phone"],
        action="redact",
        rehydrate_response=False,
    ),
    network=NetworkPolicy(
        allow_out=["httpbin.org"],
        deny_out=[ALL_TRAFFIC],
    ),
    audit=AuditConfig(enabled=True),
)
```

The probe script POSTs a JSON body containing an SSN, email, and name
to httpbin.org/post, which echoes the body back verbatim:

```python theme={null}
PROBE = """
import json, ssl, urllib.request

body = json.dumps({
    "ssn": "123-45-6789",
    "email": "alice@example.com",
    "name": "Alice Smith",
}).encode()

ctx = ssl._create_unverified_context()
r = urllib.request.urlopen(
    urllib.request.Request(
        "https://httpbin.org/post",
        data=body,
        headers={"Content-Type": "application/json"},
    ),
    timeout=15,
    context=ctx,
)
echoed = json.loads(r.read().decode())["json"]
print("DEST_SAW:", json.dumps(echoed))
"""
```

Run the probe inside a sandbox and check the echo:

```python theme={null}
sbx = Sandbox.create(template="python", timeout=120, security=POLICY)
try:
    sbx.files.write("/tmp/script.py", PROBE)
    r = sbx.commands.run("python3 /tmp/script.py", timeout=60)
    out = r.stdout or ""
finally:
    sbx.kill()
```

## Expected output

```
DEST_SAW: {"ssn": "[REDACTED_SSN]", "email": "[REDACTED_EMAIL]",
           "name": "[REDACTED_PERSON]"}

ssn_redacted=True, email_redacted=True, name_redacted=True
VERDICT  : PASS
```

All three identifiers are replaced with `[REDACTED_*]` tokens before
the request reaches httpbin. If the SSN passes through unredacted,
the probe exits with a non-zero code.

## Full source

See `cookbook/examples/pii-ssn-redaction/main.py` in the repo.
