Skip to content

DataFog/fogclaw

Repository files navigation

FogClaw

An OpenClaw plugin for PII detection and custom entity redaction, powered by DataFog.

FogClaw uses a dual-engine approach: battle-tested regex patterns for structured PII (emails, SSNs, credit cards, etc.) and GLiNER via ONNX for zero-shot named entity recognition — letting you redact not just PII but any custom terms, expressions, or entity types you define.

Features

  • Three-layer scanning — inbound prompts, tool results, and outbound messages are all scanned for PII before they cross trust boundaries
  • Automatic guardrail — flags sensitive data in inbound prompts (before_prompt_build) and instructs the agent to work with placeholders. The OpenClaw plugin API cannot rewrite inbound prompts, so this layer is advisory; for hard inbound enforcement, configure block actions and the before_agent_run gate stops the run before the model sees the message (requires plugins.entries.fogclaw.hooks.allowConversationAccess: true)
  • Tool result scanning — redacts PII in file reads, API responses, and web fetches before they enter the session transcript (tool_result_persist)
  • Outbound message scanning — last-chance gate that catches PII in agent replies before delivery to external channels (message_sending)
  • On-demand toolsfogclaw_scan, fogclaw_preview, and fogclaw_redact
  • Dual detection engine — regex for structured PII (<1ms), GLiNER for zero-shot NER (~50-200ms)
  • Custom entity types — define any entity label (e.g., "project codename", "competitor name") and GLiNER detects them with zero training
  • Configurable actions — per-entity-type behavior: redact, block, or warn
  • Per-entity confidence tuning — tighten or relax detection confidence by label
  • Policy allowlist — whitelist exact strings or regex patterns to skip enforcement on known-safe values
  • Policy preview — run a dry-run simulation before changing runtime policy
  • Multiple redaction strategiestoken, mask, or hash
  • Audit trail summary logging — optional structured action summaries without logging raw entity content
  • Graceful degradation — falls back to regex-only mode if GLiNER fails to load

Installation

# From the OpenClaw CLI
openclaw plugins install @datafog/fogclaw

# Or manually
git clone https://github.com/DataFog/fogclaw.git ~/.openclaw/extensions/fogclaw
cd ~/.openclaw/extensions/fogclaw
npm install
npm run build

Quick Start

GLiNER first-run setup (no extra steps)

FogClaw automatically downloads the GLiNER ONNX model on first run if it is not already cached locally, then reuses it for all later starts.

What happens on first scan:

  1. Tokenizers are downloaded (if needed).
  2. The first available ONNX file from Hugging Face is downloaded to the plugin's local model cache:
    • .../node_modules/@xenova/transformers/.cache/<model-repo>/onnx/<selected-model>.onnx
    • (This download can take a moment depending on network and selected model size.)
  3. GLiNER starts using local files, so later runs stay fast and offline-friendly.

If the download cannot be performed (network/firewall/auth), FogClaw safely falls back to regex-only mode and continues to protect common structured PII.

If your network requires Hugging Face authentication, export HF_TOKEN or HF_ACCESS_TOKEN before starting OpenClaw so model files can download.

  1. Copy the example config:
cp fogclaw.config.example.json fogclaw.config.json
  1. Edit fogclaw.config.json to your needs:
{
  "enabled": true,
  "guardrail_mode": "redact",
  "redactStrategy": "token",
  "model": "onnx-community/gliner_large-v2.1",
  "confidence_threshold": 0.5,
  "entityConfidenceThresholds": {
    "PERSON": 0.6,
    "ORGANIZATION": 0.7
  },
  "custom_entities": ["project codename", "competitor name"],
  "entityActions": {
    "SSN": "block",
    "CREDIT_CARD": "block",
    "EMAIL": "redact",
    "PHONE": "redact",
    "PERSON": "warn"
  },
  "allowlist": {
    "values": ["noreply@example.com"],
    "patterns": ["^internal-"],
    "entities": {
      "PERSON": ["john doe"]
    }
  },
  "auditEnabled": true
}
  1. Enable the plugin in your OpenClaw config and restart.

Submission Readiness Evidence (Recommended)

These commands are the minimum evidence set for PR review:

npm test
npm run build
npm run test:plugin-smoke
npm pkg get openclaw
npm run build
node - <<'NODE'
import plugin from './dist/index.js';
const result = plugin.register ? 'ok' : 'missing-register';
console.log(result, plugin.id, plugin.name);
NODE

Expected output:

  • All tests pass.
  • npm run build exits with 0 and writes dist/index.js.
  • npm run test:plugin-smoke passes and confirms hook/tool contracts.
  • npm pkg get openclaw shows {"extensions":["./dist/index.js"]}.
  • The inline node check prints ok fogclaw FogClaw.

How It Works

Incoming message
       |
       v
 +-----------+
 | Regex Pass |  emails, SSNs, phones, credit cards, IPs, dates, zips
 |  (<1ms)    |  confidence: 1.0
 +-----+-----+
       |
       v
 +-----------+
 | GLiNER    |  persons, orgs, locations + your custom entities
 |  (ONNX)   |  confidence: 0.0-1.0
 +-----------+
       |
       v
 +-----------+
 | Merge &   |  deduplicate overlapping spans, prefer higher confidence
 | Normalize |
 +-----------+
       |
       v
  Apply action per entity type (redact / block / warn)

Scanning Architecture

FogClaw hooks into the OpenClaw message lifecycle at every point where sensitive data can enter or leave. Each hook uses the detection engine best suited to its runtime constraints:

