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

# Custom rules & RE2 safety

> Ad-hoc, tenant-defined content-safety rules

Any caller can attach ad-hoc rules to a single `/scan` call via `customRules`, using the same shape as a catalog entry minus the maintainer-only fields (`level`, `mandatory`, `defaultEnabled`). A tenant can also persist a reusable rule library with `jaasctl guardrails push`.

```json Example custom rule theme={null}
{
  "id": "custom:acme:no-internal-hostname",
  "name": "No internal hostname",
  "category": "SUPPLY_CHAIN",
  "severity": "WARN",
  "kind": "regex_file_scan",
  "config": {
    "scope": "all_files",
    "patterns": [{ "name": "host", "regex": "\\.acme\\.internal\\b" }]
  }
}
```

<Warning>
  **Two deliberate restrictions, both security boundaries.** A custom rule can only use an existing executor `kind` — it can never run arbitrary code, the same line Semgrep and gitleaks draw between "rule" and "engine." And its regex is compiled with [RE2](https://github.com/google/re2), not Python's `re` — guaranteed linear-time matching, so no caller-supplied pattern can trigger catastrophic backtracking (CWE-1333 / ReDoS). This means a custom pattern cannot use backreferences or lookaround (`(?=`, `(?!`, `(?<=`, `(?<!`); both `/validate-rule` and `/scan` reject such a pattern with a **400** rather than silently falling back to backtracking `re`. Catalog rules are unaffected — maintainer-reviewed before shipping, they keep using `re` and may use lookaround.
</Warning>

The guardrails service never persists a custom rule on its own — it validates and executes whatever arrives with a given request.
