Skip to content

Latest commit

 

History

History
365 lines (283 loc) · 14.5 KB

openclaw.md

File metadata and controls

365 lines (283 loc) · 14.5 KB

OpenClaw + Pipelock Deployment Guide

Pipelock sits between your AI agent and the OpenClaw gateway when the agent's MCP client is configured to use the Pipelock wrapper or generated MCP launcher contract. It scans that mediated MCP traffic for secret exfiltration, prompt injection, and tool poisoning. This guide covers deploying pipelock as a security layer for OpenClaw.

Why

CVE-2026-25253 affects OpenClaw through version 2026.1.28. Its Control UI accepts an unvalidated gateway URL and automatically sends the stored gateway token when connecting. Token theft can lead to gateway compromise even when the gateway listens only on loopback. Upgrade to 2026.1.29 or later; the fix requires confirmation of a new gateway URL before connecting.

For MCP calls routed through its proxy, Pipelock applies configured tool policy, input scanning, and response scanning to tool invocations, arguments, and results. These controls don't protect direct gateway connections. Pipelock doesn't provide an inbound WebSocket MCP listener; WebSocket upstreams require stdio mode.

Quick Start

1. Install pipelock:

Use GitHub CLI v2.102.0 or later for attestation verification; this release fixes a workflow signer-matching vulnerability.

Run the archive commands in a fresh directory. If verification fails or provenance cannot be retrieved, stop without extracting or installing the archive. Use another fresh directory before retrying so an existing download does not prevent the commands from running.

# From source (Go 1.26+)
git clone --branch v3.7.0 --depth 1 https://github.com/pipelab-org/pipelock.git
make -C pipelock install

# Or download the v3.7.0 Linux amd64 archive
gh release download v3.7.0 --repo luckyPipewrench/pipelock --pattern pipelock_3.7.0_linux_amd64.tar.gz &&
  gh attestation verify pipelock_3.7.0_linux_amd64.tar.gz --repo luckyPipewrench/pipelock --signer-workflow luckyPipewrench/pipelock/.github/workflows/release.yaml &&
  tar xzf pipelock_3.7.0_linux_amd64.tar.gz &&
  sudo install -m 0755 pipelock /usr/local/bin/pipelock

# Or Homebrew (macOS)
brew install luckyPipewrench/tap/pipelock

2. Generate a wrapped config:

Input must be a JSON file with a top-level mcpServers object.

# Wrap all MCP servers in your config with pipelock scanning
pipelock generate mcporter -i servers.json -o wrapped.json

# Or modify in-place (creates .bak backup)
pipelock generate mcporter -i servers.json --in-place --backup

3. Restart your agent. MCP traffic from that wrapped config now routes through pipelock.

Architecture

┌─────────────────────────────────────────────────────────┐
│                    Agent Host                           │
│                                                         │
│  ┌──────────┐    ┌──────────┐    ┌──────────────────┐   │
│  │          │    │          │    │                  │   │
│  │  Agent   │───>│ Pipelock │───>│ OpenClaw Gateway │   │
│  │          │    │ MCP Proxy│    │   (ws/http)      │   │
│  │ (secrets,│    │          │    │                  │   │
│  │  no net) │    │ (no      │    └──────────────────┘   │
│  │          │    │  secrets, │           │               │
│  └──────────┘    │  scans   │           │               │
│                  │  traffic)│           ▼               │
│                  └──────────┘    ┌──────────────┐       │
│                                 │   Internet   │       │
│                                 └──────────────┘       │
└─────────────────────────────────────────────────────────┘

In an enforced deployment, the agent has secrets but no direct network access. Pipelock has no agent secrets and provides policy-controlled network egress. Deployment controls such as Docker networking, host containment, firewall rules, or K8s NetworkPolicy enforce this boundary. This capability separation prevents a compromised agent from exfiltrating secrets directly.

Two Protection Layers

Layer 1: MCP Proxy (tool calls and responses)

Wraps the OpenClaw gateway connection with bidirectional scanning:

  • Response scanning detects prompt injection in tool results
  • Input scanning catches DLP violations and injection in tool arguments
  • Tool scanning detects poisoned tool descriptions and rug-pull drift
  • Tool policy blocks dangerous tool invocations (shell commands, file access)
  • Chain detection catches suspicious tool call sequences (read-then-exfil patterns)
  • Session binding pins the tool inventory per session to prevent tool swapping

