Content
# CyVisGuard
English | [中文](README.zh.md)
An open-source, self-contained **security control plane for AI agents**. It sits
between an agent — anything that holds credentials and calls tools on someone's
behalf — and everything it can reach, and on every action answers: *who is calling,
on behalf of whom, and is this still within what they're allowed to do?*
Agents are becoming the identity that actually touches production: they read tickets,
query warehouses, call internal APIs, and act on content nobody reviewed. The
interesting controls are no longer at the model, they're at the **action** — identity
and delegation, capability policy, data-flow taint, and an audit trail you can
replay. CyVisGuard enforces those over **MCP**, so they apply to any agent that
speaks it.
Coding agents are the sharpest version of the problem — full filesystem, shell,
network, sub-agents, and untrusted repo content in the same context — so they're the
reference integration. Point it at a real Claude Code and it guards every tool call,
refuses a prompt-injected exfiltration, catches a poisoned `CLAUDE.md` or skill, and
even refuses a settings change that would remove the guard itself — all streamed to a
live audit console.

*Every row is a real `GuardedSession` call and every verdict comes from the real
policy engine — token exchange, taint tracking, arbitration, circuit-break. The
capture is reload-paced, not a real-time recording.*
Clicking a row opens the request and response the guard actually saw:

> **Not demo-ware.** What's live vs. scripted is labelled honestly, and a
> non-deterministic miss is reported as a miss.
## Two ways in
**1 · See the whole thing running — one command, no API key, no network**
```bash
docker compose -f docker/compose.yml up --build
```
Brings up the dashboard and exercises the control plane end to end: a real MCP client
gets its exfil attempt blocked, and two employees get different tool views through one
gateway. Open **http://localhost:4300/audit** to watch every call land. Replay with
`docker compose -f docker/compose.yml run --rm flow`. (Optional `--profile llm` bakes
a real weak model into the image so the live-injection scenario runs offline.)
No Docker? The same flow runs on the host:
```bash
pnpm install
pnpm dev # dashboard → http://localhost:4300
pnpm --filter @cyvisguard/demo-flow start # exercise the control plane
```
**2 · Put it in front of your own agent** — see **[INTEGRATIONS.md](INTEGRATIONS.md)**.
## What it guards
Four interception points, each writing to one live audit trail. The first three are
agent-agnostic; the fourth is how deep it goes when you can integrate with the agent
itself:
| layer | what it guards | applies to |
|---|---|---|
| **MCP gateway** (`apps/mcp-gateway`) | every tool call: identity → policy → data-flow taint → audit, then execute | any MCP client |
| **Aggregating MCP proxy** (`apps/mcp-proxy`) | many downstream servers behind one endpoint, each employee getting a **ceiling-filtered tool view** | any MCP client, org-wide |
| **Model gateway** (`apps/model-gateway`) | the raw LLM request/response the tool layer can't see | any agent on the Anthropic API |
| **Claude Code hooks** (`apps/cc-hook`) | CC's *native* tools (Read / Write / Bash / WebFetch / Task / Skill) | Claude Code |
The proxy is the shape most orgs need: the agent connects only to CyVisGuard, which
fronts your downstream MCP servers — a business an employee can't reach isn't denied,
it's **invisible** — and token-exchange means the downstream sees the real employee,
not the proxy.
Where the agent lets you hook it, the guard also **defends its own attack surface**.
On Claude Code that means (each verified against the docs and empirically):
- **scope is anchored** to the session's start dir and doesn't follow `cd`;
- a **poisoned `CLAUDE.md`** is scanned and taints the session;
- a **poisoned skill** is refused at invocation (fingerprint whitelist + content scan);
- a settings change that **removes the guard's own hook** is refused;
- **sub-agent derivation** mints a real delegated child token (revoke cascades).
## The control plane
The enforcement logic lives in small, pure packages behind four replaceable seams:
| package | role |
|---|---|
| `@cyvisguard/registry` | asset registration + config-fingerprint admission |
| `@cyvisguard/identity` | short-lived NHI identity, attestation, RFC-8693-style token exchange with nested delegation chains, cascade revoke |
| `@cyvisguard/gateway` | PEP: policy enforcement + data-plane taint tagging |
| `@cyvisguard/policy` | pure-TS evaluator — **capability-based** (a tool is judged by its `{egress, scoped, stepup}` class, never its name) + five-tier scope arbitration |
| `@cyvisguard/runtime-guard` | intent-alignment scoring + circuit breaker |
| `@cyvisguard/soc` | attack-chain reconstruction from the event stream |
| `@cyvisguard/audit` | the shared append-only audit / control / skills state |
| `@cyvisguard/agent-runtime` | `LLMProvider` + Ollama provider + a ReAct loop for the live-injection mode |
| `@cyvisguard/model-eval` | seams, metrics and harnesses for **learned components** (below) |
| `@cyvisguard/shared` | domain types, event bus, and the four integration **seams** |
The **seams** an adopter replaces to wire this to a real platform, in
`@cyvisguard/shared`: `IdentityBackend`, `PolicySource`, `IntentProvider`,
`EnforcementAdapter`. The demo ships in-memory/cooperative implementations.
## Plugging in a model
Two of the guard's judgements sit behind seams, so you can back them with a model
instead of the built-in heuristics — an existing open weight, or one of ours when
we publish it:
| seam | question | default |
|---|---|---|
| `ContentClassifier` | is this text an injection? | regex baseline |
| `BehaviorJudge` | given the task and the calls so far, is this agent still doing its job? | rule-based scoring |
Any local Ollama model works today. Point it at one and run the harness:
```bash
CYVISGUARD_JUDGE_MODEL=gemma4:e2b-it-q4_K_M \
pnpm --filter @cyvisguard/model-eval eval:judge
```
`demo-flow` act 4 shows the difference on a real case — an agent that reads
credentials and posts them to a C2 address slips past the rules (too few denials
to trip the breaker) and is caught once a judge is attached.
**A model can only ever *add* suspicion, never remove it.** The rule baseline
always runs and the results are combined one-directionally, so a model that is
absent, wrong, or fooled leaves the guard exactly as strong as it is without one.
The seams and the combiners live in
[`@cyvisguard/shared`](packages/shared/src/model-types.ts); the eval harness and
its honest caveats are in [`@cyvisguard/model-eval`](packages/model-eval).
## Guided scenarios (S0–S4)
The dashboard also has scripted-but-real scenarios that exercise the same control
plane in isolation. Open **`/docs`** for a bilingual visual tour:

