2026-01-20 · Authensor

How to Secure AI Agents in Express.js APIs

SafeClaw by Authensor integrates into Express.js as middleware, providing deny-by-default action gating for AI agent tool calls. Every file read, shell command, and outbound request your agent attempts is checked against your YAML policy before execution. Install with npx @authensor/safeclaw and add the middleware to your Express routes.

Why Express AI Agents Need Gating

Express.js APIs that expose AI agent functionality are a common pattern — chatbots, code assistants, and automation tools all run behind Express endpoints. These agents can call child_process.exec(), read files with fs, and make outbound requests with fetch or axios. Without gating, a single compromised tool call can escalate into full server compromise.

SafeClaw's 446-test gate engine and hash-chained audit trail stop this at the action level.

Installation

npx @authensor/safeclaw
npm install @authensor/safeclaw

Policy

version: 1
defaultAction: deny

rules:
- action: file.read
path:
glob: "./uploads/**"
decision: allow

- action: file.write
path:
glob: "./output/**"
decision: allow

- action: network.request
host:
in: ["api.openai.com", "api.anthropic.com"]
decision: allow

- action: process.exec
command:
in: ["node scripts/analyze.js", "node scripts/format.js"]
decision: allow

- action: file.read
path:
glob: "*/.env"
decision: deny

Express Middleware

Create a SafeClaw middleware that gates all agent actions:

// middleware/safeclaw.js
import { Gate } from '@authensor/safeclaw';

const gate = new Gate();

export function safeClawMiddleware(req, res, next) {
// Attach gate to request for use in route handlers
req.gate = gate;
next();
}

export async function gateAction(gate, actionRequest) {
const decision = await gate.check(actionRequest);
if (!decision.allowed) {
const error = new Error(SafeClaw denied: ${decision.reason});
error.status = 403;
throw error;
}
return decision;
}

Route Integration

// routes/agent.js
import express from 'express';
import { execSync } from 'child_process';
import { readFile, writeFile } from 'fs/promises';
import { gateAction } from '../middleware/safeclaw.js';

const router = express.Router();

router.post('/tool-call', async (req, res, next) => {
try {
const { tool, params } = req.body;

switch (tool) {
case 'readFile': {
await gateAction(req.gate, {
action: 'file.read',
path: params.path
});
const content = await readFile(params.path, 'utf-8');
return res.json({ result: content });
}

case 'writeFile': {
await gateAction(req.gate, {
action: 'file.write',
path: params.path
});
await writeFile(params.path, params.content, 'utf-8');
return res.json({ result: 'File written' });
}

case 'execCommand': {
await gateAction(req.gate, {
action: 'process.exec',
command: params.command
});
const output = execSync(params.command, { encoding: 'utf-8' });
return res.json({ result: output });
}

case 'httpRequest': {
const host = new URL(params.url).hostname;
await gateAction(req.gate, {
action: 'network.request',
host,
url: params.url,
method: params.method || 'GET'
});
const response = await fetch(params.url, {
method: params.method || 'GET'
});
const data = await response.json();
return res.json({ result: data });
}

default:
return res.status(400).json({ error: 'Unknown tool' });
}
} catch (err) {
next(err);
}
});

export default router;

App Setup

// app.js
import express from 'express';
import { safeClawMiddleware } from './middleware/safeclaw.js';
import agentRoutes from './routes/agent.js';

const app = express();

app.use(express.json());
app.use(safeClawMiddleware);
app.use('/api/agent', agentRoutes);

// Error handler for SafeClaw denials
app.use((err, req, res, next) => {
if (err.status === 403) {
return res.status(403).json({ error: err.message });
}
next(err);
});

app.listen(3000);

Error Handling

SafeClaw denials return structured error responses:

{
  "error": "SafeClaw denied: matched deny rule for .env files"
}

Every decision is hash-chained in the audit trail. MIT licensed, works with Claude and OpenAI, 446 tests.

Cross-References

Try SafeClaw

Action-level gating for AI agents. Set it up in your browser in 60 seconds.

$ npx @authensor/safeclaw