Layer 2: HTTP Proxy (fetch and forward)

When the agent makes outbound HTTP requests through pipelock's fetch proxy:

  • Ordered URL scanning (CRLF, path traversal, destination policy, DLP, SSRF, rate limiting, entropy checks)
  • Response injection detection on fetched content
  • Data budget tracking per domain

Configuration

Stdio-to-WebSocket (most common)

Your agent talks to pipelock over stdin/stdout. Pipelock connects to the OpenClaw gateway over WebSocket.

{
  "mcpServers": {
    "openclaw": {
      "command": "pipelock",
      "args": [
        "mcp", "proxy",
        "--config", "/path/to/pipelock.yaml",
        "--env", "OPENCLAW_GATEWAY_URL",
        "--env", "OPENCLAW_GATEWAY_TOKEN",
        "--upstream", "ws://localhost:3000/mcp"
      ],
      "env": {
        "OPENCLAW_GATEWAY_URL": "ws://localhost:3000",
        "OPENCLAW_GATEWAY_TOKEN": "your-token-here"
      }
    }
  }
}

Stdio-to-HTTP

If your OpenClaw gateway exposes an HTTP MCP endpoint:

{
  "mcpServers": {
    "openclaw": {
      "command": "pipelock",
      "args": [
        "mcp", "proxy",
        "--config", "/path/to/pipelock.yaml",
        "--upstream", "http://localhost:3000/mcp"
      ]
    }
  }
}

Using generate mcporter

Instead of manually editing configs, use the generator:

# Preview what will change (outputs to stdout)
pipelock generate mcporter -i mcporter.json

# Write to a new file
pipelock generate mcporter -i mcporter.json -o wrapped.json

# Modify in-place with backup
pipelock generate mcporter -i mcporter.json --in-place --backup

# Custom pipelock binary path and config
pipelock generate mcporter -i mcporter.json \
  --pipelock-bin /usr/local/bin/pipelock \
  --config /etc/pipelock/pipelock.yaml

The generator is idempotent. Running it twice produces identical output. Servers already wrapped with pipelock are detected and skipped.

Kubernetes Sidecar Deployment

For enforced cluster deployments, generate a companion-proxy topology and point it at the OpenClaw MCP endpoint:

pipelock init sidecar \
  --inject-spec agent-deployment.yaml \
  --mcp-upstream http://openclaw-gateway:3000/mcp \
  --mcp-server-name openclaw \
  --output enforced.yaml
kubectl apply -f enforced.yaml

The generated agent workload gets HTTPS_PROXY and HTTP_PROXY for HTTP egress, plus two MCP launcher inputs:

  • PIPELOCK_MCP_PROXY_URL=http://<pipelock-service>:8889
  • PIPELOCK_MCP_CONFIG=/etc/pipelock/mcp/mcp.json

The mounted mcp.json contains an mcpServers.openclaw entry whose URL points at Pipelock's MCP listener. Configure your agent launcher to read PIPELOCK_MCP_CONFIG, or configure the MCP client directly from PIPELOCK_MCP_PROXY_URL. The generated NetworkPolicy limits the agent pod to DNS plus the Pipelock HTTP and MCP proxy ports, so direct egress to the OpenClaw gateway is outside the generated agent boundary. That boundary only holds if your CNI actually enforces the policy — see NetworkPolicy Semantics for how to prove it with a positive control followed by a negative test.

Same-pod sidecar wiring is still useful for local prototypes, but it relies on the agent honoring proxy settings and is not the generated enforced topology:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: agent
spec:
  template:
    spec:
      # Room for the receipt-group close at shutdown; Kubernetes defaults to 30 s
      terminationGracePeriodSeconds: 600
      initContainers:
        - name: pipelock-init
          image: ghcr.io/luckypipewrench/pipelock-init:3.7.0
          command: ["cp", "/pipelock", "/shared-bin/pipelock"]
          volumeMounts:
            - name: shared-bin
              mountPath: /shared-bin

      containers:
        - name: agent
          image: your-agent:latest
          env:
            - name: HTTPS_PROXY
              value: "http://localhost:8888"
          volumeMounts:
            - name: shared-bin
              mountPath: /usr/local/bin/pipelock
              subPath: pipelock
            - name: config
              mountPath: /etc/pipelock
              readOnly: true

        - name: pipelock
          image: ghcr.io/luckypipewrench/pipelock:3.7.0
          args: ["run", "--listen", "0.0.0.0:8888"]
          ports:
            - containerPort: 8888
          volumeMounts:
            - name: config
              mountPath: /etc/pipelock
              readOnly: true

      volumes:
        - name: config
          configMap:
            name: pipelock-config
        - name: shared-bin
          emptyDir: {}

