Skip to content
Merged
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
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
83 changes: 83 additions & 0 deletions CHANGELOG.md

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,9 @@ Agent (secrets, no network) → Pipelock (no agent secrets, full network) → In

### Scanner Pipeline

1. Scheme (http/https only) → 2. Domain blocklist → 3. DLP (patterns, env leak detection, entropy) → 4. Path entropy → 5. Subdomain entropy → 6. SSRF (private IPs, metadata, DNS rebinding) → 7. Rate limiting → 8. URL length → 9. Data budget
1. Scheme (http/https only) → 2. CRLF injection → 3. Path traversal → 4. Domain blocklist → 5. DLP (patterns, env leak detection, entropy) → 6. Path entropy → 7. Subdomain entropy → 8. SSRF (private IPs, metadata, DNS rebinding) → 9. Rate limiting → 10. URL length → 11. Data budget

Layers 2-3 run **before** DNS resolution. Layer 6 runs **after**. This ordering prevents DNS-based exfiltration.
Layers 4-5 run **before** DNS resolution. Layer 8 runs **after**. This ordering prevents DNS-based exfiltration.

### MCP Proxy

Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@ Synthetic secrets injected into the agent's environment. If pipelock detects a c
| **Diagnose** | `pipelock diagnose` runs 7 local checks to verify your config works end-to-end (no network required) |
| **Enforcement Doctor** (v2.5) | `pipelock doctor` reports configured-vs-enforceable status for proxying, TLS interception, request-body scanning, Browser Shield, MCP wrapping, MCP binary integrity, tool provenance, file_sentry, Sentry, and deployment-boundary signals. |
| **Request Body Injection Blocking** (v2.5) | Request-body prompt-injection and critical-DLP findings hard-block non-provider destinations in enforce mode across forward, reverse, TLS-intercept, and WebSocket transports, with block-reason headers for operator-visible diagnosis. |
| **Request Policy** (v2.6) | Allow-by-default deny/warn rails on outbound API *operations*: match a request on route plus a GraphQL operation predicate and block the dangerous ones. Enforces across every HTTP egress transport, recurses into JSON `$batch` envelopes, fails closed on unparseable or opaque bodies, and runs before the contract gate. See the [request policy guide](docs/guides/request-policy.md). |
| **TLS Interception** | Optional CONNECT tunnel MITM: decrypt, scan bodies/headers/responses, re-encrypt. `pipelock tls init` generates a CA, then `pipelock tls install-ca` trusts it system-wide. |
| **Block Hints** | Opt-in `explain_blocks: true` adds fix suggestions to blocked responses |
| **Project Audit** | `pipelock audit ./project` scans for security risks and generates a tailored config |
Expand Down Expand Up @@ -466,6 +467,7 @@ Details, config examples, and gap analysis: [docs/owasp-mapping.md](docs/owasp-m
| Document | What's In It |
|----------|-------------|
| [Configuration Reference](docs/configuration.md) | All config fields, defaults, hot-reload behavior, presets |
| [Request Policy](docs/guides/request-policy.md) | Allow-by-default deny/warn rails on outbound API operations (GraphQL / discriminator / batch), fail-closed (v2.6) |
| [Request Redaction](docs/guides/redaction.md) | JSON request rewriting across HTTP, WebSocket, and MCP transports |
| [False Positive Tuning](docs/false-positive-tuning.md) | Identifying, suppressing, and tuning scanner findings |
| [Scan API](docs/scan-api.md) | Evaluation endpoint for programmatic scanning |
Expand Down
Binary file modified assets/demo.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion bench/egress/mocks/mcpstdio/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ func run(in io.Reader, out io.Writer) error {
}
var req rpcRequest
if err := json.Unmarshal(line, &req); err != nil {
// Malformed input is benign for the bench skip and keep reading.
// Malformed input is benign for the bench - skip and keep reading.
continue
}
resp := handle(&req)
Expand Down
6 changes: 3 additions & 3 deletions charts/pipelock/Chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ apiVersion: v2
name: pipelock
description: Agent firewall for AI agents. Network scanning, process containment, and tool policy enforcement.
type: application
version: 0.2.0
appVersion: "2.5.0"
version: 0.3.0
appVersion: "2.6.0"
home: https://pipelab.org
sources:
- https://github.com/luckyPipewrench/pipelock
Expand All @@ -29,7 +29,7 @@ annotations:
url: https://github.com/luckyPipewrench/pipelock-verify-python
artifacthub.io/changes: |
- kind: changed
description: Pin default image to v2.5.0 multi-arch digest.
description: Bump default application version to v2.6.0 and let the chart follow .Chart.AppVersion unless image.digest is explicitly set.
- kind: added
description: Health-watchdog-backed liveness and readiness probes with timeout and threshold tuning.
- kind: added
Expand Down
6 changes: 4 additions & 2 deletions charts/pipelock/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,11 @@ The chart is configured by passing values to `helm install -f values.yaml`. The
|---|---|---|
| `image.repository` | `ghcr.io/luckypipewrench/pipelock` | Image repository |
| `image.tag` | `""` | Tag used when `image.digest` is empty. Falls through to `.Chart.AppVersion` if also empty. |
| `image.digest` | v2.5.0 multi-arch manifest digest | When set, the chart renders `repository@digest` for pinning |
| `image.digest` | `""` | Optional multi-arch manifest digest. When set, the chart renders `repository@digest` for pinning |
| `image.pullPolicy` | `IfNotPresent` | Image pull policy |

> **Upgrading from chart 0.2.0:** the default `image.digest` was cleared, so the chart now follows `.Chart.AppVersion` (v2.6.0) by default instead of a pinned digest. Set `image.digest` explicitly in your values if you need an immutable image reference.

### Ports

| Key | Default | Description |
Expand All @@ -34,7 +36,7 @@ The chart is configured by passing values to `helm install -f values.yaml`. The

### Health probes

Liveness and readiness probes hit `/health`, which v2.5 backs with a subsystem watchdog. The endpoint returns 503 when scanner, config, kill switch, session, or watchdog liveness fails — Kubernetes will restart the pod automatically.
Liveness and readiness probes hit `/health`, backed by the subsystem watchdog. The endpoint returns 503 when scanner, config, kill switch, session, or watchdog liveness fails — Kubernetes will restart the pod automatically.

| Key | Default | Description |
|---|---|---|
Expand Down
2 changes: 1 addition & 1 deletion charts/pipelock/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ image:
# to a sha256 string and the chart will render repository@digest. The tag
# value falls through to .Chart.AppVersion when empty.
tag: "" # defaults to .Chart.AppVersion
digest: "sha256:ea07c3b476829e0a9c13b8484aa9c71e60e811c5fdf07d35e17bcb889bb72446" # v2.5.0 multi-arch manifest digest
digest: "" # optional sha256 multi-arch manifest digest
pullPolicy: IfNotPresent

imagePullSecrets: []
Expand Down
4 changes: 2 additions & 2 deletions cmd/pipelock-verifier/replay.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ package main

// `pipelock-verifier replay` re-evaluates a Pipelock action receipt against
// a current policy. The point: turn receipts from "what happened" into
// "what would happen today under current policy" the governance-evidence
// "what would happen today under current policy" - the governance-evidence
// shift. Codex 2026-05-21 leadership review framed this as the
// load-bearing primitive for receipts as evidence rather than logs.
//
Expand Down Expand Up @@ -197,7 +197,7 @@ func runReplay(stdout, stderr io.Writer, receiptPath string, opts replayOptions)

// verdictsAgree compares an original receipt verdict (block / allow / warn /
// strip / redirect / ask / forward) against a replay verdict (block / allow).
// Warn and strip are "soft allows" they let the action through with a
// Warn and strip are "soft allows" - they let the action through with a
// finding logged. Redirect, ask, forward are also "soft allows" relative
// to a binary block/allow comparison.
func verdictsAgree(original, replay string) bool {
Expand Down
4 changes: 2 additions & 2 deletions cmd/pipelock-verifier/replay_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ func TestReplay_VerdictChanged_PolicyLoosened(t *testing.T) {
PolicyHash: "policy-fixture",
}
receiptPath := writeSignedReceiptFile(t, dir, ar)
// New policy has empty blocklist would now allow.
// New policy has empty blocklist - would now allow.
policyPath := writePolicyFile(t, dir, nil)

report, _, exitCode := runReplayCommand(t,
Expand Down Expand Up @@ -286,7 +286,7 @@ func TestReplay_BadKeyMismatch(t *testing.T) {
receiptPath := writeSignedReceiptFile(t, dir, ar)
policyPath := writePolicyFile(t, dir, nil)

// Pass a different key the verifier should reject.
// Pass a different key - the verifier should reject.
otherPub, _, err := ed25519.GenerateKey(rand.Reader)
if err != nil {
t.Fatal(err)
Expand Down
54 changes: 54 additions & 0 deletions docs/cli/scan.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# `pipelock scan`

`pipelock scan` inspects files for invisible-Unicode and bidi-control injection: zero-width, bidirectional-override, Unicode-tag, and control characters that hide instructions inside agent-context files (`CLAUDE.md`, `.cursorrules`, `AGENTS.md`, skill definitions) where a human reviewer cannot see them.

This is the local-file half of supply-chain prompt injection. The network proxy never sees files at rest, so this command surfaces that vector and exits non-zero so pre-commit hooks and CI can gate on it. Detection is free-tier and adds no dependencies; it reuses the same `normalize.InvisibleRanges` data the runtime scanner strips, so file detection never diverges from proxy detection.

```sh
pipelock scan # scan the current directory
pipelock scan CLAUDE.md .cursorrules
pipelock scan ~/.claude/skills --json
pipelock scan . --min-severity medium # also gate on suspicious-but-contextual chars
pipelock scan . --fail-on-skip # fail CI if anything went uninspected
pipelock scan . --include-deps # also scan vendored/node_modules context
```

When no path is given, the current directory is scanned recursively.

## Flags

| Flag | Default | Description |
|---|---|---|
| `--json` | `false` | Emit findings as JSON instead of the human-readable report. |
| `--max-bytes` | `5 MiB` | Skip files larger than N bytes. `0` means the 5 MiB default. |
| `--exclude` | none | Additional directory names to skip (repeatable / comma-separated). |
| `--min-severity` | `high` | Minimum finding severity that causes a non-zero exit: `high`, `medium`, or `low`. Lower severities are still reported, just not gated. |
| `--include-deps` | `false` | Also scan dependency / VCS directories (`node_modules`, `vendor`, `.git`, ...) that are skipped by default. |
| `--fail-on-skip` | `false` | Exit 2 if any file was skipped (binary, symlink, or oversized). |

## Severity

Not every invisible character is equally suspicious in a file, so findings carry a severity and `--min-severity` controls what causes a non-zero exit (the default gates on `high` and reports the rest):

| Severity | Examples |
|---|---|
| `high` | Bidi embedding/override (U+202A–U+202E), bidi isolates (U+2066–U+2069), word joiner (U+2060), zero-width space (U+200B). |
| `medium` | Directional marks (U+200E/U+200F), BOM (U+FEFF), invisible math operators, Arabic letter mark. |
| `low` | Contextually legitimate characters: zero-width non-joiner/joiner (Persian/Arabic, emoji), soft hyphen, combining grapheme joiner. |

## Exit codes

| Exit code | Meaning |
|---|---|
| 0 | No findings at or above `--min-severity`. |
| 1 | One or more findings at or above `--min-severity`. |
| 2 | Scan / config error, an explicitly named file was skipped (binary, symlink, oversized), or `--fail-on-skip` was set and any file was skipped. |

The distinct exit codes let a CI wrapper tell "found hidden characters" (1) apart from "the scan itself broke" (2).

## CI / pre-commit use

```sh
# pre-commit hook: block commits that introduce hidden instructions in context files
pipelock scan CLAUDE.md AGENTS.md .cursorrules ~/.claude/skills || exit 1
```
1 change: 1 addition & 0 deletions docs/cli/verify-install.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ Scanning and local enforcement checks:
| `scanning_dlp` | MCP input scanning catches secret-shaped tool input. |
| `scanning_injection` | Prompt-injection scanning fires on a hostile input. |
| `scanning_policy` | MCP tool policy denies a blocked command. |
| `scanning_websocket` | WebSocket frame scanning catches a hostile text frame. |
| `browser_shield` | Browser Shield rewrites shieldable browser content. |
| `file_sentry` | file_sentry detects a secret written to a watched workspace. |
| `mcp_binary_integrity_smoke` | MCP binary-integrity manifest loading and hash verification work. |
Expand Down
12 changes: 11 additions & 1 deletion docs/compliance/eu-ai-act-mapping.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,17 @@ How Pipelock's runtime security controls map to the [EU AI Act (Regulation 2024/

**Disclaimer:** This document maps Pipelock's security features to EU AI Act requirements for informational purposes. It does not constitute legal advice or guarantee regulatory compliance. Organizations should consult qualified legal counsel for compliance obligations specific to their AI systems.

**Last updated:** May 2026 (reviewed against v2.5 feature set; v2.5 adds the host containment lifecycle CLI (`pipelock contain install / verify / rollback / add-tool / grant-workspace / revoke-workspace / ca-refresh`) implementing a 3-UID kernel-enforced separation strengthening Art. 14 Human Oversight (operator-enforced separation of duties between the operator and the agent process), Art. 15 Cybersecurity (kernel-enforced egress containment with TOFU binary integrity and explicit workspace ACL lifecycle), and Art. 26 Deployer Obligations (operator-visible install / verify / rollback path); the canonical Audit Packet v0 schema plus first-party Go / TypeScript / Rust / standalone verifier implementations strengthening Art. 12 Record-Keeping and Art. 13 Transparency (language-portable, independent verification of every signed receipt without depending on Pipelock); strict-default SPIFFE actor enforcement on inbound mediation envelopes plus the `pipelock envelope trust` operator CLI strengthening Art. 14 Identification of Deployers and cross-organisational verifiability; activation-time tombstone enforcement preventing re-promotion of withdrawn contracts strengthening Art. 9 Risk Management System (operator-driven withdrawal stays withdrawn); skill-poisoning instruction-recognition coverage strengthening Art. 15 Cybersecurity at the agent-content boundary; rules-bundle keyring separated from license key strengthening Art. 15 cryptographic isolation between commercial keys and detection keys; optional OTel `agent.threat.detection.*` attributes strengthening Art. 12 Record-Keeping for observability-driven audit. Builds on the v2.4 baseline (learn-and-lock contracts for Art. 12 / Art. 14, inbound envelope verification + replay protection for Art. 13, SPIFFE actor format + RFC 9421 directory for Art. 14, `X-Pipelock-Block-Reason` for Art. 13, Gemini provider redaction extending Art. 10), the v2.3.0 baseline (class-preserving redaction across HTTP / WebSocket / MCP, generic SSE streaming with per-event body scanning), and the v2.2.0 baseline (mediation envelope, signed action receipts across all transports, taint-aware policy escalation, posture verify CLI, companion-proxy deployment, session operator CLI).
**Last updated:** May 2026 (reviewed against the v2.6 feature set. v2.5 added the host containment lifecycle CLI (`pipelock contain install / verify / rollback / add-tool / grant-workspace / revoke-workspace / ca-refresh`) implementing a 3-UID kernel-enforced separation strengthening Art. 14 Human Oversight (operator-enforced separation of duties between the operator and the agent process), Art. 15 Cybersecurity (kernel-enforced egress containment with TOFU binary integrity and explicit workspace ACL lifecycle), and Art. 26 Deployer Obligations (operator-visible install / verify / rollback path); the canonical Audit Packet v0 schema plus first-party Go / TypeScript / Rust / standalone verifier implementations strengthening Art. 12 Record-Keeping and Art. 13 Transparency (language-portable, independent verification of every signed receipt without depending on Pipelock); strict-default SPIFFE actor enforcement on inbound mediation envelopes plus the `pipelock envelope trust` operator CLI strengthening Art. 14 Identification of Deployers and cross-organisational verifiability; activation-time tombstone enforcement preventing re-promotion of withdrawn contracts strengthening Art. 9 Risk Management System (operator-driven withdrawal stays withdrawn); skill-poisoning instruction-recognition coverage strengthening Art. 15 Cybersecurity at the agent-content boundary; rules-bundle keyring separated from license key strengthening Art. 15 cryptographic isolation between commercial keys and detection keys; optional OTel `agent.threat.detection.*` attributes strengthening Art. 12 Record-Keeping for observability-driven audit. Builds on the v2.4 baseline (learn-and-lock contracts for Art. 12 / Art. 14, inbound envelope verification + replay protection for Art. 13, SPIFFE actor format + RFC 9421 directory for Art. 14, `X-Pipelock-Block-Reason` for Art. 13, Gemini provider redaction extending Art. 10), the v2.3.0 baseline (class-preserving redaction across HTTP / WebSocket / MCP, generic SSE streaming with per-event body scanning), and the v2.2.0 baseline (mediation envelope, signed action receipts across all transports, taint-aware policy escalation, posture verify CLI, companion-proxy deployment, session operator CLI).

v2.6 review (May 2026):

- Art. 12: block-reason receipts, scan API tool-call findings, and file_sentry skip visibility improve operator records for mediated decisions and uninspected local files.
- Art. 13: `request_policy_deny` block reasons and explicit scan-cap failure behavior make denial causes more transparent to operators and agent clients.
- Art. 14: `verify-install` WebSocket coverage and file_sentry block mode give deployers more concrete checks and controls over protected agent runtime behavior.
- Art. 15: `request_policy` operation rails, per-frame WebSocket enforcement, header-DLP parity, and submit-profile SSRF-safe dialing strengthen runtime robustness against unsafe egress.
- Art. 15(4)/(5): redaction passthrough hardening, media canonical-end truncation, and response scan-cap fail-closed behavior reduce avoidable corruption while keeping cybersecurity controls fail-closed.

Fleet control-plane documentation is deferred to v2.7.

---

Expand Down
Loading
Loading