chore(helm): bump pipelock to 2.5.0 and surface 2.5 config (#1913)

* chore(helm): bump pipelock to 2.5.0 and surface 2.5 config

Bumps pipelock.image.tag from 2.2.0 to 2.5.0 and exposes the most
relevant 2.5 features as structured Helm values:

- pipelock.requestBodyScanning: scan outbound bodies and sensitive
  headers for prompt-injection and DLP payloads. Disabled by default;
  roll out with action=warn before flipping to block.
- pipelock.healthWatchdog: structured config for the wedge-detection
  watchdog with an exposeSubsystems toggle for /health detail.
- pipelock.mcpToolPolicy.rules: structured values for rendering
  mcp_tool_policy.rules including redirect-profile references.

Also fixes a latent config-validation regression: pipelock 2.x rejects
an enabled mcp_tool_policy with no rules, but the chart previously
defaulted to enabled=true with an empty rules list, which hard-fails
'pipelock check'. The default is now enabled=false; operators must
explicitly enable and provide at least one rule.

Refreshes README, CHANGELOG, docs/hosting/pipelock.md, docs/hosting/ai.md,
compose example pin comment, and pipelock.example.yaml to call out 2.5
highlights (Audit Packet v0 verifiers, SPIFFE-strict envelopes, scanner
attribution on MCP block receipts, pipelock doctor). Also fixes a stale
docs/hosting/mcp.md reference to the removed compose.example.pipelock.yml.

* chore(helm): fail helm template when mcp_tool_policy enabled with no rules

Adds a guard in asserts.tpl so an operator who sets
pipelock.mcpToolPolicy.enabled=true without populating
pipelock.mcpToolPolicy.rules gets a clear render-time error instead
of a container crash-loop with the pipelock validation message.

Per CodeRabbit feedback on #1913.

* Versions

---------

Co-authored-by: Juan José Mata <jjmata@jjmata.com>
This commit is contained in:
Josh
2026-05-24 07:50:44 -04:00
committed by GitHub
parent 98ca1608f4
commit ca895416a4
10 changed files with 196 additions and 22 deletions

View File

@@ -5,16 +5,22 @@ All notable changes to the Sure Helm chart will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
## [0.7.1] - 2026-05-31]
### Changed
- Bumped `pipelock.image.tag` from `2.0.0` to `2.2.0` (three minor releases behind latest). Floating `@v2` CI action pin picks up patch/minor updates automatically.
- Refreshed pipelock feature notes in the chart README, `docs/hosting/pipelock.md`, and `pipelock.example.yaml` to reference the upstream changelog instead of a single version.
- Bumped `pipelock.image.tag` from `2.2.0` to `2.5.0`. Picks up three releases of scanner, federation, and audit work — see the [pipelock changelog](https://github.com/luckyPipewrench/pipelock/blob/main/CHANGELOG.md) for the full surface.
- Refreshed pipelock feature notes in the chart README, `docs/hosting/pipelock.md`, and `pipelock.example.yaml` to call out 2.5 highlights (Audit Packet v0, request-body prompt-injection blocking, SPIFFE-strict inbound envelopes, scanner attribution on MCP block receipts).
- Expanded the `pipelock.extraConfig` escape-hatch comment to reference the new sections available in 2.5 (browser_shield, mediation_envelope, redaction, learn, media_policy, a2a_scanning, emit).
- Defaulted `pipelock.mcpToolPolicy.enabled` to `false`. Pipelock 2.x rejects an enabled `mcp_tool_policy` with no rules, so the prior chart default (`enabled: true`, empty rules) hard-failed config validation on startup. Operators who want tool policy active must now set `enabled: true` and provide at least one entry in `pipelock.mcpToolPolicy.rules`.
### Added
- `pipelock.requestBodyScanning` (pipelock 2.5+): structured config for scanning outbound request bodies for prompt-injection and bodies/sensitive headers for DLP payloads. Disabled by default to preserve existing chart behavior; opt in with `enabled: true`.
- `pipelock.healthWatchdog` (pipelock 2.4+): structured config for the wedge-detection watchdog. Operators can opt into per-subsystem detail in `/health` responses via `exposeSubsystems: true`.
- `pipelock.mcpToolPolicy.rules`: structured Helm values for rendering `mcp_tool_policy.rules`, including redirect-profile references.
- `asserts.tpl` guard that fails `helm template`/`helm install` when `pipelock.mcpToolPolicy.enabled=true` is paired with an empty `rules` list, surfacing the pipelock validation error at render time instead of container startup.
- README: CI scan status badge for the pipelock workflow.
## [0.6.9-alpha] - 2026-03-24
## [0.6.9] - 2026-03-31
### Changed
- Bumped `pipelock.image.tag` from `1.5.0` to `2.0.0`
@@ -58,7 +64,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Fixed
- Renamed `_asserts.tpl` to `asserts.tpl` — Helm's `_` prefix convention prevented guards from executing
## [0.6.7-alpha] - 2026-01-10
## [0.6.7] - 2026-01-31
### Added
- **Redis Sentinel support for Sidekiq high availability**: Application now automatically detects and configures Sidekiq to use Redis Sentinel when `redisOperator.mode=sentinel` and `redisOperator.sentinel.enabled=true`

View File

@@ -645,7 +645,7 @@ hpa:
- **Forward proxy** (port 8888): Scans outbound HTTPS from Faraday-based AI clients. Auto-injected via `HTTPS_PROXY` env vars when enabled.
- **MCP reverse proxy** (port 8889): Scans inbound MCP traffic from external AI assistants.
Recent pipelock releases add enhanced tool poisoning detection (full JSON schema scanning), per-read kill switch preemption, trusted domain allowlisting, MCP tool redirect profiles, signed action receipts, per-pattern DLP warn mode, and the `pipelock posture verify` / `pipelock session` CLIs. Process sandboxing and attack simulation are also available via `extraConfig` and CLI. See the [pipelock changelog](https://github.com/luckyPipewrench/pipelock/releases) for details.
Recent pipelock releases add the Audit Packet v0 schema and language-portable verifiers (Go, TypeScript, Rust), request-body prompt-injection blocking, SPIFFE-strict inbound mediation envelopes, scanner attribution on MCP block receipts, enhanced tool poisoning detection, per-read kill switch preemption, trusted domain allowlisting, MCP tool redirect profiles, signed action receipts, per-pattern DLP warn mode, learn-and-lock behavioural contracts, the wedge-detection health watchdog, and the `pipelock posture verify` / `pipelock session` / `pipelock doctor` CLIs. Browser Shield, process sandboxing, and attack simulation are available via `extraConfig` and CLI. See the [pipelock changelog](https://github.com/luckyPipewrench/pipelock/releases) for details.
### Enabling Pipelock
@@ -653,7 +653,7 @@ Recent pipelock releases add enhanced tool poisoning detection (full JSON schema
pipelock:
enabled: true
image:
tag: "2.2.0"
tag: "2.5.0"
mode: balanced # strict, balanced, or audit
```
@@ -677,12 +677,45 @@ pipelock:
mcpToolPolicy:
enabled: true
action: redirect # or use per-rule action overrides
rules:
- name: redirect-fetch
toolPattern: "^(fetch|web_fetch)$"
action: redirect
redirectProfile: safe-fetch
redirectProfiles:
safe-fetch:
exec: ["/pipelock", "internal-redirect", "fetch-proxy"]
reason: "Route fetch calls through audited proxy"
```
### Request body scanning (pipelock 2.5+)
Pipelock 2.5 added prompt-injection detection on outbound request bodies (JSON, form-encoded, raw text, WebSocket frames). When enabled, findings hard-block non-provider destinations even when `action: warn`; trusted provider hosts (OpenAI, Anthropic, etc.) remain exempt through the response-scanning exemption list.
```yaml
pipelock:
requestBodyScanning:
enabled: true
action: warn # warn or block
maxBodyBytes: 5242880 # 5 MB; fail-closed above this
scanHeaders: true
headerMode: sensitive # "sensitive" or "all"
```
Disabled by default. Roll out with `action: warn` first to observe findings in logs without blocking, then flip to `action: block` once the false-positive rate is acceptable.
### Health watchdog
The wedge-detection watchdog returns 503 on `/health` when a subsystem heartbeat (proxy hot path, MCP listener, rules-engine reload watcher) goes stale. Enabled by default in pipelock; the chart exposes the controls so operators can opt into per-subsystem detail in the health payload:
```yaml
pipelock:
healthWatchdog:
enabled: true
intervalSeconds: 2
exposeSubsystems: true # adds per-subsystem boolean map to /health
```
### Validating your config
Pipelock includes CLI tools for config validation:
@@ -693,6 +726,9 @@ pipelock simulate --config pipelock.yaml
# Score your config's security posture (0-100)
pipelock audit score --config pipelock.yaml
# Report whether configured protections are actually enforceable
pipelock doctor
```
### Exposing MCP to external AI assistants
@@ -811,7 +847,7 @@ See `values.yaml` for the complete configuration surface, including:
- `migrations.*`: strategy job or initContainer
- `simplefin.encryption.*`: enable + backfill options
- `cronjobs.*`: custom CronJobs
- `pipelock.*`: AI agent security proxy (forward proxy, MCP reverse proxy, DLP, injection scanning, trusted domains, tool redirect profiles, logging, serviceMonitor, ingress, PDB, extraConfig)
- `pipelock.*`: AI agent security proxy (forward proxy, MCP reverse proxy, DLP, injection scanning, request-body scanning, health watchdog, trusted domains, tool redirect profiles, logging, serviceMonitor, ingress, PDB, extraConfig)
- `service.*`, `ingress.*`, `serviceMonitor.*`, `hpa.*`
## Helm tests

View File

@@ -21,3 +21,18 @@ Mutual exclusivity and configuration guards
{{- if and $extEnabled (not $plEnabled) $requirePL -}}
{{- fail "pipelock.requireForExternalAssistant is true but pipelock.enabled is false. Enable pipelock (pipelock.enabled=true) when using rails.externalAssistant, or set pipelock.requireForExternalAssistant=false." -}}
{{- end -}}
{{/*
Pipelock 2.x rejects an enabled mcp_tool_policy with no rules; surface this
at helm template time instead of waiting for the container to crash-loop.
*/}}
{{- if $plEnabled -}}
{{- $mtp := .Values.pipelock.mcpToolPolicy | default (dict) -}}
{{- if hasKey $mtp "enabled" -}}
{{- if $mtp.enabled -}}
{{- if eq (len ($mtp.rules | default (list))) 0 -}}
{{- fail "pipelock.mcpToolPolicy.enabled=true requires at least one entry in pipelock.mcpToolPolicy.rules. Pipelock rejects an enabled tool policy with no rules." -}}
{{- end -}}
{{- end -}}
{{- end -}}
{{- end -}}

View File

@@ -65,6 +65,34 @@
{{- $chainWindow = int (.Values.pipelock.toolChainDetection.windowSize | default 20) -}}
{{- $chainGap = int (.Values.pipelock.toolChainDetection.maxGap | default 3) -}}
{{- end -}}
{{- $rbsEnabled := false -}}
{{- $rbsAction := "warn" -}}
{{- $rbsMaxBytes := 5242880 -}}
{{- $rbsScanHeaders := true -}}
{{- $rbsHeaderMode := "sensitive" -}}
{{- if .Values.pipelock.requestBodyScanning -}}
{{- if hasKey .Values.pipelock.requestBodyScanning "enabled" -}}
{{- $rbsEnabled = .Values.pipelock.requestBodyScanning.enabled -}}
{{- end -}}
{{- $rbsAction = .Values.pipelock.requestBodyScanning.action | default "warn" -}}
{{- $rbsMaxBytes = int (.Values.pipelock.requestBodyScanning.maxBodyBytes | default 5242880) -}}
{{- if hasKey .Values.pipelock.requestBodyScanning "scanHeaders" -}}
{{- $rbsScanHeaders = .Values.pipelock.requestBodyScanning.scanHeaders -}}
{{- end -}}
{{- $rbsHeaderMode = .Values.pipelock.requestBodyScanning.headerMode | default "sensitive" -}}
{{- end -}}
{{- $hwEnabled := true -}}
{{- $hwInterval := 2 -}}
{{- $hwExpose := false -}}
{{- if .Values.pipelock.healthWatchdog -}}
{{- if hasKey .Values.pipelock.healthWatchdog "enabled" -}}
{{- $hwEnabled = .Values.pipelock.healthWatchdog.enabled -}}
{{- end -}}
{{- $hwInterval = int (.Values.pipelock.healthWatchdog.intervalSeconds | default 2) -}}
{{- if hasKey .Values.pipelock.healthWatchdog "exposeSubsystems" -}}
{{- $hwExpose = .Values.pipelock.healthWatchdog.exposeSubsystems -}}
{{- end -}}
{{- end -}}
{{- $logFormat := "json" -}}
{{- $logOutput := "stdout" -}}
{{- $logIncludeAllowed := false -}}
@@ -128,6 +156,25 @@ data:
mcp_tool_policy:
enabled: {{ $mcpPolicyEnabled }}
action: {{ $mcpPolicyAction }}
{{- if and .Values.pipelock.mcpToolPolicy .Values.pipelock.mcpToolPolicy.rules }}
rules:
{{- range .Values.pipelock.mcpToolPolicy.rules }}
- name: {{ required "pipelock.mcpToolPolicy.rules[].name is required" .name | quote }}
tool_pattern: {{ required "pipelock.mcpToolPolicy.rules[].toolPattern is required" .toolPattern | quote }}
{{- if .argPattern }}
arg_pattern: {{ .argPattern | quote }}
{{- end }}
{{- if .argKey }}
arg_key: {{ .argKey | quote }}
{{- end }}
{{- if .action }}
action: {{ .action | quote }}
{{- end }}
{{- if .redirectProfile }}
redirect_profile: {{ .redirectProfile | quote }}
{{- end }}
{{- end }}
{{- end }}
{{- if and .Values.pipelock.mcpToolPolicy .Values.pipelock.mcpToolPolicy.redirectProfiles }}
redirect_profiles:
{{- toYaml .Values.pipelock.mcpToolPolicy.redirectProfiles | nindent 8 }}
@@ -140,6 +187,16 @@ data:
action: {{ $chainAction }}
window_size: {{ $chainWindow }}
max_gap: {{ $chainGap }}
request_body_scanning:
enabled: {{ $rbsEnabled }}
action: {{ $rbsAction }}
max_body_bytes: {{ $rbsMaxBytes }}
scan_headers: {{ $rbsScanHeaders }}
header_mode: {{ $rbsHeaderMode }}
health_watchdog:
enabled: {{ $hwEnabled }}
interval_seconds: {{ $hwInterval }}
expose_subsystems: {{ $hwExpose }}
logging:
format: {{ $logFormat }}
output: {{ $logOutput }}

View File

@@ -497,7 +497,7 @@ pipelock:
enabled: false
image:
repository: ghcr.io/luckypipewrench/pipelock
tag: "2.2.0"
tag: "2.5.0"
pullPolicy: IfNotPresent
imagePullSecrets: []
replicas: 1
@@ -530,8 +530,17 @@ pipelock:
originPolicy: rewrite # rewrite, forward, or strip
# MCP tool policy: pre-execution rules for tool calls (shell obfuscation, etc.)
mcpToolPolicy:
enabled: true
# Enable only when at least one rule is configured; pipelock rejects an
# enabled mcp_tool_policy with no rules.
enabled: false
action: warn
# Example:
# rules:
# - name: redirect-fetch
# toolPattern: "^(fetch|web_fetch)$"
# action: redirect
# redirectProfile: safe-fetch
rules: []
# Redirect profiles: route matched tool calls to audited handler programs instead
# of blocking. The handler returns a synthetic MCP response. Fail-closed on error.
# Example:
@@ -550,6 +559,24 @@ pipelock:
action: warn
windowSize: 20
maxGap: 3
# Request body scanning (pipelock 2.5+): detect prompt-injection payloads
# in outbound request bodies (JSON, form-encoded, raw text, WebSocket frames).
# In enforce mode, prompt-injection findings hard-block non-provider
# destinations even when action is "warn"; trusted provider hosts (OpenAI,
# Anthropic, etc.) remain exempt via the response_scanning exemption list.
requestBodyScanning:
enabled: false
action: warn # warn or block
maxBodyBytes: 5242880 # 5 MB; fail-closed above this
scanHeaders: true # scan request headers for DLP
headerMode: sensitive # "sensitive" or "all"
# Health watchdog (pipelock 2.4+): /health returns 503 when any subsystem
# heartbeat goes stale. Enabled by default in pipelock; exposed here so
# operators can opt into per-subsystem detail in the health payload.
healthWatchdog:
enabled: true
intervalSeconds: 2
exposeSubsystems: false # include per-subsystem map in /health response
service:
type: ClusterIP
resources:
@@ -601,8 +628,10 @@ pipelock:
includeBlocked: true
# Escape hatch: ADDITIONAL config sections appended to pipelock.yaml.
# Use for sections not covered by structured values above (session_profiling,
# data_budget, adaptive_enforcement, kill_switch, sandbox, reverse_proxy, etc.)
# Use for sections not covered by structured values above. Examples:
# session_profiling, data_budget, adaptive_enforcement, kill_switch, sandbox,
# reverse_proxy, redaction, browser_shield, mediation_envelope, learn,
# media_policy, a2a_scanning, emit (OTel agent.threat.detection attributes).
# Do NOT duplicate keys already rendered above - behavior is parser-dependent.
extraConfig: {}

View File

@@ -112,7 +112,7 @@ x-rails-env: &rails_env
services:
pipelock:
image: ghcr.io/luckypipewrench/pipelock:latest # pin to a specific version (e.g., :2.2.0) for production
image: ghcr.io/luckypipewrench/pipelock:latest # pin to a specific version (e.g., :2.5.0) for production
container_name: pipelock
hostname: pipelock
restart: unless-stopped

View File

@@ -450,13 +450,18 @@ Pipelock scans for prompt injection, DLP violations, and tool poisoning. The ext
**`NO_PROXY` behavior (Helm/Kubernetes only):** The Helm chart's env template sets `NO_PROXY` to include `.svc.cluster.local` and other internal domains. This means in-cluster agent URLs (like `http://agent.namespace.svc.cluster.local:18789`) bypass the forward proxy and go directly. If your agent is in-cluster, its traffic won't be forward-proxy scanned (but MCP callbacks from the agent are still scanned by the reverse proxy). Docker Compose deployments use a different `NO_PROXY` set; check your compose file for the exact values.
**`mcpToolPolicy` note:** The Helm chart's `pipelock.mcpToolPolicy.enabled` defaults to `true`. If you haven't defined any policy rules, disable it:
**`mcpToolPolicy` note:** The Helm chart's `pipelock.mcpToolPolicy.enabled` defaults to `false`. Pipelock rejects an enabled tool policy with no rules, so the chart ships it off by default. To turn it on, define at least one rule and set `enabled: true`:
```yaml
# Helm values
pipelock:
mcpToolPolicy:
enabled: false
enabled: true
action: warn
rules:
- name: example
toolPattern: "^shell$"
action: block
```
See the [Pipelock documentation](https://github.com/luckyPipewrench/pipelock) for tool policy configuration details.

View File

@@ -231,7 +231,7 @@ Pipelock provides:
- **Tool poisoning detection**: Prevents malicious tool call sequences
- **Policy enforcement**: Block or warn on suspicious patterns
See the [Pipelock documentation](pipelock.md) and the example configuration in `compose.example.pipelock.yml` for setup instructions.
See the [Pipelock documentation](pipelock.md) and the example configuration in `compose.example.ai.yml` for setup instructions.
### Network Security

View File

@@ -77,13 +77,13 @@ Enable Pipelock in your Helm values:
pipelock:
enabled: true
image:
tag: "2.2.0"
tag: "2.5.0"
mode: balanced
```
This creates a separate Deployment, Service, and ConfigMap. The chart auto-injects `HTTPS_PROXY`/`HTTP_PROXY`/`NO_PROXY` into web and worker pods.
Recent pipelock releases add trusted domain allowlisting, MCP tool redirect profiles, enhanced tool poisoning detection (full JSON schema scanning), per-read kill switch preemption, signed action receipts, per-pattern DLP warn mode, and the `pipelock posture verify` / `pipelock session` CLI commands. See the [pipelock changelog](https://github.com/luckyPipewrench/pipelock/releases) for details.
Recent pipelock releases add the Audit Packet v0 schema and language-portable verifiers (Go/TypeScript/Rust), request-body prompt-injection blocking, SPIFFE-strict inbound mediation envelopes, scanner attribution on MCP block receipts, trusted domain allowlisting, MCP tool redirect profiles, enhanced tool poisoning detection, per-read kill switch preemption, signed action receipts, per-pattern DLP warn mode, learn-and-lock behavioural contracts, the wedge-detection health watchdog, and the `pipelock posture verify` / `pipelock session` / `pipelock doctor` CLI commands. See the [pipelock changelog](https://github.com/luckyPipewrench/pipelock/releases) for details.
### Exposing MCP to external agents (Kubernetes)
@@ -149,6 +149,7 @@ The `pipelock.example.yaml` file (Docker Compose) or ConfigMap (Helm) controls s
| `trusted_domains` | Allow internal services whose public DNS resolves to private IPs |
| `forward_proxy` | Outbound HTTPS scanning (tunnel timeouts, idle timeouts) |
| `dlp` | Data loss prevention (scan env vars, built-in patterns) |
| `request_body_scanning` | Scan outbound request bodies for prompt-injection and bodies/sensitive headers for DLP (pipelock 2.5+) |
| `response_scanning` | Scan LLM responses for prompt injection |
| `mcp_input_scanning` | Scan inbound MCP requests |
| `mcp_tool_scanning` | Validate tool calls, detect drift |
@@ -156,6 +157,7 @@ The `pipelock.example.yaml` file (Docker Compose) or ConfigMap (Helm) controls s
| `mcp_session_binding` | Pin tool inventory, detect manipulation |
| `tool_chain_detection` | Multi-step attack patterns |
| `websocket_proxy` | WebSocket frame scanning (disabled by default) |
| `health_watchdog` | Wedge-detection on subsystem heartbeats, returns 503 on stall (pipelock 2.4+) |
| `logging` | Output format (json/text), verbosity |
For the Helm chart, most sections are configurable via `values.yaml`. For additional sections not covered by structured values (session profiling, data budgets, kill switch, sandbox, reverse proxy, adaptive enforcement), use the `extraConfig` escape hatch:

View File

@@ -1,12 +1,16 @@
# Pipelock configuration for Docker Compose
# See https://github.com/luckyPipewrench/pipelock for full options.
#
# Recent additions: trusted_domains, redirect profiles, attack simulation,
# security scoring, process sandbox, enhanced tool poisoning detection, signed
# action receipts, per-pattern DLP warn mode, and the `pipelock posture verify`
# / `pipelock session` CLIs.
# Recent additions (2.5): Audit Packet v0 schema with Go/TypeScript/Rust
# verifiers, request-body prompt-injection blocking, SPIFFE-strict inbound
# mediation envelopes, scanner attribution on MCP block receipts, wedge-
# detection health watchdog, learn-and-lock behavioural contracts, trusted
# domains, redirect profiles, attack simulation, security scoring, process
# sandbox, signed action receipts, per-pattern DLP warn mode, and the
# `pipelock posture verify` / `pipelock session` / `pipelock doctor` CLIs.
# Run `pipelock simulate --config <file>` to test your config against 24 attack scenarios.
# Run `pipelock audit score --config <file>` for a security posture score (0-100).
# Run `pipelock doctor` to verify configured protections are actually enforceable.
version: 1
mode: balanced
@@ -72,3 +76,23 @@ tool_chain_detection:
action: warn
window_size: 20
max_gap: 3
# Request body scanning (pipelock 2.5+): detect prompt-injection payloads in
# outbound request bodies (JSON, form-encoded, raw text, WebSocket frames).
# In enforce mode, prompt-injection findings hard-block non-provider
# destinations even when action is "warn". Trusted provider hosts (OpenAI,
# Anthropic, etc.) remain exempt via the response_scanning exemption list.
request_body_scanning:
enabled: false
action: warn
max_body_bytes: 5242880
scan_headers: true
header_mode: sensitive
# Health watchdog (pipelock 2.4+): /health returns 503 when any subsystem
# heartbeat goes stale. Enabled by default; set expose_subsystems true to
# include a per-subsystem boolean map in /health responses.
health_watchdog:
enabled: true
interval_seconds: 2
expose_subsystems: false