Hook Direction Engine Latency Entity Coverage
before_agent_run (block mode only) Inbound gate Regex + GLiNER ~50-200ms Full; stops the run when blocked entities are found. Requires hooks.allowConversationAccess: true
before_prompt_build Inbound (user prompt) Regex + GLiNER ~50-200ms Full detection; advisory — prepends guidance and a placeholder reference, but the plugin API cannot remove the original prompt
tool_result_persist Internal (tool results) Regex only <1ms Structured PII — emails, SSNs, phones, credit cards, IPs, secrets, tokens
message_sending Outbound (agent reply) Regex only <1ms Structured PII + secrets/tokens
reply_payload_sending Outbound (normalized payload, incl. media captions) Regex only <1ms Structured PII + secrets/tokens

Why regex-only on the hot paths? tool_result_persist requires synchronous handlers, and the outbound hooks sit on the delivery path where GLiNER's 100-500ms ONNX inference would delay every reply. Regex covers the high-confidence structured patterns most common in tool output and replies (credentials in file reads, contact info in API responses). Person names, organizations, and custom entities are caught on the async inbound path, providing defense-in-depth without hot-path latency.

User prompt ──► before_agent_run (block gate, when configured)
                        │
                        ▼
                before_prompt_build (regex + GLiNER)
                        │
                        ▼
                   Agent + LLM
                        │
              ┌─────────┼─────────┐
              ▼         ▼         ▼
         Tool call  Tool call  Tool call
              │         │         │
              ▼         ▼         ▼
     tool_result_persist (regex only, sync)
                        │
                        ▼
                   Agent reply
                        │
                        ▼
              message_sending ──► reply_payload_sending
                  (regex only)        (regex only)
                        │
                        ▼
                  External channel
              (Telegram, Slack, etc.)

Detected Entity Types

Regex Engine (structured PII)

Type Examples
EMAIL john@example.com, user+tag@example.co.uk
PHONE 555-123-4567, (555) 123-4567, +44 20 7946 0958
SSN 123-45-6789
CREDIT_CARD Visa, Mastercard, Amex (with/without separators)
IP_ADDRESS 192.168.1.1, 10.0.0.1
DATE 01/15/1990, 2020-01-15, January 15, 2000
ZIP_CODE 10001, 10001-1234

GLiNER Engine (zero-shot NER)

Built-in labels: person, organization, location, address, date of birth, medical record number, account number, passport number

Plus any labels you add via custom_entities in the config.

Redaction Strategies

Strategy Input Output
token Contact john@example.com Contact [EMAIL_1]
mask Contact john@example.com Contact ****************
hash Contact john@example.com Contact [EMAIL_a1b2c3d4e5f6]

Configuration

Option Type Default Description
enabled boolean true Enable/disable the plugin
guardrail_mode string "redact" Default action: "redact", "block", or "warn"
redactStrategy string "token" How to redact: "token", "mask", or "hash"
model string "onnx-community/gliner_large-v2.1" HuggingFace model path for GLiNER (or a local .onnx path for advanced setups).
confidence_threshold number 0.5 Minimum confidence for GLiNER detections (0-1)
entityConfidenceThresholds object {} Per-label confidence overrides, e.g. { "PERSON": 0.7, "ORGANIZATION": 0.85 }
custom_entities string[] [] Custom entity labels for zero-shot detection
entityActions object {} Per-entity-type action overrides
allowlist object {} Exception rules to skip enforcement via exact values or regex patterns
auditEnabled boolean true Emit structured audit logs for guardrail decisions

OpenClaw Tools

fogclaw_scan

Scan text for PII and custom entities. Returns detected entities with types, positions, and confidence scores.

Parameters:

  • text (required) — text to scan
  • custom_labels (optional) — additional entity labels for zero-shot detection

fogclaw_preview

Preview what the guardrail would do for a message.

Parameters:

  • text (required) — text to simulate
  • strategy (optional) — "token", "mask", or "hash" (defaults to config)
  • custom_labels (optional) — additional entity labels for zero-shot detection

Response:

  • entities: detected entities and metadata
  • totalEntities: total entities found
  • actionPlan: counts and labels grouped by blocked, warned, redacted
  • redactedText: message with only redacted entities applied

fogclaw_redact

Scan and redact PII/custom entities from text. Returns sanitized text with entities replaced.

Parameters:

  • text (required) — text to scan and redact
  • strategy (optional) — "token", "mask", or "hash" (defaults to config)
  • custom_labels (optional) — additional entity labels for zero-shot detection

Standalone Usage

FogClaw's core can also be used outside of OpenClaw:

import { Scanner, redact, loadConfig, DEFAULT_CONFIG } from "@datafog/fogclaw";

const scanner = new Scanner(DEFAULT_CONFIG);
await scanner.initialize();

// Scan for entities
const result = await scanner.scan("Contact john@example.com or call 555-123-4567");
console.log(result.entities);
// [
//   { text: "john@example.com", label: "EMAIL", start: 8, end: 24, confidence: 1, source: "regex" },
//   { text: "555-123-4567", label: "PHONE", start: 33, end: 45, confidence: 1, source: "regex" }
// ]

// Redact
const redacted = redact(result.text, result.entities, "token");
console.log(redacted.redacted_text);
// "Contact [EMAIL_1] or call [PHONE_1]"

Development

git clone https://github.com/DataFog/fogclaw.git
cd fogclaw
npm install
npm test          # run tests
npm run build     # compile TypeScript
npm run lint      # type-check without emitting

Security Notes

  • Keep api.logger output free of raw sensitive values.
  • Use allowlists and auditEnabled according to your governance requirements.
  • Consider block actions for high-risk entity types in regulated environments.

License

MIT

About

OpenClaw plugin for PII detection & custom entity redaction powered by DataFog

Resources

License

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors