← Back to Plugins
Integration

Privacy Proxy

Nora-0 By Nora-0 👁 11 views ▲ 0 votes

`privacy-proxy` is a runtime privacy protection plugin for OpenClaw.

GitHub

Configuration Example

"messagePlaceholderPolicy": "restore"

README

# Privacy Proxy

English | [简体中文](./README.zh-CN.md)

`privacy-proxy` is a runtime privacy protection plugin for OpenClaw.

Its purpose is not just to make logs look cleaner. It moves sensitive-data handling into the actual agent execution path:

1. Redact sensitive data before it reaches the model
2. Restore real values only for trusted tools and message actions
3. Restore or sanitize user-visible output based on policy
4. Sanitize content before it is written to `session.jsonl`
5. Sanitize content again before it is written to `MEMORY.md` or `memory/*.md`

If your goal is:

- the model should not see API keys, tokens, emails, phone numbers, or business IDs
- tools should still receive real values when they actually need them
- session and memory files should not persist raw secrets

then this plugin is built for that workflow.

## Verified Environment

The current documentation and validation results in this repository are based on:

- OpenClaw `2026.4.5`
- model `gpt-5.4`
- message channel `Discord`

## Use Cases

This plugin is useful when:

- user messages contain sensitive values directly
- environment variables are expanded into real values at runtime
- tool outputs are fed back into model context
- the agent needs real IDs, URLs, or tokens to execute tools
- you want end users to see real values, while keeping session and memory storage redacted

## What It Does

### 1. Redacts data before model execution

The plugin sanitizes model context before it is sent to the model.

Supported categories currently include:

- `secret`, such as API keys, bearer tokens, JWTs, bot tokens, and webhook secrets
- email addresses
- phone numbers
- payment card numbers
- national ID numbers
- structured business IDs such as `guildId`, `channelId`, `messageId`, and `userId`
- custom literals
- custom regex patterns
- explicit markers such as `PII[store_id]=123456789012345`

### 2. Restores real values only for allowed tools

This plugin does not restore real values for every tool by default.

The recommended model is:

- default to `passthrough`
- only restore for tools or message actions that truly require real values

That keeps unknown tools, external tools, and networked tools from receiving sensitive data by default.

### 3. Controls final user-visible output

The plugin supports four output modes:

- `restore`
- `scrub`
- `placeholder`
- `passthrough`

If you want "model sees redacted values, user sees real values", use:

```json
"messagePlaceholderPolicy": "restore"
```

### 4. Controls session persistence

The plugin sanitizes messages again before they are written to session history.

Common options:

- `placeholder`
- `scrub`
- `passthrough`

Recommended:

```json
"sessionPersistencePolicy": "placeholder"
```

### 5. Controls memory persistence

The plugin also protects writes performed through tools such as:

- `write`
- `edit`
- `apply_patch`

If the target file is:

- `MEMORY.md`
- `memory/*.md`

the content is sanitized again before persistence.

Recommended:

```json
"memoryPersistencePolicy": "scrub"
```

### 6. Supports explicit PII markers

Besides automatic detection, the plugin supports explicit marking:

```text
PII[store_id]=123456789012345
PII[api_key]=sk-test-1234567890abcdef
PII[url]="https://example.com/detail/76219040483288220"
```

This is useful when:

- your business-specific fields are not covered well by default heuristics
- you want to explicitly force a value into the reversible placeholder mapping

## How It Works

```text
user input / expanded config / tool output
  -> sanitize before model execution
  -> model only sees placeholders or scrubbed text
  -> restore real values for allowed tools and message actions
  -> restore or sanitize user-visible output based on policy
  -> sanitize before session persistence
  -> sanitize before memory persistence
```

Internally, this is not just a one-shot regex replacement. The plugin keeps reversible placeholder mappings for:

- real value -> placeholder
- placeholder -> real value

Those mappings are controlled by:

- `placeholderTtlMs`
- `maxEntries`

## Installation

### 1. Place the plugin in a local directory

Put this plugin in a path OpenClaw can access, for example:

```text
extensions/privacy-proxy
```

### 2. Register it in `openclaw.json`

The most common setup is a local path install:

```json
{
  "plugins": {
    "installs": {
      "privacy-proxy": {
        "source": "path",
        "sourcePath": "/path/to/extensions/privacy-proxy",
        "installPath": "/path/to/extensions/privacy-proxy"
      }
    },
    "entries": {
      "privacy-proxy": {
        "enabled": true,
        "config": {}
      }
    }
  }
}
```

### 3. Restart OpenClaw

After changing plugin code or configuration, restart OpenClaw so the new settings take effect.

## Recommended Configuration

The following config is a good starting point for most setups:

