Skip to main content

What You’ll Learn

  • Creating TransformationRule entries with regex match and replace fields
  • Controlling direction with OUTBOUND, INBOUND, or BOTH
  • Using TransformationRule.apply() locally to verify regex matching before deploying
  • Using TransformationRule.applies_to() to check which directions a rule covers
  • Attaching rules to a SecurityPolicy at sandbox creation time

Prerequisites

  • Declaw instance running and DECLAW_API_KEY / DECLAW_DOMAIN set
pip install declaw python-dotenv

Code Walkthrough

This example is available in Python. TypeScript support coming soon.

1. Define transformation rules

Each TransformationRule takes a regex match pattern, a replace string, and a direction.
from declaw import Sandbox, SecurityPolicy, TransformationRule, TransformDirection

rules = [
    # Mask internal hostnames before requests leave the sandbox
    TransformationRule(
        match=r"internal\.company\.com",
        replace="api.example.com",
        direction="outbound",
    ),
    # Strip bearer tokens from inbound API responses
    TransformationRule(
        match=r"Bearer sk-[a-zA-Z0-9]+",
        replace="Bearer [MASKED]",
        direction="inbound",
    ),
    # Filter passwords in both directions
    TransformationRule(
        match=r"password=\w+",
        replace="password=[FILTERED]",
        direction="both",
    ),
]

2. Create a sandbox with the rules attached

sbx = Sandbox.create(
    template="base",
    timeout=300,
    security=SecurityPolicy(
        transformations=rules,
    ),
)
The proxy applies each rule to all matching traffic for the lifetime of the sandbox.

3. Transformation directions

DirectionBehaviour
OUTBOUNDApplied to traffic leaving the sandbox (requests to external APIs). Use this to mask internal hostnames, tokens, or other data before it reaches third-party services.
INBOUNDApplied to traffic entering the sandbox (responses from external APIs). Use this to strip or mask sensitive data in API responses before the sandboxed code sees it.
BOTHApplied in both directions. Use for patterns like passwords that should never appear in any traffic through the proxy.

4. Test rules locally with apply() and applies_to()

Before deploying, verify your regex patterns work as expected:
# TransformationRule.apply() runs the regex substitution locally
rule = TransformationRule(
    match=r"internal\.company\.com",
    replace="api.example.com",
    direction="outbound",
)

before = "Calling https://internal.company.com/api/v2/users to fetch data"
after = rule.apply(before)
# after -> "Calling https://api.example.com/api/v2/users to fetch data"
print(f"Before: {before}")
print(f"After:  {after}")

# TransformationRule.applies_to() checks direction filtering
print(rule.applies_to("outbound"))  # True
print(rule.applies_to("inbound"))   # False

5. Before/after examples for all three rules

RuleDirectionBeforeAfter
Hostname maskoutboundCalling https://internal.company.com/api/v2/usersCalling https://api.example.com/api/v2/users
Bearer tokeninboundAuthorization: Bearer sk-abc123XYZ789secretTokenAuthorization: Bearer [MASKED]
Password filterbothPOST /login?password=hunter2&user=admin HTTP/1.1POST /login?password=[FILTERED]&user=admin HTTP/1.1

6. Cleanup

sbx.kill()

Expected Output

============================================================
Declaw Transformation Rules Example
============================================================

--- Creating Sandbox with Transformation Rules ---
Sandbox created: sbx_abc123

Security policy applied:
  transformations: 3 rule(s)
    1. match='internal\\.company\\.com'  replace='api.example.com'  direction=outbound
    2. match='Bearer sk-[a-zA-Z0-9]+'  replace='Bearer [MASKED]'  direction=inbound
    3. match='password=\\w+'  replace='password=[FILTERED]'  direction=both

------------------------------------------------------------
Local Regex Matching Demo (TransformationRule.apply)
------------------------------------------------------------

  Rule:      match='internal\\.company\\.com'  replace='api.example.com'
  Direction: outbound
  Before:    Calling https://internal.company.com/api/v2/users to fetch data
  After:     Calling https://api.example.com/api/v2/users to fetch data

  Rule:      match='Bearer sk-[a-zA-Z0-9]+'  replace='Bearer [MASKED]'
  Direction: inbound
  Before:    Authorization: Bearer sk-abc123XYZ789secretToken
  After:     Authorization: Bearer [MASKED]

  Rule:      match='password=\\w+'  replace='password=[FILTERED]'
  Direction: both
  Before:    POST /login?password=hunter2&user=admin HTTP/1.1
  After:     POST /login?password=[FILTERED]&user=admin HTTP/1.1

--- Cleaning Up ---
Sandbox killed.

============================================================
Done!
============================================================