Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

rules.json

One per engagement, at $HOME/.redactproxy/engagements/<name>/rules.json. It holds which detector categories are enabled and any custom block and allow entries.

Hand-editing is supported and the file is written to be self-documenting: every known category appears in it with its description and, where relevant, its warning. Run redactproxy rules validate afterwards.

Shape

{
  "categories": {
    "cloud.aws": {
      "enabled": true,
      "description": "AWS access key IDs (AKIA/ASIA-prefixed) and secret access keys ..."
    },
    "allowlist.wellknown_platforms": {
      "enabled": true,
      "description": "Exempts well-known public dev platforms (github.com, ...)",
      "warning": "Disabling this makes MORE get redacted, not less: ..."
    }
  },
  "block": [
    {
      "value": "XYZCorp",
      "regex": false,
      "note": "wizard 2026-09-05, customer name"
    },
    {
      "value": "xyzcorp-fixture.internal",
      "regex": false,
      "note": "wizard 2026-09-05, domain",
      "is_domain": true
    }
  ],
  "allow": [
    {
      "value": "mylab.internal",
      "regex": false,
      "note": "our own lab"
    }
  ]
}

categories

A map of category name to state.

FieldTypeMeaning
enabledboolwhether the detector runs
descriptionstringmaintained by redactproxy; edits are overwritten
warningstringpresent on the inverted allowlist.* categories

The map is reconciled against the running build every time redactproxy writes the file: missing categories are added with their defaults, and names the build does not recognize are dropped, with a note on stderr:

note: rules.json had a category "Cloud.AWS" this build doesn't recognize, so it
was dropped. If it was meant to match an existing category, check for a typo
(case matters) ...

Case matters. That note exists because a silently-reverted typo on a file whose whole premise is “safe to hand-edit” is exactly the trap worth flagging.

rules validate warns about unrecognized names without writing anything, which makes it the safe way to check an edit before it takes effect.

block and allow

Arrays of entries.

FieldTypeDefaultMeaning
valuestringrequiredthe literal string or regex
regexboolfalsetreat value as a regular expression
notestringomittedfree text explaining why the entry exists
is_domainboolomittedblock entries only; give the value structure-preserving domain treatment

Block entries match case-insensitively as a substring. Allow entries match the exact value only, case-insensitively.

An allow entry always overrides a block entry for the same value, with no exception. The CLI refuses to create such a pair; rules show flags one left over from a hand edit:

Block:
  - [string] "mylab.internal"  ⚠ has NO effect: an Allow entry for the same value always overrides Block

is_domain

{"value": "xyzcorp-fixture.internal", "regex": false, "is_domain": true}

Equivalent to rules block --domain. The value is treated as a real domain and tokenized with structure preserved, everywhere it appears: bare, as a subdomain, inside an email address, or in a URL. Without it, the entry is opaque text matched literally.

Give the base domain, no www. and no subdomain.

A hand-edited file gets no interactive warning, so a nonsensical is_domain (set on a URL by accident, say) is handled quietly rather than breaking anything: it falls back to an ordinary literal block value, and redactproxy logs a one-time warning at startup or reload:

level=WARN msg="block entry marked \"is_domain\" doesn't look like a real
domain; treating it as an ordinary literal block value instead" value=...

Regex entries

{"value": "10\\.42\\.\\d+\\.\\d+", "regex": true, "note": "customer VPN range"}

Go’s regexp syntax (RE2). Remember JSON string escaping: a regex backslash is written \\.

An invalid pattern fails rules validate, and on a live reload the proxy logs the error and keeps the previous rules active rather than starting to send unredacted traffic.

Concurrency

Every command that modifies the file does the whole load-modify-save cycle under a lock, so two concurrent rules commands cannot silently discard each other’s change. A running proxy takes the same lock when it reconciles categories at startup.

rules.json is not held open the way tokens.db is. It is polled every two seconds, so edits from any source reach a running proxy within a couple of seconds with no restart.

What is not in this file

  • Minted mappings live in tokens.db. See Tokens.
  • The upstream provider lives in upstream.txt, one bare URL and never a credential. See Other API providers.
  • Claude Code settings live in the working folder’s .claude/settings.local.json. See Configuring Claude Code.