Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- **feat(guardrails):** per-type PII selection, custom masking patterns (ReDoS-gated) and detection counters for the opt-in PII masking ([#16902](https://github.com/diegosouzapw/OmniRoute/pull/16902)) — thanks @lsilveirab39
86 changes: 86 additions & 0 deletions docs/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3446,6 +3446,92 @@ paths:
"200":
description: Updated IP filter configuration

/api/settings/pii:
get:
tags: [Settings]
summary: Get PII masking settings
description: |
Returns the opt-in flag state (`PII_REDACTION_ENABLED`, `PII_RESPONSE_SANITIZATION`),
the per-type selection (`enabledTypes`, `null` = all built-in types), the custom
patterns and in-memory detection counters (counts only, never matched values).
responses:
"200":
description: PII masking settings
put:
tags: [Settings]
summary: Update PII masking settings
description: |
Replaces the per-type selection and/or the custom pattern list. Custom regex patterns
that fail the safe-regex (catastrophic backtracking) check, do not compile, or match an
empty string are refused with 400. Does not turn masking on.
requestBody:
required: true
content:
application/json:
schema:
type: object
additionalProperties: false
properties:
enabledTypes:
type: array
nullable: true
items:
type: string
customPatterns:
type: array
maxItems: 20
items:
type: object
required: [id, name, type, pattern]
properties:
id:
type: string
name:
type: string
type:
type: string
enum: [regex, wildcard]
pattern:
type: string
maxLength: 500
flags:
type: string
enabled:
type: boolean
responses:
"200":
description: Updated PII masking settings
"400":
description: Validation failed (including an unsafe pattern)

/api/settings/pii/test:
post:
tags: [Settings]
summary: Test a custom PII pattern
description: Dry-runs one pattern against a sample of at most 8 KB. Nothing is stored.
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [pattern, sampleText]
properties:
type:
type: string
enum: [regex, wildcard]
pattern:
type: string
flags:
type: string
sampleText:
type: string
responses:
"200":
description: Matches and a redacted preview
"400":
description: Invalid body, oversized sample or unsafe pattern

/api/settings/system-prompt:
get:
tags: [Settings]
Expand Down
36 changes: 36 additions & 0 deletions docs/security/GUARDRAILS.md
Original file line number Diff line number Diff line change
Expand Up @@ -666,6 +666,42 @@ Runs on **both** stages.
The guardrail never blocks; it only annotates (`meta.detections`,
`meta.redacted`) or rewrites.

#### Per-type selection, custom patterns and detection counters

**Dashboard → Settings → Security → PII masking** chooses _what_ is masked. It
does not switch masking on: that is still `PII_REDACTION_ENABLED` (request) and
`PII_RESPONSE_SANITIZATION` (response + SSE), both off by default.

- **Per-type selection** — the built-in ids are listed in
`src/shared/constants/piiTypes.ts` (`PII_BUILTIN_TYPES`). Unset means every
type (the behaviour before this setting existed). The request engine's
`ssn_us` pattern maps to `ssn`. Templates (Minimal, Standard, Financial,
Brazilian, USA, Full) only fill the checkboxes in the UI.
- **Custom patterns** — up to 20 regex or wildcard patterns (`*` = up to 64
non-whitespace characters, `?` = one). Matches become `[CUSTOM_REDACTED]`.
Every pattern goes through `compilePiiCustomPattern()`
(`src/shared/utils/piiCustomPatterns.ts`): at most 500 characters, flags limited
to `g i m s u`, must compile, must pass `safe-regex` (catastrophic
backtracking), and must not match an empty string or a redaction placeholder.
A pattern that fails is refused when saved and when tested, and a stored row
that fails is skipped at runtime instead of being compiled. Custom patterns only
run while masking is on.
- **Detection counters** — per-type counts (never matched values), held in
memory and reset on restart (`src/lib/pii/piiDetectionStats.ts`). They only
increase while masking is on.

The settings live in the `key_value` table (namespace `pii_settings`,
`src/lib/db/piiSettings.ts`) and are read through a 1 s cache. API:

| Method | Path | Purpose |
| ------ | ------------------------ | ----------------------------------------------------------------------- |
| `GET` | `/api/settings/pii` | Flag state, `enabledTypes`, `customPatterns`, detection counters |
| `PUT` | `/api/settings/pii` | Replace `enabledTypes` (`null` = all) and/or `customPatterns` |
| `POST` | `/api/settings/pii/test` | Dry-run one pattern against a sample of at most 8 KB; nothing is stored |

All three require management auth and validate the body with Zod
(`src/shared/validation/schemas/piiSettings.ts`).

### Prompt Injection (`promptInjection.ts`)

Detects adversarial structures in user-supplied content and enforces the
Expand Down
3 changes: 3 additions & 0 deletions skills/omni-settings/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ All requests require a valid Bearer token or session cookie. Obtain a token via
- [`POST /api/settings/require-login`](references/endpoints.md#post-apisettingsrequire-login)
- [`GET /api/settings/ip-filter`](references/endpoints.md#get-apisettingsip-filter)
- [`PUT /api/settings/ip-filter`](references/endpoints.md#put-apisettingsip-filter)
- [`GET /api/settings/pii`](references/endpoints.md#get-apisettingspii)
- [`PUT /api/settings/pii`](references/endpoints.md#put-apisettingspii)
- [`POST /api/settings/pii/test`](references/endpoints.md#post-apisettingspiitest)
- [`GET /api/settings/system-prompt`](references/endpoints.md#get-apisettingssystem-prompt)
- [`PUT /api/settings/system-prompt`](references/endpoints.md#put-apisettingssystem-prompt)
- [`GET /api/settings/thinking-budget`](references/endpoints.md#get-apisettingsthinking-budget)
Expand Down
46 changes: 46 additions & 0 deletions skills/omni-settings/references/endpoints.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@
- [`POST /api/settings/require-login`](#post-apisettingsrequire-login)
- [`GET /api/settings/ip-filter`](#get-apisettingsip-filter)
- [`PUT /api/settings/ip-filter`](#put-apisettingsip-filter)
- [`GET /api/settings/pii`](#get-apisettingspii)
- [`PUT /api/settings/pii`](#put-apisettingspii)
- [`POST /api/settings/pii/test`](#post-apisettingspiitest)
- [`GET /api/settings/system-prompt`](#get-apisettingssystem-prompt)
- [`PUT /api/settings/system-prompt`](#put-apisettingssystem-prompt)
- [`GET /api/settings/thinking-budget`](#get-apisettingsthinking-budget)
Expand Down Expand Up @@ -420,6 +423,49 @@ curl -X PUT http://localhost:20128/api/settings/ip-filter \
-d '{}'
```

### GET /api/settings/pii

Get PII masking settings

Returns the opt-in flag state (`PII_REDACTION_ENABLED`, `PII_RESPONSE_SANITIZATION`),
the per-type selection (`enabledTypes`, `null` = all built-in types), the custom
patterns and in-memory detection counters (counts only, never matched values).


```bash
curl http://localhost:20128/api/settings/pii \
-H "Authorization: Bearer $OMNIROUTE_TOKEN"
```

### PUT /api/settings/pii

Update PII masking settings

Replaces the per-type selection and/or the custom pattern list. Custom regex patterns
that fail the safe-regex (catastrophic backtracking) check, do not compile, or match an
empty string are refused with 400. Does not turn masking on.


```bash
curl -X PUT http://localhost:20128/api/settings/pii \
-H "Authorization: Bearer $OMNIROUTE_TOKEN" \
-H "Content-Type: application/json" \
-d '{}'
```

### POST /api/settings/pii/test

Test a custom PII pattern

Dry-runs one pattern against a sample of at most 8 KB. Nothing is stored.

```bash
curl -X POST http://localhost:20128/api/settings/pii/test \
-H "Authorization: Bearer $OMNIROUTE_TOKEN" \
-H "Content-Type: application/json" \
-d '{}'
```

### GET /api/settings/system-prompt

Get system prompt configuration
Expand Down
Loading
Loading