If you keep a same-pod prototype, do not treat a pod-level NetworkPolicy as a container-level wall between containers in that same pod. Kubernetes NetworkPolicy selects pods, not individual containers, so it cannot stop one container from reaching destinations another container in the same pod can reach. For enforced cluster isolation, prefer the generated companion-proxy topology above, where the agent pod and Pipelock service are separate policy subjects.

For a separate-agent-pod topology, a NetworkPolicy should restrict the agent pod's egress to DNS and the Pipelock Service:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: agent-egress
spec:
  podSelector:
    matchLabels:
      app: agent
  policyTypes:
    - Egress
  egress:
    # Allow DNS resolution.
    - to:
        - namespaceSelector: {}
      ports:
        - port: 53
          protocol: UDP
    # Allow traffic only to pods selected as the Pipelock proxy Service backend.
    - to:
        - podSelector:
            matchLabels:
              app: pipelock
      ports:
        - port: 8888

Controls for Mediated Traffic

These controls apply when the relevant traffic passes through Pipelock. They do not intercept an attacker's direct connection to the OpenClaw gateway in the CVE-2026-25253 attack chain.

Traffic or Operation Pipelock Control Layer
Gateway token theft through a direct WebSocket connection Outside MCP wrapper coverage; upgrade OpenClaw to the fixed release --
Sandbox disable via a mediated MCP tool call Configured tool policy can deny matching tool invocations MCP proxy
Shell/exec operation via a mediated MCP tool call Configured tool policy can deny matching tool names and arguments; direct gateway node.invoke calls bypass it MCP proxy
Data exfiltration via tool args Input scanning catches secrets in outbound calls MCP proxy
Prompt injection in tool results Response scanning detects injection attempts MCP proxy
Read-then-exfil tool sequences Chain detection catches multi-step patterns MCP proxy
Outbound HTTP exfiltration Ordered URL scanning, DLP on request URLs HTTP proxy

Pipelock does not patch the CVE itself; upgrade OpenClaw as described above. Pipelock scans traffic routed through its proxies; direct gateway connections remain outside that coverage.

TLS Interception

When using pipelock as an HTTP forward proxy (HTTPS_PROXY), CONNECT tunnels are opaque by default: pipelock only sees the hostname, not the request body or response content. Enabling TLS interception closes this gap by performing a MITM on HTTPS connections, giving you full DLP on request bodies and response injection detection through CONNECT tunnels.

To enable it:

  1. Generate a CA and enable TLS interception (see the TLS Interception Guide)
  2. Trust the CA in your agent's runtime:
# Node.js agents
export NODE_EXTRA_CA_CERTS=~/.pipelock/ca.pem

# Python agents
export SSL_CERT_FILE=~/.pipelock/ca.pem

MCP proxy mode (stdio wrapping and --upstream) does not require TLS interception. It scans traffic directly without certificates.

Troubleshooting

Connection refused to upstream

Check that the OpenClaw gateway is running and accessible at the configured URL:

# For WebSocket upstreams
wscat -c ws://localhost:3000/mcp

# For HTTP upstreams
curl http://localhost:3000/mcp

DLP false positives

If pipelock blocks legitimate traffic containing strings that match a non-core DLP pattern, add an exact-name suppression rule to your config. Core DLP names cannot be suppressed and require a pattern precision fix:

suppress:
  - rule: "Internal Provider API Key"
    path: "*.example.com"
    reason: "Known safe endpoint"

Tool policy blocks

If pipelock blocks a tool invocation your agent needs:

mcp_tool_policy:
  enabled: true
  action: warn  # Change from "block" to "warn" for debugging
  rules:
    - name: "allow my tool"
      tool_pattern: "^your_tool_name$"
      action: warn

Checking what pipelock scanned

Enable verbose logging by including allowed (non-blocked) events:

logging:
  include_allowed: true
  include_blocked: true

Or check the structured audit log for specific events.

See Also