Skip to main content
Glama
README.md
# pod — least-privilege compiler for AI agents

[![CI](https://github.com/suhui-organization/pod/actions/workflows/ci.yml/badge.svg)](https://github.com/suhui-organization/pod/actions/workflows/ci.yml)
[![Sponsor](https://img.shields.io/badge/Sponsor-GitHub%20Sponsors-ea4aaa?logo=github)](https://github.com/sponsors/suhui-organization)

> Your agent ran for a week. pod compiles what it actually did into the smallest policy it needs.
>
> 让 AI Agent 只拥有它真正需要的权限——从真实行为编译最小权限策略。

**Record → compile → enforce → prove.**

Most agent security tools stop at one of two places: a scanner that tells you what your agent *could* touch, or a gateway that asks you to *hand-write* a policy. pod closes the loop — run your agent in record-only mode for a few days, compile a least-privilege policy from its real tool calls, enforce it, and keep tamper-evident evidence for everything that ran.

```text
record real calls ──▶ compile least-privilege policy ──▶ enforce (deny > approve > allow)
       │                        │                                  │
       │                        │                                  ▼
       │                        │                    ┌──────────────────────────┐
       └── SHA-256 hash chain ───┴───────────────────▶│ tamper-evident audit     │
          (every call, hashes only)                  │ verify / export evidence │
                                                     └──────────────────────────┘
```

## 中文速览

- **不是又一个 MCP 网关**:网关让你手写策略;pod 从 agent 的真实行为里**编译**出最小权限策略。
- **闭环**:`pod record`(只录不拦)→ `pod policy draft`(生成策略 + 与基线 diff)→ 人工复核 → `pod serve`(执法)。
- **证据**:每一次工具调用进入 SHA-256 哈希链,可校验、可导出为证据包(敏感内容只存哈希)。
- **本地优先**:策略、审计、密钥不出你的机器;Pod Cloud 是可选控制平面。

## See it in 5 minutes

No agent, no account, no data leaves your machine — everything runs in a temp directory:

```bash
git clone https://gitee.com/suhuisoftwares/pod.git && cd pod
pnpm install && pnpm build
bash scripts/demo-least-privilege.sh
```

It seeds a realistic week of tool calls (reads, writes, a delete, and one `.env` access), then compiles a policy from that corpus and diffs it against a permissive baseline:

```text
## 策略 diff(baseline → draft)

| server     | tool                 | baseline | draft      | 变化     |
|------------|----------------------|----------|------------|----------|
| *          | *                    | allow    | deny       | 默认决策 |
| filesystem | read_file            | allow    | deny       | 收紧     |
| filesystem | write_file           | allow    | approve    | 收紧     |
| filesystem | delete_file          | allow    | deny       | 收紧     |
| github     | create_pull_request  | allow    | approve    | 收紧     |
| shell      | execute_command      | allow    | approve    | 收紧     |
| filesystem | get_file_info        | allow    | (unlisted) | 移除     |

**汇总**:收紧 8 · 新增 0 · 移除 1 · 放宽 0
```

Two details matter here: `read_file` is locked down because it touched `.env` **once** (observation beats guessing), and `get_file_info` is removed because it never appeared in the corpus (least privilege = don't grant what you didn't observe).

## Install

```bash
# macOS / Linux — builds from source, no npm account needed
# 链接钉在发布版上(可复现):想跟主干就把 v0.4.2 换成 main
curl -fsSL https://gitee.com/suhuisoftwares/pod/raw/v0.4.2/scripts/install.sh | sh
# 主源连不上时用 GitHub 镜像(同一个脚本):
# curl -fsSL https://raw.githubusercontent.com/suhui-organization/pod/v0.4.2/scripts/install.sh | sh
pod --help
```

The installer clones `v0.4.2` to `~/.pod/src`, builds, and puts `pod` in `~/.local/bin`. Override with `POD_SRC`, `POD_BIN_DIR`, `POD_REPO_URL`, `POD_VERSION`(`POD_VERSION=main` 跟主干)。

**中文 / English**:CLI 输出支持中英切换——`pod --lang en-US <cmd>`,或设一次
`POD_LANG=en-US`(也会读 `LC_ALL` / `LANG`)。默认中文;未翻译的句子原样显示,
不会出现空白或 key 名。`pod guard` 与 `pod harden` 的报表、威胁目录与交付物
**整篇有英文**(含 finding 正文与策略草稿的判定依据),由 CI 断言守门。
覆盖进度自查:`bash scripts/i18n-coverage.sh`
(列出还没英文词条的串和词表里的僵尸键,`--strict` 有缺口时退出 1);控制台另有
真机逐页验收 `bash scripts/web-acceptance.sh`(指到 k8s 后端、无头 Chrome 点一遍,
断言"每页都渲染了内容且没有非数据中文")。

### Run the MCP gateway as a container

同一个网关也能以自包含镜像运行:镜像里已经构建好 CLI、预装了上游 filesystem server,
默认用 `baseline` 策略(只读工具放行,写操作进审批),从 stdio 暴露 MCP。

```bash
docker build -f deploy/Dockerfile.mcp -t pod-mcp .
docker run -i --rm pod-mcp        # 接到任意 MCP 客户端即可(stdio)
```

要换成别的上游 server 或策略,覆盖 entrypoint 参数即可;默认等价于
`pod serve --agent glama --server filesystem --command mcp-server-filesystem --arg /workspace`。
(公开目录收录时要求的检查也是这两步:进程能启动、能响应 `initialize` / `tools/list`。)

Requires **Node.js ≥ 22.13** (pnpm 11's runtime floor) and git.

## What's in this repo

一个仓库包含完整闭环:本地在 agent 机器上执法,云端(可选)做跨机器视图。

| 路径 | 是什么 | 怎么装 |
|---|---|---|
| `packages/` | 核心库:策略求值、审计哈希链、网关、能力图、控制平面姿态、身份/委托/JIT、扫描器 | `pnpm install && pnpm build` |
| `apps/cli` | `pod` 命令行(网关 + 策略编译 + 证据 + 控制平面命令) | `bash scripts/install.sh` |
| `apps/web` | 本地控制台(`pod ui`:读为主,写操作只有纳管/移除) | 随 CLI 构建 |
| `cloud/server` | 可选云端控制平面后端(FastAPI):agent 注册、审计同步、策略中心、告警、时间线、控制平面事件 | `bash deploy/install.sh` |
| `cloud/web` | 云端控制台前端(Vue 3 + Element Plus) | 同上(随 docker 构建) |
| `deploy/` | 一键部署:`install.sh` + `docker-compose.yml` + `.env.example`(含每个配置项说明) | `bash deploy/install.sh` |
| `cloud/server/deploy/k8s/` | Kubernetes 清单(参考,适合本机 kind/Docker-Desktop 集群) | `bash cloud/server/deploy/k8s/install-local.sh` |

能力与价值速览见 [docs/FEATURES.md](docs/FEATURES.md)。

From source:

```bash
git clone --branch v0.4.2 --depth 1 https://gitee.com/suhuisoftwares/pod.git && cd pod
pnpm install && pnpm build
node apps/cli/dist/index.js --help
```

> `npm i -g @podsec/cli` is **not live yet** — use the installer above until the package is published.

## From zero to enforcement

```bash
pod scan                              # 1. see what is exposed (read-only)
pod onboard                           # 2. preview the takeover plan (dry-run)
pod onboard --yes                     #    wrap agents in record-only mode (backups kept)
# ... use your agents normally for a day or two ...
pod policy draft --diff <baseline>    # 3. compile least-privilege policy + show the diff
pod lint --policy ~/.pod/policies/draft.json
pod serve --agent <name> --server <name> --policy ~/.pod/policies/draft.json \
  --command <cmd> --arg <value>       # 4. switch to enforcement
pod watch                             # 5. approve high-risk calls from a second terminal
pod verify-audit                      #    tamper check over the whole chain
pod export-evidence                   #    verifiable evidence bundle
```

## What pod is / is not

| pod is | pod is not |
| --- | --- |
| A **policy compiler**: turns real tool-call corpora into least-privilege rules | A sandbox or a container runtime |
| A **policy enforcement point** on the MCP boundary (fail-closed) | A replacement for your agent's own sandbox |
| A **tamper-evident audit + evidence layer** across agents | An LLM content-moderation firewall |
| **Local-first**: policies, audits and secrets stay on your machine | A cloud service that needs your logs |

Compared with the rest of the market: platform-native sandboxes (Claude Code, Codex, Gemini CLI) protect **one agent**; MCP gateways (agentgateway, ToolHive, ContextForge, Docker) give you a **place to enforce hand-written rules**; scanners (Snyk Agent Scan, mcp-guard) tell you **what is exposed**. pod is the missing step between "what is exposed" and "what is allowed": it **writes the policy for you from observed behavior**, then proves what happened.

## Core capabilities

- **`pod policy draft`** — compile a least-privilege policy from recorded calls. Read-only tools → `allow`, write/exec → `approve`, destructive → `deny`; any observed sensitive-path or secret hit forces `deny`. `--diff <baseline.json>` prints exactly what got tightened, added, removed or loosened.
- **Policy gate** — evaluated `deny > secrets-input > approve > allow`, fail-closed by default; unlisted servers/tools are denied.
- **Approval gate** — high-risk calls suspend and wait for a human; timeout fails closed; approvals are recorded with approver + reason.
- **Tamper-evident audit** — append-only SHA-256 hash chain; `pod verify-audit` detects any historical edit; sensitive content is stored as hashes only.
- **Evidence bundles** — `pod export-evidence` / `pod verify-evidence` produce and verify a portable evidence bundle plus a one-page report.
- **Secret gates** — sensitive input paths (`.env`, `.ssh`, `.aws`, …), known-format output regexes, and high-entropy fallback detection for unknown secret formats.
- **Rollback points** — `pod serve --snapshot` captures write operations; `pod rollback` restores files.
- **Coverage + drift** — `pod coverage --strict` exits non-zero when an MCP server is bypassing the gateway.
- **Supply-chain gate (T4)** — the gateway validates the declared server source (`command` / `package` / `version`) before startup.
- **Control-plane posture (`pod posture`)** — same rules, applied to the control plane: lifecycle hooks, frozen config, memory files, MCP package sources, agent identities, delegation chains. Drift is reported against a `pod posture freeze` baseline; `--strict` exits 1.
- **User-owned rules** — every verdict comes from `~/.pod/rules.json` (or `--rules <file>`): risk patterns, severities, thresholds, trusted sources, egress lists. Code ships defaults; you own the decisions. Invalid rules fail closed.
- **Hardening audit deliverable (`pod harden`)** — one command runs multi-harness scan + exposure scan + control-plane posture + least-privilege compilation + evidence export and writes a client-ready report directory: executive summary, scope and method, prioritized to-dos with runnable commands, an honest coverage-boundary section, and a per-file sha256 manifest. `--client` / `--auditor` / `--engagement` stamp the cover; `pod harden --verify <dir>` lets the **recipient** re-check every artifact by hash without trusting the sender. Local only, never uploaded; secrets appear as masks, never prefixes.
- **Continuous agent/harness guard (`pod guard`)** — scans 16 harnesses (Claude Code, Codex, Cursor, DSH, OpenClaw, OpenCode, Gemini CLI, Windsurf, Zed, VS Code, Cline, Kilo, Amazon Q, Copilot CLI, Amp, Continue), 5 config formats (incl. Codex TOML) plus project-level `.mcp.json` / `.cursor/mcp.json` / `.vscode/mcp.json`, and reports against an 18-entry threat catalog (`AG-01…AG-18`, each with cited sources and an honest coverage verdict). Output opens with **the three things to do first** — each a copy-paste `pod` command **bound to the harness it affects** (`pod agents enroll --harness claude-code`) plus the command that confirms it worked — then the vulnerability list and a prioritized recommendation list, and finally a hand-off to the deliverable (`pod harden`). `pod guard baseline` + `pod guard watch` make it continuous: it only speaks on new/changed/gone findings and writes those to the hash chain. `pod guard remediate --llm` has a model draft proposals from an outbound allowlist that carries **no paths, no hostnames and no config text**; rule deltas must pass the same relaxation guard as `pod rules apply`, and any non-`pod` command is stripped.
- **Enrollment from the console (`pod agents` / the "Enroll" button)** — one click scans the host for installed harnesses and lists them as cards with their evidence, MCP-server count, how many of those bypass the gateway, and their `pod guard` finding counts. Enrolling an agent creates an ed25519 identity, a **zero-permission policy** (unregistered servers denied) and an audit directory, then appends `kind=identity` / `config-change` events to **that agent's** hash chain — so `pod sync` carries them to the cloud's control-plane view (machine-wide facts stay on the local `_control` chain). It **never rewrites harness configuration** — that stays with `pod onboard --yes` (which backs up and can revert). Enrolling is idempotent, removable (`forget`, identity kept by default), and `pod ui --read-only` turns the whole write path off. The console's POST endpoints require the token, `Content-Type: application/json` and a same-origin `Origin`.
- **Takeover (`pod agents onboard` / the "Take over" button)** — step two: rewrites each MCP server's command to `pod serve --record-only … --command <original>` so calls actually cross the gateway. Because it edits your files, the console shows the **before/after command per server**, the backup path and the "records but does not block" caveat *before* you confirm. It only touches user-level configs (never repo-level `.mcp.json`), refuses to run when `pod` is not on PATH (a broken wrapper would take every MCP server down), and reuses your existing zero-permission policy instead of writing an `allow:['*']` template — so dropping `--record-only` later fails closed rather than open. `pod agents revert --agent <name>` restores from the most recent `.pod-backup-*`.
- **Enforcement switch (`pod agents enforce` / the "Enforce" button)** — step three: drops `--record-only` and points the wrapper at your compiled policy, so the gateway actually decides. The failure mode here is not "broke the config" but **"looks enforced while protecting nothing"**, so it hard-refuses unless a policy exists that is bound to the agent, has server rules, and is not `allow:["*"]` — and the dialog shows which policy is in force, its allow/approve/deny counts and how much corpus it was compiled from. Switching back to record-only, or "restore config" (which undoes one step at a time), are both one click.
- **Subscribed rules (`pod rules`)** — rules ship as signed Ed25519 packs (`pack` / `verify` / `apply` / `pull`). Network sources must be verified. A pack that would *loosen* any of your existing rules is refused unless you pass `--allow-relax`, so an "update" can never silently weaken your posture.
- **Policy red team (`pod redteam`)** — attack scenarios are drilled against your policy through the *same* pure pipeline the gateway uses (`decideCall`), so "blocked" means blocked in production too, and the results are reproducible in CI. A model can *propose* scenarios (`--llm`), but only as data: it never gets a verdict, never gets execution, and never touches an MCP server. Only the capability surface (server/tool names + verdicts) leaves the machine, and every model call is written to the hash chain as `kind=llm-call`.
- **Agent identities + delegation narrowing (`pod identity` / `pod delegate`)** — ed25519 keypair per agent; delegations are signed hop-by-hop and must narrow capabilities; `--ttl` bounds every hop.
- **JIT grants (`pod grant`)** — signed, time-boxed, scope-limited tokens; a valid grant satisfies an `approve` decision without a human in the loop, and single-use grants are consumed atomically.
- **Circuit breaker (`pod quarantine`)** — quarantine an agent and the gateway denies its calls on the next invocation (no restart), with the decision written to the audit chain.
- **Trust-propagation anomalies + pollution tracing (`pod anomaly` / `pod trace`)** — thresholds from `rules.anomaly`; trace walks the delegation chain and the audit chain to find where a poisoned agent came from and who it could reach.

## Policy example

```json
{
  "version": "0.1.0",
  "agent": "openclaw",
  "defaultDecision": "deny",
  "servers": {
    "filesystem": {
      "allow":   ["read_file", "list_directory", "search_files"],
      "approve": ["write_file", "edit_file"],
      "deny":    ["delete_file"]
    }
  },
  "secrets": {
    "deny_input_paths": ["~/.ssh", ".env", "credentials", "id_rsa", ".aws", "known_hosts"],
    "deny_output_matching": ["ghp_[A-Za-z0-9]{36}", "sk-[A-Za-z0-9]{20,}", "AKIA[0-9A-Z]{16}"],
    "entropy": { "enabled": true, "min_length": 24, "threshold": 4.5, "block": true }
  }
}
```

## CLI

```text
pod init            scaffold policy templates (baseline / record)
pod onboard         discover local MCP servers and wrap them behind pod (dry-run by default)
pod serve           run the gateway (stdio / Streamable HTTP)
pod record          record-only mode: log every call without blocking (corpus collection)
pod policy draft    compile a least-privilege policy from real calls (+ --diff baseline)
pod approve|deny|pending   side-channel approvals
pod watch           resident approval queue
pod snapshots       list write-operation snapshots (rollback points)
pod rollback        restore files from a snapshot (serve --snapshot enables capture)
pod timeline        audit timeline filtered by agent / tool / time
pod verify-audit    verify the full hash chain, emit a report
pod digest          local weekly security digest (no network)
pod coverage        managed vs. unmanaged MCP servers; --strict exits 1 on drift
pod export-evidence / verify-evidence   export & verify evidence bundles
pod lint | doctor   policy lint / environment health
pod scan            free local security scan (config & bypass checks)
pod guard [scan]    continuous multi-agent / multi-harness vulnerability scan → vulnerability list + prioritized recommendations
pod guard watch     re-scan on an interval; speaks only on new/changed/gone findings, records them in the audit chain
pod guard remediate --llm   model drafts hardening proposals (never auto-applied; must pass the relaxation guard)
pod guard catalog   the threat catalog (AG-01…AG-18) with sources and pod's coverage for each
pod agents [scan]   list the harnesses installed on this machine (and whether each is already enrolled)
pod agents enroll --harness <id>   enroll one: identity + zero-permission policy + audit dir (never touches harness config)
pod agents onboard --harness <id> [--yes]   take over (rewrite that harness's MCP servers to go through the gateway; backup + revert)
pod agents enforce --harness <id> [--record-only] [--yes]   switch to enforcement (or back to record-only) — refuses unless a compiled policy exists
pod agents revert --agent <name>   restore the config from the most recent .pod-backup-*
pod agents forget --agent <name>   remove the enrollment (policy deleted; identity kept unless --purge-identity)
pod ui [--read-only]   local console; the "Scan this machine" + "Enroll" + "Take over" buttons call the same write paths as pod agents
pod harden          one-shot hardening audit: harness scan + exposure + posture + policy draft + evidence → client-ready report directory (--verify re-checks a delivered one)
pod posture [freeze]   control-plane posture: hooks / frozen config / memory / packages / identities / delegations
pod rules              rule packs for subscribed hardening: show | pack | verify | apply | pull
pod redteam            attack scenarios vs. your policy (offline built-in library, or --llm generated); exit 1 on a high-severity bypass
pod identity           per-agent ed25519 identity: init | list | verify
pod delegate           signed delegation: issue | verify | check (capability narrowing)
pod grant              JIT capability tokens: issue | list (signed, TTL, scope, single-use)
pod quarantine         circuit breaker: list | add | remove (enforced by the gateway)
pod anomaly            convention-burst / capability-spread signals over the rules window
pod trace <agent>      pollution tracing: delegation chain + related audit entries
pod graph build     static capability graph from agent configs + tool schemas
pod graph toxic     source→sink toxic paths + targeted policy diff
pod graph explain   trace a path back to evidence
pod sync / pull-policy   optional Pod Cloud sync & policy distribution
```

## Supported agents

| Agent | Transport | Status |
| --- | --- | --- |
| Hermes | Streamable HTTP | ✅ verified end-to-end |
| OpenClaw | stdio wrapper | ✅ verified end-to-end |
| Codex | stdio wrapper + PostToolUse hook | ✅ ready (see docs) |
| DSH / Claude Code / Cursor | MCP | pluggable via MCP |

## Documentation

- [能做什么、给你带来什么](docs/FEATURES.md) ← 先看这个
- [部署 Pod Cloud(云端控制平面)](docs/deploy-cloud.md) ← 部署与"你需要提供什么"

> 云端控制平面原先分两个独立仓库(`podcloud-server` / `podcloud-web`),
> 已并入本仓库 `cloud/` 下并**归档原仓库**——历史链接会看到指向这里的告示。
- [Positioning & wedge](docs/positioning.md)
- [Threat model](docs/threat-model.md)
- [Multi-agent / multi-harness security](docs/agent-harness-security.md) ← 现状盘点 · 威胁目录 · 差距
- [Egress defense](docs/egress-defense.md)
- [Control-plane hardening (requirements + design)](docs/control-plane-hardening.md)
- [Agent onboarding](docs/agent-onboarding.md)
- [Automation (launchd/systemd/cron)](docs/automation.md)

## Pod Cloud (optional, in this repo)

本地部分开箱可用,**云端是可选的**:没有它,`pod` 照样编译策略、执法、留证据。
需要跨机器/跨 agent 的统一视图、策略下发、告警与合规报告时,一条命令起一个:

```bash
bash deploy/install.sh            # 单机 Docker Compose(首次 2-5 分钟)
# 或带管理员:ADMIN_EMAIL=you@x.com ADMIN_PASSWORD='...' bash deploy/install.sh
```

数据方向是单向的:本地只推 SHA-256 哈希上云,审计原文不出你的机器;云端不参与本地执法(云端挂了 agent 不受影响)。
必填配置只有一项(JWT 密钥,脚本自动生成),其余见 [docs/deploy-cloud.md](docs/deploy-cloud.md)。

## Sponsor

pod is Apache-2.0 and stays that way: the CLI, the gateway, the audit chain and the
evidence export are complete on your own machine, and nothing is locked behind a
sponsorship. Sponsorship pays for the parts that do not demo well — CI minutes, a
machine to run the multi-harness attack suites on, and the security maintenance
that only shows up as *absence* of incidents.

The only official channel is **GitHub Sponsors**:
[github.com/sponsors/suhui-organization](https://github.com/sponsors/suhui-organization)
(or the **Sponsor** button at the top of this repository).

赞助不是解锁功能的前置条件——核心能力本地全都有。不给钱也一样欢迎:提一个真实的
误报、贴一份 `pod scan` 的输出、或者帮下一个人装起来,都是等价的帮忙。

## License

Apache-2.0 — see [LICENSE](LICENSE). Security notes: [SECURITY.md](SECURITY.md).

TDQS

A3.7/5.0

Scored across 14 tools

Disambiguation4/5

Most tools have distinct purposes, but there is overlap between read_file (deprecated) and read_text_file, and between list_directory and list_directory_with_sizes. The descriptions clearly differentiate them, so an agent should select correctly, though the redundancy is slightly confusing.

Naming Consistency4/5

Tool names predominantly follow a verb_noun snake_case pattern (e.g., read_text_file, create_directory, move_file). Minor deviation: directory_tree uses a noun-only name, and read_file is deprecated but retained. Overall, the pattern is predictable and consistent.

Tool Count5/5

With 14 tools, the server covers file system operations without being bloated. Each tool serves a clear purpose (read, write, edit, list, move, search, metadata), and the count is appropriate for the domain.

Completeness3/5

The surface covers reading, writing, editing, moving, listing, searching, and metadata retrieval, but lacks delete operations for files or directories. This is a notable gap that would require workarounds or fail typical file management workflows. Copy functionality is also absent, though move partially covers it.

Maintenance

ActivityMaintained
ResponsivenessNo issues