lockhttp

module
v0.8.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 7, 2026 License: Apache-2.0

README

CI Latest release Go version

Let any AI agent use the web: reads of trusted hosts pass,
anything that sends data or reaches an unknown host waits for you.

An agent (here Claude Code, left, in a lea container) and the approval screen (right). Drawn in the console's frame from before the hub: today you answer in lox run.

Quick start · How it works · Docs · Lock Family · lockhttp.com


lockhttp is a Lock of the Lock Family, harness security for AI agents. It is the proxy every outbound HTTP(S) request of your agent goes through. Reads of hosts you trust pass; anything else waits for your approval on lockhub, where the agent cannot reach it.

[!NOTE] Pre-release (v0.8.x), built on lockkit v0.13.0. Command names are fixed; flags may still move. Design decisions: docs/decisions.md.

Why lockhttp

  • Per request, not per domain. An allowlist lets a host's writes through with its reads. lockhttp keeps reads free and holds writes, uploads and unknown hosts for a human.
  • Approval outside the agent. Each held request becomes a NeverAuto ticket on lockhub, answered by a human in lox run. Nothing in the agent's process can switch it off.
  • Credentials the agent never holds. The gate can inject an API token for one host and port; a credential sent to the wrong host is refused.
  • Traced. Every decision is tied to the container, the agent and the session that asked.

In-agent approval is a convenience; a separate approval process is a boundary.

Install

brew trust davidgodefroid/tap
brew install davidgodefroid/tap/lox davidgodefroid/tap/lockhttp
brew install davidgodefroid/tap/lea

lockhttp runs in Docker: Homebrew installs the lockhttp launcher, which runs every command in the release's signed image. lox is lockhub's CLI, and the gate runs inside lea. The whole family instead: brew install davidgodefroid/tap/lockfamily.

Without Homebrew, the signed install script of a release:

V=vX.Y.Z
curl -fsSLO "https://raw.githubusercontent.com/DavidGodefroid/lockhttp/$V/scripts/install.sh"
less install.sh
LOCKHTTP_VERSION=$V sh install.sh

Linux and macOS; on Windows, WSL 2 with Docker Desktop. The launcher, its commands and the setup by hand: docs/install.md.

Quick start

  1. In lea's projects directory, add the lock. lox add lockhttp asks only for its name, writes the policy and starts the console:

    cd ~/projects
    lox add lockhttp
    
  2. In a terminal of its own, outside lea and any agent, keep lox run open. Every held request shows up there:

    lox run
    
  3. Start lea with lockhttp on (lea stop first if it already runs):

    LEA_LOCKHTTP=1 lea
    
  4. Ask your agent to read the docs of a trusted site: it goes through. Ask it to post somewhere: the request waits for your y.

lockhttp is a proxy, so it works with any agent and any HTTP client inside lea's containers (lea runs Claude Code today). The contract with lea: docs/lea.md.

Highlights

👤 Never answered automatically
Every held request is a NeverAuto ticket: a human answers it. Only a free rule you confirmed lets a request pass unasked.

🔑 Credentials injected
A policy inject entry has the gate add an Authorization header from its own secrets file. The agent never holds the token.

🔁 LLM APIs checked as a relay
With TLS decryption, the Claude API's mcp_servers, server tools and Files API wait for a human; plain messages pass.

🧱 Fail closed
No console: asks are refused at once. Unknown source, undecodable policy, an error while deciding: deny.

More: the verdicts, refusal codes and the Claude API rules, and the policy keys.

How it works

Three pieces, each in a container of its own, and the hub.

 agent container (internal network only)
        │ HTTP(S)_PROXY
        ▼
 lockhttp gate  ── FREE ──▶ squid ──▶ Internet
        │ ASK                ▲
        ▼                    │ on y
 lockhub ── ticket ──▶ you, in lox run
        ·
 lockhttp console: serves the approved policy to the gate
  1. The agent's HTTP client sends every request to the gate. In lea the agent's container has no other route out.
  2. The gate decides each request with the policy the console serves it. It never reads a policy file.
  3. A free request goes out through squid. A request that needs a human is held (60 s by default) as a signed ticket on the hub.
  4. With a local CA and the signer, the gate decrypts HTTPS and decides each request by method, path, headers and body. Without them, it decides a CONNECT at the domain only.

The full diagram, verdicts, refusal codes, the Claude API checks and the limits: docs/how-it-works.md.

Safety model

  • The gate is the enforcement point. The console is the only place the policy loosens; the hub's facades the only place a request is approved.
  • OS separation. The console runs as its own account in its own container; the kernel checks the gate's uid on its socket.
  • The AI tightens, the human loosens. Any change that widens what passes without a human waits for your :review in the console.
  • Audit. The gate's JSONL log and the console's audit share a request_id, never a body, a query string or a header value.
  • Known limits. Without decryption a CONNECT opens reads and writes, and whoever can run docker can reach the console's container.

