{"_id":"@agentic-security-mcp/agent-firewall","name":"@agentic-security-mcp/agent-firewall","dist-tags":{"latest":"0.1.0"},"versions":{"0.1.0":{"name":"@agentic-security-mcp/agent-firewall","version":"0.1.0","description":"Agent Firewall for AI and MCP tool calls: deterministic allow, ask, deny permissions with human approval and audit hooks.","keywords":["agent-firewall","agent-permissions","agent-security","ai-agent","agentic-ai","ai-security","mcp","mcp-security","model-context-protocol","tool-calling","guardrails","authorization","least-privilege","human-in-the-loop","llm-security"],"license":"MIT","type":"module","main":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"bin":{"agent-firewall":"dist/cli.js"},"engines":{"node":">=18"},"scripts":{"clean":"rm -rf dist","build":"tsc -p tsconfig.json","test":"npm run build && node --test test/*.test.js","prepack":"npm test","pack:check":"npm pack --dry-run"},"devDependencies":{"typescript":"^5.8.3"},"sideEffects":false,"publishConfig":{"access":"public"},"_id":"@agentic-security-mcp/agent-firewall@0.1.0","_integrity":"sha512-tio5D0eEhMBdDyyhNzzZO+VfB2B0UJQ0pG31Vljl1Q29Amu0cOvCUz5j0K56OTqFj08BPsIFtGvYoERabIJF3A==","_resolved":"/Users/shashank/Downloads/agentic-security-mcp-agent-firewall-0.1.0.tgz","_from":"file:agentic-security-mcp-agent-firewall-0.1.0.tgz","_nodeVersion":"18.20.8","_npmVersion":"10.8.2","dist":{"integrity":"sha512-tio5D0eEhMBdDyyhNzzZO+VfB2B0UJQ0pG31Vljl1Q29Amu0cOvCUz5j0K56OTqFj08BPsIFtGvYoERabIJF3A==","shasum":"ced29571e08fb4809ec7906c7b9d8a03c325bf52","tarball":"https://registry.npmjs.org/@agentic-security-mcp/agent-firewall/-/agent-firewall-0.1.0.tgz","fileCount":52,"unpackedSize":65699,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIG+9TrEUjd7iT0/ryNhgsj7XBWujVLcL/uRmuodWMtFPAiBOYQu0BxWJYgFJ0DjhFLJPOtkQ3VnzOmynd5LIw11DZg=="}]},"_npmUser":{"name":"shashank022","email":"shashank022@gmail.com"},"directories":{},"maintainers":[{"name":"shashank022","email":"shashank022@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/agent-firewall_0.1.0_1788803227502_0.7610025772587028"},"_hasShrinkwrap":false}},"time":{"created":"2026-09-07T17:47:07.250Z","0.1.0":"2026-09-07T17:47:07.630Z","modified":"2026-09-07T17:47:07.941Z"},"maintainers":[{"name":"shashank022","email":"shashank022@gmail.com"}],"description":"Agent Firewall for AI and MCP tool calls: deterministic allow, ask, deny permissions with human approval and audit hooks.","keywords":["agent-firewall","agent-permissions","agent-security","ai-agent","agentic-ai","ai-security","mcp","mcp-security","model-context-protocol","tool-calling","guardrails","authorization","least-privilege","human-in-the-loop","llm-security"],"license":"MIT","readme":"# @agentic-security-mcp/agent-firewall\n\n**Deterministic permissions for AI agents and MCP tools — ALLOW, ASK, or DENY before execution.**\n\nThink **“sudo/browser permissions for AI agents.”** `agent-firewall` is local-first, framework-agnostic, and has **zero runtime dependencies**.\n\n> `agent-firewall` is an application-level authorization boundary, not an OS sandbox. Put it at the tool-execution boundary you control.\n\n## Why\n\nAI agents can run shell commands, read files, call MCP tools, push code, publish packages, send messages, and mutate infrastructure. The model should not be the final authority for consequential actions.\n\n```text\nAI Agent / MCP Client\n        |\n        v\n   requested action\n        |\n        v\n+-------------------+\n|   AGENT FIREWALL  |\n| ALLOW | ASK | DENY|\n+-------------------+\n        |\n        v\n Shell / Files / MCP / APIs / DB / Cloud\n```\n\nThe policy decision is deterministic. No LLM is used to decide whether an LLM is allowed to do something.\n\n## Install\n\n```bash\nnpm install @agentic-security-mcp/agent-firewall\n```\n\n## 60-second example\n\n```ts\nimport {\n  codingAgentPolicy,\n  createAgentFirewall,\n} from \"@agentic-security-mcp/agent-firewall\";\n\nconst firewall = createAgentFirewall({\n  policy: codingAgentPolicy(),\n\n  onApproval: async ({ request, reason }) => {\n    console.log(\"Needs approval:\", request.target, reason);\n    return false; // connect your terminal/UI/HITL approval flow here\n  },\n});\n\nawait firewall.execute(\n  {\n    agentId: \"coding-agent\",\n    action: \"shell.exec\",\n    target: \"git status\",\n  },\n  () => runCommand(\"git status\"),\n);\n```\n\nThe built-in coding-agent policy starts with behavior like:\n\n```text\ngit status                 -> ALLOW\nnpm test                   -> ALLOW\ngit push origin main       -> ASK\ngit push --force           -> DENY\nsudo ...                   -> DENY\nread ./.env                -> DENY\nrequest api.github.com     -> ALLOW\nunknown network host       -> ASK\n```\n\n## MCP tool permissions\n\nMap an MCP `tools/call` into a normal firewall action with `mcpToolAction()`:\n\n```ts\nimport {\n  createAgentFirewall,\n  mcpToolAction,\n} from \"@agentic-security-mcp/agent-firewall\";\n\nconst firewall = createAgentFirewall({\n  policy: {\n    defaultDecision: \"deny\",\n    rules: [\n      {\n        id: \"github-read\",\n        effect: \"allow\",\n        action: \"mcp.tool.call\",\n        target: \"github/get_*\",\n      },\n      {\n        id: \"github-write\",\n        effect: \"ask\",\n        action: \"mcp.tool.call\",\n        target: \"github/create_*\",\n      },\n      {\n        id: \"github-delete\",\n        effect: \"deny\",\n        action: \"mcp.tool.call\",\n        target: \"github/delete_*\",\n        risk: \"critical\",\n      },\n    ],\n  },\n  onApproval: async ({ request }) => {\n    console.log(\"Human approval required:\", request.target);\n    return false;\n  },\n});\n\nawait firewall.execute(\n  mcpToolAction({\n    agentId: \"codex\",\n    server: \"github\",\n    tool: \"create_pull_request\",\n    arguments: { owner: \"acme\", repo: \"demo\" },\n  }),\n  () => callTheRealMcpTool(),\n);\n```\n\n`mcpToolAction()` produces:\n\n```text\naction = mcp.tool.call\ntarget = github/create_pull_request\n```\n\nThat keeps the core independent from any specific MCP SDK.\n\n## Define your own policy\n\n```ts\nconst firewall = createAgentFirewall({\n  policy: {\n    defaultDecision: \"deny\",\n    rules: [\n      {\n        id: \"read-source\",\n        effect: \"allow\",\n        action: \"filesystem.read\",\n        target: \"./src/**\",\n      },\n      {\n        id: \"protect-secrets\",\n        effect: \"deny\",\n        action: [\"filesystem.read\", \"filesystem.write\"],\n        target: [\"**/.env\", \"**/.ssh/**\"],\n        risk: \"critical\",\n      },\n      {\n        id: \"confirm-push\",\n        effect: \"ask\",\n        action: \"shell.exec\",\n        target: \"git push*\",\n      },\n    ],\n  },\n});\n```\n\n### Security precedence\n\nIf multiple rules match, the strongest effect wins:\n\n```text\nDENY > ASK > ALLOW\n```\n\nA broad ALLOW can never override a matching DENY.\n\n## Protect an existing tool function\n\n```ts\nconst protectedExec = firewall.protect(\n  (command: string) => ({\n    agentId: \"my-agent\",\n    action: \"shell.exec\",\n    target: command,\n  }),\n  execCommand,\n);\n\nawait protectedExec(\"npm test\");\n```\n\n## Audit decisions\n\n```ts\nconst firewall = createAgentFirewall({\n  policy,\n  onAudit: async (event) => {\n    console.log({\n      time: event.timestamp,\n      agent: event.request.agentId,\n      action: event.request.action,\n      target: event.request.target,\n      decision: event.decision,\n      approved: event.approved,\n    });\n  },\n});\n```\n\nAvoid placing secrets in `request.params` if audit events are persisted.\n\n## CLI\n\nAfter installation:\n\n```bash\nagent-firewall check shell.exec \"git status\"\nagent-firewall check shell.exec \"git push origin main\"\nagent-firewall check filesystem.read \"./.env\"\n```\n\nExample output:\n\n```text\nASK  risk=high\nCommand can create a remote or infrastructure side effect.\nrules=ask-remote-side-effects\n```\n\n## Core action vocabulary\n\nThe engine accepts any namespaced action string. Recommended conventions:\n\n| Action | Example target |\n|---|---|\n| `shell.exec` | `git push origin main` |\n| `filesystem.read` | `./src/app.ts` |\n| `filesystem.write` | `./src/app.ts` |\n| `network.request` | `api.github.com` |\n| `mcp.tool.call` | `github/create_pull_request` |\n| `database.query` | `production.customers` |\n| `email.send` | `user@example.com` |\n| `github.write` | `org/repo#123` |\n\n## Design invariants\n\n- **Deterministic authorization** — an LLM cannot grant itself permission.\n- **Least privilege** — permit the narrowest action/resource needed.\n- **Fail closed** — unknown operations should default to DENY or ASK.\n- **Human approval** — ASK never executes without affirmative approval.\n- **DENY wins** — DENY always outranks ASK and ALLOW.\n- **Zero runtime dependencies** — the core has no third-party production dependency.\n\n## Important security limitations in v0.1.0\n\n- This is **not an OS/process sandbox**.\n- It does not magically intercept tools; integrate it before the real side effect.\n- Wildcards are convenience matching, not a shell parser.\n- Path rules do not yet resolve symlinks or canonical filesystem paths.\n- Network targets are application-supplied strings; URL/redirect enforcement is not yet built in.\n- Do not rely on the preset as your only production security boundary.\n\n## Roadmap\n\n- [x] deterministic ALLOW / ASK / DENY engine\n- [x] framework-agnostic MCP `tools/call` mapping\n- [x] human approval callback\n- [x] audit callback\n- [x] coding-agent starter policy\n- [ ] terminal approval UI\n- [ ] Claude Code / Codex / Cursor adapters\n- [ ] path normalization + symlink protections\n- [ ] structured shell command parser\n- [ ] URL/host parser + redirect-aware egress policy\n- [ ] JSON/YAML policy loader\n- [ ] signed, expiring one-time capabilities\n- [ ] OpenTelemetry audit exporter\n- [ ] `agent-firewall doctor`\n- [ ] policy test helpers for CI\n\n## Security\n\nSee `SECURITY.md`. Please do not include real credentials, tokens, customer data, or private prompts in reports.\n\n## License\n\nMIT\n","readmeFilename":"README.md","_rev":"1-be8d0a5b881de8c03445f23dd92b05a4"}