Express.js Integration
The Surfinguard JS SDK includes built-in Express.js middleware that automatically checks incoming requests for security threats.
Installation
npm install @surfinguard/sdk expressQuick Start
import express from 'express';
import { Guard, surfinguardMiddleware } from '@surfinguard/sdk';
const app = express();
const guard = await Guard.create({ mode: 'local' });
// Apply middleware to all routes
app.use(surfinguardMiddleware(guard));
app.post('/api/execute', (req, res) => {
// If we reach here, the request passed the security check
res.json({ status: 'executed' });
});
app.listen(3000);How It Works
The middleware inspects incoming requests and checks action values found in the request body against the Surfinguard engine. If the check returns DANGER (or CAUTION in strict mode), the middleware responds with a 403 Forbidden before the request reaches your route handler.
Middleware Options
app.use(surfinguardMiddleware(guard, {
// Which policy to enforce
policy: 'moderate', // 'permissive' | 'moderate' | 'strict'
// Custom function to extract the action from the request
extractAction: (req) => {
return {
type: req.body.type || 'text',
value: req.body.value || req.body.input || '',
};
},
// Custom error handler
onBlocked: (req, res, result) => {
res.status(403).json({
error: 'Action blocked by security policy',
level: result.level,
score: result.score,
reasons: result.reasons,
});
},
}));Route-Level Protection
Apply the middleware to specific routes instead of globally:
const checkUrl = surfinguardMiddleware(guard, {
extractAction: (req) => ({ type: 'url', value: req.body.url }),
});
const checkCommand = surfinguardMiddleware(guard, {
extractAction: (req) => ({ type: 'command', value: req.body.command }),
policy: 'strict',
});
// Only these routes are protected
app.post('/api/fetch-url', checkUrl, (req, res) => {
// URL has been checked
res.json({ status: 'ok' });
});
app.post('/api/run-command', checkCommand, (req, res) => {
// Command has been checked with strict policy
res.json({ status: 'ok' });
});
// This route has no security check
app.get('/api/health', (req, res) => {
res.json({ status: 'healthy' });
});Custom Action Extraction
The extractAction function determines what gets checked. Here are common patterns:
// Check URL from query parameter
extractAction: (req) => ({
type: 'url',
value: req.query.url,
})
// Check command from JSON body
extractAction: (req) => ({
type: 'command',
value: req.body.command,
})
// Check text from form data
extractAction: (req) => ({
type: 'text',
value: req.body.prompt || req.body.message,
})
// Dynamic type based on request
extractAction: (req) => ({
type: req.body.action_type,
value: req.body.action_value,
})Error Handling
When the middleware blocks a request, it calls the onBlocked handler. The default behavior returns a 403 JSON response:
{
"error": "Blocked by Surfinguard",
"level": "DANGER",
"score": 9,
"reasons": ["Brand impersonation: google", "Risky TLD: .tk"]
}Override this with a custom handler:
app.use(surfinguardMiddleware(guard, {
onBlocked: (req, res, result) => {
// Log the blocked request
console.warn(`Blocked ${req.method} ${req.path}:`, result.reasons);
// Custom response
res.status(422).json({
message: 'This action has been flagged for security review',
referenceId: generateReferenceId(),
});
},
}));Full Example
import express from 'express';
import { Guard, surfinguardMiddleware } from '@surfinguard/sdk';
const app = express();
app.use(express.json());
const guard = await Guard.create({
mode: 'local',
policy: 'moderate',
});
// Global middleware for all API routes
app.use('/api', surfinguardMiddleware(guard, {
extractAction: (req) => {
// Map different endpoints to action types
if (req.path.includes('/fetch')) {
return { type: 'url', value: req.body.url };
}
if (req.path.includes('/execute')) {
return { type: 'command', value: req.body.command };
}
if (req.path.includes('/chat')) {
return { type: 'text', value: req.body.message };
}
return null; // Skip check if no action to extract
},
onBlocked: (req, res, result) => {
res.status(403).json({
blocked: true,
level: result.level,
reasons: result.reasons,
});
},
}));
app.post('/api/fetch', (req, res) => {
res.json({ html: '...' });
});
app.post('/api/execute', (req, res) => {
res.json({ output: '...' });
});
app.post('/api/chat', (req, res) => {
res.json({ reply: '...' });
});
app.listen(3000, () => {
console.log('Server running with Surfinguard protection');
});