```json
{
  "plugins": {
    "entries": {
      "privacy-proxy": {
        "enabled": true,
        "config": {
          "debugToolRestore": false,
          "detectors": {
            "secret": true,
            "email": true,
            "phone": true,
            "identifier": true,
            "paymentCard": true,
            "nationalId": true
          },
          "customPatterns": [],
          "customLiterals": [],
          "placeholderTtlMs": 86400000,
          "maxEntries": 2048,
          "trace": {
            "enabled": false,
            "summaryOnly": true
          },
          "messagePlaceholderPolicy": "restore",
          "restoreDiscordOutboundMessages": true,
          "sessionPersistencePolicy": "placeholder",
          "memoryPersistencePolicy": "scrub",
          "defaultToolRestoreMode": "passthrough",
          "restoreAllowedTools": [
            "write",
            "edit",
            "apply_patch",
            "exec"
          ],
          "restorePassthroughTools": [],
          "restoreAllowedMessageActions": [
            "channel-info",
            "channel-list",
            "channel-create",
            "channel-edit",
            "channel-delete",
            "channel-move",
            "category-create",
            "category-edit",
            "category-delete"
          ],
          "identifierKeys": [],
          "unresolvedPlaceholderPolicy": "block"
        }
      }
    }
  }
}
```

This configuration gives you:

- model-side redaction
- allowlist-based restore for trusted tools
- restored user-visible replies
- placeholder-based session persistence
- scrubbed memory persistence

## Key Configuration Options

### `messagePlaceholderPolicy`

Controls the final user-visible message behavior.

Available values:

- `restore`
- `scrub`
- `placeholder`
- `passthrough`

Recommended:

```json
"messagePlaceholderPolicy": "restore"
```

### `sessionPersistencePolicy`

Controls how content is handled before writing to `session.jsonl`.

Available values:

- `placeholder`
- `scrub`
- `passthrough`

Recommended:

```json
"sessionPersistencePolicy": "placeholder"
```

### `memoryPersistencePolicy`

Controls how content is handled before writing to `MEMORY.md` and `memory/*.md`.

Available values:

- `scrub`
- `placeholder`
- `passthrough`

Recommended:

```json
"memoryPersistencePolicy": "scrub"
```

### `defaultToolRestoreMode`

Controls the default restore behavior for tool calls.

Available values:

- `restore`
- `passthrough`

Recommended:

```json
"defaultToolRestoreMode": "passthrough"
```

Then only opt in the tools or message actions that truly need real values.

### `restoreAllowedTools`

Allowlist of tools that may receive restored real values.

Typical examples:

- `write`
- `edit`
- `apply_patch`
- `exec`
- `browser`

### `restoreAllowedMessageActions`

Allowlist of message actions that may receive restored real values.

For Discord or channel-management use cases, common entries include:

- `channel-info`
- `channel-list`
- `channel-create`
- `channel-edit`
- `channel-delete`
- `channel-move`
- `category-create`
- `category-edit`
- `category-delete`

### `identifierKeys`

Adds custom structured ID keys.

Many common ID fields are already covered by default, such as:

- `guild_id`
- `channel_id`
- `thread_id`
- `user_id`
- `message_id`

If your business uses additional keys, extend them here:

```json
"identifierKeys": [
  "store_id",
  "merchant_id",
  "order_id"
]
```

### `restoreDiscordOutboundMessages`

This field is easy to misunderstand.

What it actually does:

- when the plugin receives a `message_sending` event with `metadata.channel === "discord"`
- it decides whether to apply final restore for that outbound Discord message

What it does not do:

- it does not patch OpenClaw's Discord extension for you
- it does not automatically wire Discord monitor direct-send flows into `message_sending`

In other words:

> This is a processing switch, not a wiring switch.

## Discord Direct Replies

This is the most important boundary to understand.

### What works with the plugin alone

If you only install this plugin, you still get:

- model-side redaction
- tool-side restore
- session and memory sanitization

### What does not automatically work with the plugin alone

This does not automatically guarantee:

- Discord monitor direct replies will show restored plaintext to end users

### Why

The plugin performs final user-visible restore in the `message_sending` hook.

If your OpenClaw Discord extension does not trigger `message_sending` before its final outbound send, then:

- enabling `restoreDiscordOutboundMessages` is not enough
- direct Discord monitor replies will not automatically gain restored plaintext output

### When source changes are required

If you want this behavior:

```text
Discord monitor sends a direct reply
  -> message passes through privacy-proxy's message_sending restore
  -> Discord user sees restored plaintext
```

then your OpenClaw Discord extension must explicitly wire its final send path into the existing `message_sending` and `mess

... (truncated)
integration

Comments

Sign in to leave a comment

Loading comments...