Skip to content
Open
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
159 changes: 159 additions & 0 deletions community/middlewares/pii/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
# @community/middlewares-pii

PII (Personally Identifiable Information) detection and redaction middleware for XpertAI agents.

## Features

- **Built-in PII detectors**: SSN, email, phone numbers, credit card numbers, IP addresses
- **Custom detectors**: Define your own PII detection logic
- **Multiple redaction strategies**: Hash, mask, remove, or replace with custom text
- **Configurable detection scope**: Detect in user input, AI output, or both
- **State tracking**: Track PII detection counts by type

## Installation

```bash
pnpm add @community/middlewares-pii
```

## Usage

### Basic Usage with Built-in Detector

```typescript
import { createAgent } from '@xpert-ai/agent-sdk';
import { piiMiddleware } from '@community/middlewares-pii';

const agent = createAgent({
model: "gpt-4",
tools: [],
middleware: [
piiMiddleware({
piiType: "ssn",
strategy: "hash",
detectIn: ["both"],
}),
],
});
```

### Custom Detector Function

```typescript
function detectCustomPII(content: string): PiiMatch[] {
const matches: PiiMatch[] = [];
const pattern = /\b[A-Z]{2}\d{6}\b/g; // Example: AB123456 format
let match: RegExpExecArray | null;

while ((match = pattern.exec(content)) !== null) {
matches.push({
text: match[0],
start: match.index ?? 0,
end: (match.index ?? 0) + match[0].length,
type: "custom_id",
});
}
return matches;
}

const agent = createAgent({
model: "gpt-4",
tools: [],
middleware: [
piiMiddleware({
piiType: "custom",
detector: detectCustomPII,
strategy: "mask",
maskChar: "#",
maskLength: 3,
}),
],
});
```

### Configuration Options

| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `piiType` | `string` | `"custom"` | Type of PII to detect: `"ssn"`, `"email"`, `"phone"`, `"credit_card"`, `"ip_address"`, or `"custom"` |
| `detector` | `PiiDetector` | - | Custom detector function (required when `piiType` is `"custom"`) |
| `strategy` | `"hash" \| "mask" \| "remove" \| "replace"` | `"hash"` | Redaction strategy |
| `replacementText` | `string` | `"[REDACTED]"` | Text to use when strategy is `"replace"` |
| `maskChar` | `string` | `"*"` | Character to use for masking |
| `maskLength` | `number` | `4` | Number of characters to mask |
| `hashAlgorithm` | `"sha256" \| "sha1" \| "md5"` | `"sha256"` | Hash algorithm for hash strategy |
| `detectIn` | `Array<"input" \| "output" \| "both">` | `["both"]` | Where to detect PII |
| `enabled` | `boolean` | `true` | Enable or disable PII detection |

## Redaction Strategies

### Hash Strategy
Replaces PII with a hash value. Example: `"123-45-6789"` → `"[HASH:a1b2c3d4]"`

### Mask Strategy
Partially masks PII while keeping some characters visible. Example: `"john.doe@example.com"` → `"john.doe@exa***.com"`

### Remove Strategy
Completely removes PII from the text.

### Replace Strategy
Replaces PII with custom text. Example: `"123-45-6789"` → `"[REDACTED]"`

## Built-in Detectors

### SSN Detector
Detects US Social Security Numbers in `XXX-XX-XXXX` format with validation (excludes invalid prefixes like 000, 666, 900-999).

### Email Detector
Detects email addresses using standard email pattern matching.

### Phone Detector
Detects phone numbers in various formats including international and US formats.

### Credit Card Detector
Detects credit card numbers (16-digit and 15-digit Amex formats).

### IP Address Detector
Detects IPv4 addresses with octet validation.

## API Reference

### Types

```typescript
interface PiiMatch {
text: string;
start: number;
end: number;
type: string;
}

type PiiDetector = (content: string) => PiiMatch[];
type RedactionStrategy = "hash" | "mask" | "remove" | "replace";
type BuiltInPiiType = "ssn" | "email" | "phone" | "credit_card" | "ip_address";
```