Every rule: docs/safety.md. Threat model: docs/security-model.md.

Documentation

Doc What it covers
docs/install.md install paths, the launcher's commands, the setup with lea by hand
docs/how-it-works.md the pieces, verdicts, what the agent sees, the Claude API checks, limits
docs/configuration.md the policy file, every profile key, policy examples
docs/policy.md the policy reference: evaluation order, credential injection, shadow mode, loosenings
docs/usage.md every command and flag, exit codes, files, audit records
docs/docker.md the image, its accounts and volumes, update, migrating from a host install
docs/lea.md the integration contract with lea
docs/safety.md the safety model in full
docs/security-model.md threats, parades, residual risks
docs/decisions.md design decisions
CHANGELOG.md what changed, release by release

The site, lockhttp.com, is built from site/.

The Lock Family

Repo What it does
lockfamily The family site (lockfamily.dev) and the one-line installer.
locksql SQL databases: the agent queries, PII comes back masked; connections and writes wait for you.
lockmq RabbitMQ: masked queue inspection; connections, peeks and unmasked reads wait for you.
lockfile Files (S3, SFTP, disk): the agent asks yes/no questions about files it never reads.
lockhttp Outbound HTTP(S): reads of trusted hosts pass; anything that sends data or reaches an unknown host waits for you.
locklog Logs: masked, bounded log search; the agent reads the logs, not the people in them.
lockssh Commands over SSH: allow-listed commands run at once, the rest waits for you; the key never leaves the console.
lockhub The approval hub and its lox CLI: lox run approves outside the agent's harness and never sees values in clear.
lockkit The shared Go core of every Lock: console, policies, masking, signed tickets, audit, MCP.
lea Runs many agents in containers, wired to the Locks.

Contributing · Security · License

  • Contributing: CONTRIBUTING.md. Build with CGO_ENABLED=0 go build ./cmd/lockhttp (Go 1.26+).
  • Security: report a vulnerability privately, see SECURITY.md.
  • License: Apache License 2.0, see LICENSE and NOTICE.

Directories

Path Synopsis
cmd
lockhttp command
Command lockhttp is the proxy every outbound HTTP request of an AI agent goes through: reads of trusted hosts pass, anything that sends data, triggers an action or reaches an unknown host waits for a human in a console the agent cannot reach.
Command lockhttp is the proxy every outbound HTTP request of an AI agent goes through: reads of trusted hosts pass, anything that sends data, triggers an action or reaches an unknown host waits for a human in a console the agent cannot reach.
internal
ca
Package ca is lockhttp's local certificate authority: one per installation (P-256, pathlen 0, 90 days), trusted only inside lea's containers, and the 24-hour leaf certificates the signer issues for the gate's MITM.
Package ca is lockhttp's local certificate authority: one per installation (P-256, pathlen 0, 90 days), trusted only inside lea's containers, and the 24-hour leaf certificates the signer issues for the gate's MITM.
decide
Package decide is lockhttp's decision engine: one request (a CONNECT seen at the domain, or a decrypted or plain HTTP request) and the approved policy in, a verdict out: FREE, ASK or DENY.
Package decide is lockhttp's decision engine: one request (a CONNECT seen at the domain, or a decrypted or plain HTTP request) and the approved policy in, a verdict out: FREE, ASK or DENY.
gate
Package gate is lockhttp's data plane: the HTTP(S) proxy every request of the agents goes through.
Package gate is lockhttp's data plane: the HTTP(S) proxy every request of the agents goes through.
httpconsole
Package httpconsole is lockhttp's console backend for lockkit: the method the gate calls (policy.get) and the policy read from the console account's config file.
Package httpconsole is lockhttp's console backend for lockkit: the method the gate calls (policy.get) and the policy read from the console account's config file.
policy
Package policy is lockhttp's policy: the profile the human writes in the console account's config file, in canonical form.
Package policy is lockhttp's policy: the profile the human writes in the console account's config file, in canonical form.
product
Package product declares lockhttp's names for lockkit and its refusal codes.
Package product declares lockhttp's names for lockkit and its refusal codes.
signer
Package signer keeps the CA key away from the gate (decision D3): the signer process alone reads the key and issues leaf certificates over a Unix socket to the uids it allows; the gate asks it for each host it decrypts.
Package signer keeps the CA key away from the gate (decision D3): the signer process alone reads the key and issues leaf certificates over a Unix socket to the uids it allows; the gate asks it for each host it decrypts.
wire
Package wire is the protocol between the gate (a lockkit client) and the console: the methods, their parameters and results, and the audit record both sides write.
Package wire is the protocol between the gate (a lockkit client) and the console: the methods, their parameters and results, and the audit record both sides write.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL