Skip to main content
Glama
README.md
# Bulkhead

**Cascading content protection for AI-powered development tools.**

Bulkhead detects and redacts sensitive content -- PII, secrets, prompt injection, and system prompt leakage -- before it leaks through LLM-powered features. It runs as a VS Code extension, an HTTP REST server, or an MCP server for AI coding assistants.

| | |
|---|---|
| **Deployment** | VS Code extension, HTTP REST server, MCP server, Docker |
| **Detection** | 154 secret patterns across 13 categories, 45+ PII entity types across 20+ countries, prompt injection, system prompt leakage, test data detection |
| **Architecture** | Three-layer cascading classifier (regex, BERT, LLM) |
| **Policy** | Named policies (strict, moderate), composable compliance overlays, risk assessment with classified issues |
| **Tests** | 185 tests including adversarial suite, policy system, and performance benchmarks |

## Why Bulkhead?

### The AI Coding Assistant Blind Spot

Every time a developer uses an AI coding assistant, the IDE sends context to an LLM -- not just the active file, but adjacent tabs, terminal output, clipboard contents, and project-wide search results. That context routinely includes `.env` files with database credentials, test fixtures with real customer data, and config files with API keys.

This leakage happens **at edit time, not commit time.** It is continuous, invisible, and bypasses every existing control: git hooks don't see it, SAST doesn't scan it, WAFs don't intercept it. There is no diff, no PR, no audit trail. By the time a secret scanner catches something at commit, the AI assistant has already sent it to an LLM provider dozens of times.

### What's at Stake

- **HIPAA:** $50,000 -- $1.9M per violation. Average healthcare breach: $9.77M
- **PCI-DSS:** $5,000 -- $100,000/month in non-compliance fines
- **GDPR:** Up to 4% of annual global revenue
- **SOC 2:** Audit failures mean lost enterprise contracts
- **Average data breach cost:** $4.88M (IBM 2024). Mean time to identify: 194 days
- **A single leaked AWS key** costs $50,000+ in cloud resource abuse on average

### How Bulkhead Solves It

Bulkhead sits between your editor and the AI, catching sensitive content before it leaves. Three detection layers trade speed for depth -- expensive inference only runs on the fraction of content that needs it:

```mermaid
flowchart LR
    A["Input Text"] --> B["Layer 1: Regex\nsub-ms"]
    B -->|"60-70% resolved"| C["Confirmed"]
    B -->|"remaining"| D["Layer 2: BERT\n20-50ms"]
    D -->|"~90% resolved"| C
    D -->|"~5-10% ambiguous"| E["Layer 3: LLM\n500ms-2s"]
    E --> C
```

Every detection carries **provenance** -- which layer flagged it, at what confidence, and why. Your compliance team gets "regex matched SSN with Luhn validation" or "BERT flagged a name at 0.92 confidence," not "the AI said so."

### Deploy Anywhere, Change Nothing

- **VS Code extension** -- catches leaks at the point of creation, on every keystroke
- **HTTP REST server** -- CI/CD pipeline integration, API gateway sidecar
- **MCP server** -- direct integration with Claude Code and GitHub Copilot
- **Docker** -- zero-install containerized deployment for air-gapped environments

Same engine, same 154 secret patterns, same 45+ PII types, same policies. Different transports.

For the full business case with industry scenarios, architecture walkthroughs, and comparison with alternatives, see [Why Do We Need Content Protection for AI Dev Tools?](docs/why-do-we-need-this.md)

## What Makes Bulkhead Different

The core innovation is the **cascading classifier** -- three detection layers that progressively trade speed for depth, so expensive inference only runs on the small fraction of content that actually needs it. Regex handles the bulk (sub-millisecond, every keystroke). A BERT model resolves contextual entities like names and locations. An LLM disambiguates the genuinely hard cases ("Is 'Jordan' a person or a country?"). Each detection carries full provenance -- which layer flagged it, at what confidence, and why.

The detection patterns themselves are ported from established open-source projects (see [Attribution](#attribution)). Bulkhead's contribution is the cascade architecture, the BERT worker thread integration, the LLM disambiguation layer, the multi-platform server architecture, and the deduplication logic that ties it all together.

## The Problem

Every time you use an AI coding assistant, your editor content gets sent to an LLM. That content can include:

- **Personal data** -- SSNs, credit cards, emails, phone numbers, medical IDs
- **Secrets** -- API keys, tokens, database credentials, private keys
- **Prompt injection** -- malicious instructions hidden in code comments or data
- **System prompt leakage** -- attempts to extract your AI tool's configuration

Bulkhead sits between your code and the AI, catching sensitive content before it leaves.

## Install

```bash
npm install @bulkhead-ai/core
```

Also available as `@floatingsidewal/bulkhead-core` via [GitHub Packages](https://github.com/floatingsidewal/bulkhead/packages) and as a Docker container at `ghcr.io/floatingsidewal/bulkhead`.

### Quick Start

```typescript
import { createEngine, getPolicy } from "@bulkhead-ai/core";

const engine = createEngine({
  enabled: true, debounceMs: 500,
  guards: { pii: { enabled: true }, secret: { enabled: true }, injection: { enabled: true }, contentSafety: { enabled: false } },
  cascade: { escalationThreshold: 0.75, contextSentences: 3, modelEnabled: false, modelId: "Xenova/bert-base-NER" },
  policy: "strict",
});

const policy = getPolicy("strict");
const { risk } = await engine.policyScan("My SSN is 123-45-6789", policy);
console.log(risk.level);   // "high"
console.log(risk.issues);  // [{ category: "pii", entityType: "US_SSN", severity: "high", isTestData: true }]
```

For JSON-compatible payloads, use the document API so Bulkhead owns traversal,
overlap handling, date treatment, reconstruction, and residual validation:

```typescript
import { sanitizeDocument } from "@bulkhead-ai/core";

const result = await sanitizeDocument(payload, "eval", {
  localizedDateOrder: "reject-ambiguous",
});

if (!result.metadata.postTreatment.safe ||
    !result.metadata.postTreatment.structurallyValid) {
  throw new Error("Sanitization boundary rejected output");
}

send(JSON.stringify(result.value));
```

See the [How-To Guide](docs/how-to.md) for comprehensive examples including medical record scanning, bulk data redaction, and custom policies.

## Project Structure

```
bulkhead/
  packages/
    core/       @bulkhead-ai/core      Detection engine, guards, cascade, policies
    vscode/     bulkhead               VS Code extension
    server/     @bulkhead-ai/server    HTTP REST server + MCP server
  docs/                                Guides: architecture, API, policies, patterns
  Dockerfile                           Multi-stage build (HTTP + MCP modes)
  docker-compose.yml                   HTTP and MCP service definitions
```

## How It Works

Bulkhead uses the **cascading classifier** -- three detection layers that trade off speed against depth:

| Layer | Speed | What it catches | When it runs |
|-------|-------|----------------|--------------|
| **Regex** | Sub-ms | Structured PII (SSN, credit cards, IBAN), secrets (AWS keys, tokens), injection patterns | Every keystroke (debounced) |
| **BERT** | 20-50ms | Names, locations, organizations -- contextual entities regex can't catch | On-demand "Deep Scan" or `/v1/scan/model` |
| **LLM** | 500ms-2s | Ambiguous cases ("Is 'Jordan' a person or country?") | Only for the ~5-10% of detections the BERT layer can't resolve |

Each detection carries **provenance** -- which layer flagged it, at what confidence, and whether it's confirmed or needs review.

## What It Detects

### PII (45+ entity types across 20+ countries)
Patterns ported from [Microsoft Presidio](https://github.com/microsoft/presidio) with checksum validation (Luhn, IBAN mod-97, Verhoeff) and context-aware scoring.

- **Generic:** Credit cards, email, IBAN, IP addresses, MAC addresses, phone numbers, URLs, crypto wallets, dates
- **US:** SSN, driver's license, passport, bank accounts, ITIN, Medicare (MBI), NPI, ABA routing, DEA license
- **UK:** NHS number, NINO, passport, postcode, vehicle registration
- **EU:** Spain NIF/NIE, Italy fiscal code/VAT/driver/passport/ID, Poland PESEL, Finland PIC, Sweden personnummer, Germany tax ID/passport
- **APAC:** Singapore NRIC/UEN, Australia ABN/ACN/TFN/Medicare, India PAN/Aadhaar/vehicle/voter/passport, Korea RRN/passport, Thailand TNIN
- **Africa:** Nigeria NIN

### Secrets (154 patterns across 13 categories)
Patterns sourced from HAI-Guardrails, GitLeaks, and public provider documentation.

- **Cloud:** AWS, Azure, GCP
- **Source control:** GitHub, GitLab, Bitbucket
- **CI/CD:** Jenkins, CircleCI, Travis CI, Drone
- **Communication:** Slack, Twilio, SendGrid, Mailgun
- **Payment:** Stripe, Square, PayPal
- **Database:** Connection strings, Redis, MongoDB
- **Infrastructure:** Terraform, Vault, Consul
- **SaaS:** Jira, Confluence, Datadog, New Relic
- **AI/ML:** OpenAI, Anthropic, HuggingFace, Cohere
- **Auth:** Auth0, Okta, Firebase, Clerk, Supabase
- **CDN/Hosting:** Cloudflare, Netlify, Vercel, Heroku
- **Social:** Twitter, Facebook, LinkedIn
- **Generic:** JWT, private keys, high-entropy strings

### Prompt Injection
16 regex patterns + heuristic similarity matching against known attack phrases. Catches: "ignore previous instructions", role-play attacks, DAN mode, jailbreak attempts.

### System Prompt Leakage
7 regex patterns + heuristic matching. Catches: "reveal your system prompt", "repeat everything above", extraction techniques.

## Quick Start

### Install from source

```bash
git clone https://github.com/your-org/bulkhead.git
cd bulkhead
npm install
npm run build
```

### VS Code Extension

1. Open the `bulkhead/` folder in VS Code
2. Press `F5` to launch the Extension Development Host
3. Open any file -- Bulkhead auto-scans on edit (regex layer, debounced)
4. Use the command palette:
   - `Bulkhead: Scan File` -- regex scan
   - `Bulkhead: Deep Scan` -- regex + BERT + LLM cascade

### HTTP REST Server

```bash
# Development
cd packages/server && npm run dev

# Production
npm run build && node packages/server/dist/main.js

# With API key authentication
BULKHEAD_API_KEY=my-secret-key node packages/server/dist/main.js
```

```bash
# Scan text
curl -X POST http://localhost:3000/v1/scan \
  -H "Content-Type: application/json" \
  -d '{"text": "My SSN is 123-45-6789"}'

# Scan and redact
curl -X POST http://localhost:3000/v1/redact \
  -H "Content-Type: application/json" \
  -d '{"text": "My SSN is 123-45-6789"}'
```

### MCP Server (Claude Code)

Add to `.mcp.json` in your project root:

```json
{
  "mcpServers": {
    "bulkhead": {
      "command": "npx",
      "args": ["tsx", "packages/server/src/mcp/index.ts"]
    }
  }
}
```

### MCP Server (GitHub Copilot CLI)

Add to `.github/copilot/mcp.json`:

```json
{
  "mcpServers": {
    "bulkhead": {
      "command": "npx",
      "args": ["tsx", "packages/server/src/mcp/index.ts"]
    }
  }
}
```

### Docker

```bash
# HTTP server on port 3000
docker compose up bulkhead

# MCP server on stdio
docker compose run --rm -i bulkhead-mcp
```

### Use as a library

```typescript
import { GuardrailsEngine, PiiGuard, SecretGuard } from "@bulkhead-ai/core";

const engine = new GuardrailsEngine();
engine.addGuard(new PiiGuard());
engine.addGuard(new SecretGuard());

const results = await engine.analyze("Email: john@example.com, Key: AKIAIOSFODNN7EXAMPLE");
// results[0].detections -> [{ entityType: "EMAIL_ADDRESS", source: "regex", disposition: "confirmed", ... }]
// results[1].detections -> [{ entityType: "AWS_ACCESS_KEY", source: "regex", disposition: "confirmed", ... }]
```

## Configuration

### VS Code Settings

| Setting | Default | Description |
|---------|---------|-------------|
| `bulkhead.enabled` | `true` | Master toggle |
| `bulkhead.debounceMs` | `500` | Delay before auto-scan on edit |
| `bulkhead.guards.pii.enabled` | `true` | PII detection |
| `bulkhead.guards.secret.enabled` | `true` | Secret detection |
| `bulkhead.guards.injection.enabled` | `true` | Prompt injection detection |
| `bulkhead.cascade.modelEnabled` | `false` | Enable BERT model (downloads ~29MB on first use) |
| `bulkhead.cascade.escalationThreshold` | `0.75` | BERT confidence below which detections escalate to LLM |
| `bulkhead.cascade.contextSentences` | `3` | Sentences of context sent to LLM for disambiguation |

### Environment Variables (Server)

| Variable | Default | Description |
|----------|---------|-------------|
| `BULKHEAD_PORT` | `3000` | HTTP server port |
| `BULKHEAD_HOST` | `0.0.0.0` | HTTP server bind address |
| `BULKHEAD_LOG_LEVEL` | `info` | Log level: `info`, `warn`, `error`, `silent` |
| `BULKHEAD_API_KEY` | (none) | API key for authentication. When set, all `/v1/*` routes require `X-API-Key` header |
| `BULKHEAD_CORS_ORIGIN` | (disabled) | CORS origin. Set to `*` or a specific origin to enable |
| `BULKHEAD_MAX_BODY_SIZE` | `1048576` | Maximum request body size in bytes (default 1MB) |
| `BULKHEAD_GUARDS_PII_ENABLED` | `true` | Enable PII guard |
| `BULKHEAD_GUARDS_SECRET_ENABLED` | `true` | Enable secret guard |
| `BULKHEAD_GUARDS_INJECTION_ENABLED` | `true` | Enable injection guard |
| `BULKHEAD_CASCADE_MODEL_ENABLED` | `false` | Enable BERT model for Layer 2 |
| `BULKHEAD_CASCADE_MODEL_ID` | `gravitee-io/bert-small-pii-detection` | HuggingFace model ID |
| `BULKHEAD_CASCADE_ESCALATION_THRESHOLD` | `0.75` | BERT confidence threshold for LLM escalation |
| `BULKHEAD_LLM_PROVIDER` | `none` | LLM provider: `openai`, `anthropic`, `custom` |
| `BULKHEAD_LLM_API_KEY` | (none) | API key for the LLM provider |
| `BULKHEAD_LLM_ENDPOINT` | (none) | Endpoint URL for custom LLM provider |

## Testing

```bash
npm test              # Run all 185 tests
npm run test:watch    # Watch mode (core package)
npm run lint          # Type-check all packages
```

The test suite includes an [adversarial test suite](test/adversarial/) covering evasion techniques, false positive resistance, mixed-threat documents, performance benchmarks with ASCII bar charts, and a "kitchen sink" document that triggers all threat types simultaneously.

## Documentation

- [Why Bulkhead?](docs/why-do-we-need-this.md) -- Business case, real-world scenarios, comparison with alternatives
- [Architecture](docs/architecture.md) -- Cascading classifier design, component map, entry points
- [Policy Guide](docs/policy.md) -- Policies, risk assessment, test data detection, compliance overlays
- [Deployment](docs/deployment.md) -- Five deployment scenarios with configuration and examples
- [API Reference](docs/api.md) -- HTTP endpoints, MCP tools, environment variables
- [Guards](docs/guards.md) -- Guard implementation details
- [Patterns](docs/patterns.md) -- Detection pattern reference
- [Testing](docs/testing.md) -- Test strategy and adversarial suite
- [How-To](docs/how-to.md) -- Usage guides and library integration

## Attribution

Bulkhead derives detection patterns and guard architecture from two open-source
projects. The cascading classifier, BERT integration, LLM disambiguation, VS Code
extension, server architecture, and deduplication logic are independently developed. See
[ATTRIBUTION.md](ATTRIBUTION.md) for full details and [NOTICES](NOTICES) for
original copyright notices.

- **[Microsoft Presidio](https://github.com/microsoft/presidio)** (MIT) -- PII detection patterns, checksum algorithms, entity taxonomy
- **[HAI-Guardrails](https://github.com/presidio-oss/hai-guardrails)** (MIT) -- Guard architecture, detection tactics, security patterns

## Contributing

See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.

## License

[MIT](LICENSE)