### Functions

- `piiMiddleware(config: PiiMiddlewareConfig)`: Creates a PII middleware instance

## Development

### Build
```bash
pnpm build
```

### Test
```bash
pnpm test
```

### Lint
```bash
pnpm lint
```

## License

MIT
41 changes: 41 additions & 0 deletions community/middlewares/pii/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{
"name": "@community/middlewares-pii",
"version": "0.0.0",
"description": "PII (Personally Identifiable Information) detection and redaction middleware",
"type": "module",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": {
"./package.json": "./package.json",
".": {
"@xpert-plugins-starter/source": "./src/index.ts",
"types": "./dist/index.d.ts",
"import": "./dist/index.js",
"default": "./dist/index.js"
}
},
"files": [
"dist",
"!**/*.tsbuildinfo"
],
"scripts": {
"build": "tsc -p tsconfig.json",
"lint": "echo \"(todo) add lint\"",
"test": "echo \"(todo) add tests\""
},
"license": "MIT",
"publishConfig": {
"access": "restricted"
},
"peerDependencies": {
"@langchain/core": "0.3.72",
"@metad/contracts": "^3.7.0",
"@nestjs/common": "^11.1.6",
"@xpert-ai/plugin-sdk": "^3.7.0",
"chalk": "4.1.2",
"zod": "3.25.67"
},
"dependencies": {
"tslib": "^2.3.0"
}
}
49 changes: 49 additions & 0 deletions community/middlewares/pii/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { z } from 'zod';
import type { XpertPlugin } from '@xpert-ai/plugin-sdk';
import { readFileSync } from 'fs';
import { fileURLToPath } from 'url';
import { dirname, join } from 'path';
import { PiiPlugin } from './lib/pii.module.js';
import { PiiIcon } from './lib/types.js';

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

const packageJson = JSON.parse(readFileSync(join(__dirname, '../package.json'), 'utf8')) as {
name: string;
version: string;
};

const ConfigSchema = z.object({
});

const plugin: XpertPlugin<z.infer<typeof ConfigSchema>> = {
meta: {
name: packageJson.name,
version: packageJson.version,
category: 'middleware',
icon: {
type: 'svg',
value: PiiIcon,
},
displayName: 'PII Detection Middleware',
description: 'Detect and redact Personally Identifiable Information (PII) in agent messages. Supports built-in PII types (SSN, email, phone, credit card, IP address) and custom detectors with multiple redaction strategies.',
keywords: ['agent', 'middleware', 'pii', 'privacy', 'security', 'redaction'],
author: 'Community Contributor',
},
config: {
schema: ConfigSchema,
},
register(ctx) {
ctx.logger.log('register PII detection middleware plugin');
return { module: PiiPlugin, global: true };
},
async onStart(ctx) {
ctx.logger.log('PII detection middleware plugin started');
},
async onStop(ctx) {
ctx.logger.log('PII detection middleware plugin stopped');
},
};

export default plugin;
37 changes: 37 additions & 0 deletions community/middlewares/pii/src/lib/pii.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { XpertServerPlugin, IOnPluginBootstrap, IOnPluginDestroy } from '@xpert-ai/plugin-sdk';
import chalk from 'chalk';
import { PiiMiddleware } from './pii.js';


@XpertServerPlugin({
/**
* An array of modules that will be imported and registered with the plugin.
*/
imports: [],

providers: [
PiiMiddleware
]
})
export class PiiPlugin implements IOnPluginBootstrap, IOnPluginDestroy {
// We disable by default additional logging for each event to avoid cluttering the logs
private logEnabled = true;

/**
* Called when the plugin is being initialized.
*/
onPluginBootstrap(): void | Promise<void> {
if (this.logEnabled) {
console.log(chalk.green(`${PiiPlugin.name} is being bootstrapped...`));
}
}

/**
* Called when the plugin is being destroyed.
*/
onPluginDestroy(): void | Promise<void> {
if (this.logEnabled) {
console.log(chalk.green(`${PiiPlugin.name} is being destroyed...`));
}
}
}
Loading