Skip to content

PII Masking Examples

Basic PII Masking

from agent_airlock import Airlock, AirlockConfig

config = AirlockConfig(
    sanitize_output=True,
    mask_pii=True,
)

@Airlock(config=config)
def get_customer(id: int) -> dict:
    return {
        "id": id,
        "name": "John Doe",
        "email": "john@example.com",
        "phone": "555-123-4567",
        "ssn": "123-45-6789",
    }

result = get_customer(id=123)
# {
#     "id": 123,
#     "name": "John Doe",
#     "email": "[EMAIL REDACTED]",
#     "phone": "[PHONE REDACTED]",
#     "ssn": "[SSN REDACTED]"
# }

Secret Masking

from agent_airlock import Airlock, AirlockConfig

config = AirlockConfig(
    sanitize_output=True,
    mask_secrets=True,
)

@Airlock(config=config)
def get_config() -> dict:
    return {
        "api_key": "sk-1234567890abcdef",
        "aws_key": "AKIA1234567890EXAMPLE",
        "db_url": "postgres://user:pass@localhost/db",
        "jwt": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.xxx",
    }

result = get_config()
# {
#     "api_key": "[API_KEY REDACTED]",
#     "aws_key": "[AWS_KEY REDACTED]",
#     "db_url": "[CONNECTION_STRING REDACTED]",
#     "jwt": "[JWT REDACTED]"
# }

Masking Strategies

from agent_airlock import Airlock, AirlockConfig, MaskingStrategy

# Full redaction
config_full = AirlockConfig(
    sanitize_output=True,
    mask_pii=True,
    masking_strategy=MaskingStrategy.FULL,
)
# john@example.com → [EMAIL REDACTED]

# Partial masking
config_partial = AirlockConfig(
    sanitize_output=True,
    mask_pii=True,
    masking_strategy=MaskingStrategy.PARTIAL,
)
# john@example.com → j***@e***.com

# Type only
config_type = AirlockConfig(
    sanitize_output=True,
    mask_pii=True,
    masking_strategy=MaskingStrategy.TYPE_ONLY,
)
# john@example.com → [EMAIL]

# Hash (for correlation)
config_hash = AirlockConfig(
    sanitize_output=True,
    mask_pii=True,
    masking_strategy=MaskingStrategy.HASH,
)
# john@example.com → [EMAIL:a1b2c3d4]

Selective Type Masking

from agent_airlock import Airlock, AirlockConfig, SensitiveDataType

# Only mask specific types
config = AirlockConfig(
    sanitize_output=True,
    enabled_types=[
        SensitiveDataType.SSN,
        SensitiveDataType.CREDIT_CARD,
    ],
)

@Airlock(config=config)
def get_data() -> dict:
    return {
        "email": "john@example.com",    # NOT masked
        "ssn": "123-45-6789",           # Masked
        "card": "4111111111111111",     # Masked
    }

# Disable specific types
config2 = AirlockConfig(
    sanitize_output=True,
    mask_pii=True,
    disabled_types=[
        SensitiveDataType.IP_ADDRESS,   # Don't mask IPs
    ],
)

Workspace-Specific Rules

from agent_airlock import (
    WorkspacePIIConfig,
    sanitize_with_workspace_config,
)

# Enterprise workspace - allow internal emails
enterprise = WorkspacePIIConfig(
    workspace_id="acme-corp",
    allow_email_domains=["acme.com", "acme.internal"],
)

content = "Contact alice@acme.com or bob@gmail.com"
result = sanitize_with_workspace_config(content, enterprise)
# "Contact alice@acme.com or [EMAIL REDACTED]"

# Sales workspace - mask competitor emails
sales = WorkspacePIIConfig(
    workspace_id="sales",
    mask_email_domains=["competitor1.com", "competitor2.com"],
)

content = "Lead: prospect@company.com, Spy: mole@competitor1.com"
result = sanitize_with_workspace_config(content, sales)
# "Lead: prospect@company.com, Spy: [EMAIL REDACTED]"

Phone Number Filtering

from agent_airlock import WorkspacePIIConfig, sanitize_with_workspace_config

config = WorkspacePIIConfig(
    workspace_id="support",
    allow_phone_prefixes=["+1800", "1800", "+1888", "1888"],
)

content = """
Toll-free: 1-800-555-1234 (keep visible)
Personal: 555-123-4567 (mask this)
Support: +1888-555-9999 (keep visible)
"""

result = sanitize_with_workspace_config(content, config)
# Toll-free numbers preserved, personal masked

Custom Patterns

from agent_airlock import WorkspacePIIConfig, MaskingStrategy

config = WorkspacePIIConfig(
    workspace_id="hr-department",
    custom_patterns={
        "employee_id": r"EMP-\d{6}",
        "badge_number": r"BADGE-[A-Z]{2}\d{4}",
        "salary": r"\$\d{1,3}(?:,\d{3})*(?:\.\d{2})?",
    },
    custom_strategies={
        "employee_id": MaskingStrategy.TYPE_ONLY,
        "salary": MaskingStrategy.FULL,
    },
)

content = """
Employee: EMP-123456
Badge: BADGE-AB1234
Salary: $85,000.00
"""

result = sanitize_with_workspace_config(content, config)
# Employee: [employee_id]
# Badge: [badge_number]
# Salary: [salary REDACTED]

Streaming Sanitization

from agent_airlock import StreamingAirlock, AirlockConfig

config = AirlockConfig(
    sanitize_output=True,
    mask_pii=True,
    max_output_chars=1000,
)

streaming = StreamingAirlock(config)

def generate_report():
    yield "Customer: john@example.com\n"
    yield "Phone: 555-123-4567\n"
    yield "SSN: 123-45-6789\n"

for chunk in streaming.wrap_generator(generate_report()):
    print(chunk, end="")
# Customer: [EMAIL REDACTED]
# Phone: [PHONE REDACTED]
# SSN: [SSN REDACTED]

print(f"\nTruncated: {streaming.state.was_truncated}")

Direct Sanitization

from agent_airlock import sanitize_output

content = """
User data:
- Email: john@example.com
- Phone: (555) 123-4567
- SSN: 123-45-6789
- API Key: sk-abcdef123456
"""

result = sanitize_output(
    content,
    mask_pii=True,
    mask_secrets=True,
)

print(result.content)
print(f"Detections: {result.detection_count}")

for detection in result.detections:
    print(f"  {detection.type}: {detection.original}{detection.masked}")