@glubean/redaction
v0.1.11
Published
Scope-based secrets/PII detection and masking for [Glubean](https://glubean.dev).
Readme
@glubean/redaction
Scope-based secrets/PII detection and masking for Glubean.
Overview
Redaction v2 uses a data-driven scope model. Scopes declare what to redact (event type + field path + rules). Handlers declare how to interpret payloads (JSON, headers, URL query strings). Plugins provide detection logic (sensitive keys, value patterns).
All scope declarations — built-in HTTP, gRPC, or any future protocol — use the same shape. No hardcoded protocol knowledge in the redaction package.
Quick Start
import {
compileScopes,
redactEvent,
BUILTIN_SCOPES,
DEFAULT_GLOBAL_RULES,
} from "@glubean/redaction";
// Compile scopes once at startup
const scopes = compileScopes({
builtinScopes: BUILTIN_SCOPES,
globalRules: DEFAULT_GLOBAL_RULES,
replacementFormat: "partial",
});
// Redact events
const event = {
type: "trace",
data: {
requestHeaders: { authorization: "Bearer secret-token" },
requestBody: { password: "hunter2", username: "alice" },
},
};
const redacted = redactEvent(event, scopes, "partial");
// redacted.data.requestHeaders.authorization → "Bea***123"
// redacted.data.requestBody.password → "hun***er2"
// redacted.data.requestBody.username → "alice" (not sensitive)Architecture
scope declarations (built-in + plugins + user overrides)
→ compile to CompiledScope[]
→ redactEvent(event, compiledScopes)
→ for each matching scope:
1. extract target value via field path
2. run the scope's handler
3. handler calls engine with per-scope plugin pipeline
4. write redacted value backScopes
A scope declares where to redact and what rules apply:
{
id: "http.request.headers",
name: "HTTP request headers",
event: "trace",
target: "data.requestHeaders",
handler: "headers",
rules: {
sensitiveKeys: ["authorization", "cookie"],
},
}id— stable config key for user overridesevent— which event type to matchtarget— dot-path to the payload fieldhandler— which handler interprets the payloadrules— scope-specific sensitive keys and patterns
Handlers
Built-in handlers:
| Handler | Purpose |
|---------|---------|
| json | Recursive JSON object/array walker |
| raw-string | Value-pattern matching on plain strings |
| url-query | Parse URL, redact query params, serialize back |
| headers | Header map with cookie/set-cookie parsing |
Plugins
Detection plugins (unchanged from v1):
- sensitive-keys — key-level substring matching
- jwt — JWT token detection
- bearer — Bearer token detection
- awsKeys — AWS access key ID
- githubTokens — GitHub PAT tokens
- email — Email address detection
- ipAddress — IPv4 address detection
- creditCard — Credit card number detection
- hexKeys — Hex key detection (32+ chars)
Plugin Integration
Plugins declare their own redaction scopes via PluginFactory.redaction:
// gRPC plugin
grpc({
proto: "./protos/users.proto",
address: "{{ADDR}}",
package: "acme.users.v1",
service: "UsersService",
});
// Plugin internally declares:
// redaction: [
// { id: "grpc.metadata", handler: "headers", rules: { sensitiveKeys: ["authorization"] } },
// { id: "grpc.request", handler: "json" },
// { id: "grpc.response", handler: "json" },
// ]The runner collects all plugin declarations and merges them with built-in scopes at compile time.
User Overrides
Users override scopes by stable id in .glubean/redact.json:
{
"scopes": {
"grpc.metadata": { "enabled": false },
"http.request.headers": {
"rules": { "sensitiveKeys": ["x-custom-secret"] }
}
},
"globalRules": {
"sensitiveKeys": ["my-internal-key"],
"customPatterns": [
{ "name": "internal-id", "regex": "INT-[A-Z0-9]{8}" }
]
}
}Replacement Formats
| Format | Example |
|--------|---------|
| simple | [REDACTED] |
| labeled | [REDACTED:sensitive-keys] |
| partial | Bea***123 (smart masking) |
License
MIT