- **S0/S1** — a poisoned skill is rejected at attestation; verified agents form a
traceable delegation chain.
- **S2** — an injection taints the context; the exfil is blocked by data-flow rules
(or, with structural partitioning, the egress tool never exists). **S2 live** drives
a real weak model (`qwen2.5:0.5b`) that genuinely takes the bait — and is blocked.
- **S3** — a mid-task resource request is arbitrated: auto-approve / human / reject.
- **S4** — a hijacked agent's alignment drops until the circuit breaker trips,
cascade-revokes its tokens, and the SOC reconstructs the attack chain.
## Documentation
- [INTEGRATIONS.md](INTEGRATIONS.md) — connect Claude Code: hooks, MCP gateway/proxy, model gateway
- [packages/model-eval](packages/model-eval) — plugging a model into the guard, and how it is evaluated
- [apps/mcp-proxy](apps/mcp-proxy) — the aggregating proxy: per-employee tool views
- [docker/README.md](docker/README.md) — run the whole stack in containers
- [AGENTS.md](AGENTS.md) · [CONTRIBUTING.md](CONTRIBUTING.md) · [SECURITY.md](SECURITY.md)
- [CHANGELOG.md](CHANGELOG.md) — what shipped and why · [docs/TODO.md](docs/TODO.md) — what's next
## Use at your own risk
This is a reference implementation — **use at your own risk**. The demo credentials
(`user:demo`, a literal `demo-secret`) are placeholders; supply your own keys and
identity backend before running it anywhere real. The implementation's simplifications
are recorded in [SECURITY.md](SECURITY.md).
## License
[Apache-2.0](LICENSE).
Connection Info
You Might Also Like
No recommendations available