Skip to content

Commit 3c37d5d

Browse files
committed
feat: add helmet for security headers in agent0 and todo0 applications
1 parent 1174285 commit 3c37d5d

6 files changed

Lines changed: 47 additions & 1 deletion

File tree

packages/agent0/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,14 @@
1111
"dependencies": {
1212
"@anthropic-ai/sdk": "^0.32.0",
1313
"@aws-sdk/client-bedrock-runtime": "^3.709.0",
14+
1415
"@modelcontextprotocol/sdk": "^1.19.1",
1516
"axios": "^1.12.2",
1617
"cookie-parser": "^1.4.7",
1718
"dotenv": "^17.2.3",
1819
"express": "4.18.2",
1920
"express-session": "1.17.3",
21+
"helmet": "^8.0.0",
2022
"jose": "^6.1.0",
2123
"jsonwebtoken": "^9.0.2",
2224
"openid-client": "^5.7.1",

packages/agent0/src/app.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import express, { Request, Response } from 'express';
33
import * as path from 'path';
44
import cookieParser from 'cookie-parser';
5+
import helmet from 'helmet';
56
import { getAgentForSession } from './agent.js';
67
import { OktaAuthHelper, OktaConfig, createSessionMiddleware } from './auth/okta-auth.js';
78

@@ -155,6 +156,18 @@ export class AppServer {
155156
// ============================================================================
156157

157158
private setupMiddleware(): void {
159+
// Security headers via helmet (uses secure defaults, we only override CSP)
160+
this.app.use(helmet({
161+
contentSecurityPolicy: {
162+
directives: {
163+
defaultSrc: ["'self'"],
164+
scriptSrc: ["'self'", "https://cdn.jsdelivr.net"],
165+
styleSrc: ["'self'", "'unsafe-inline'"],
166+
connectSrc: ["'self'", "http://localhost:3000", "http://127.0.0.1:3000"],
167+
},
168+
},
169+
}));
170+
158171
this.app.use(express.json());
159172
this.app.use(cookieParser());
160173
this.app.use(createSessionMiddleware(this.config.sessionSecret));

packages/todo0/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
"ejs": "^3.1.10",
2626
"express": "^5.1.0",
2727
"express-session": "^1.18.2",
28+
"helmet": "^8.0.0",
2829
"openid-client": "^5.7.1",
2930
"prisma": "^6.16.3",
3031
"zod": "^3.22.4"

packages/todo0/src/app-server.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import express from 'express';
22
import path from 'path';
33
import bodyParser from 'body-parser';
44
import session from 'express-session';
5+
import helmet from 'helmet';
56
import { randomUUID } from 'crypto';
67
import * as dotenv from 'dotenv';
78
import { createRequireAuth } from './middleware/requireAuth';
@@ -125,7 +126,18 @@ const app = express();
125126
app.set('view engine', 'ejs');
126127
app.set('views', path.join(__dirname, '../views'));
127128

128-
// Logging middleware - must come first
129+
// Security headers via helmet (uses secure defaults, we only override CSP for inline scripts/styles)
130+
app.use(helmet({
131+
contentSecurityPolicy: {
132+
directives: {
133+
defaultSrc: ["'self'"],
134+
scriptSrc: ["'self'", "'unsafe-inline'"],
135+
styleSrc: ["'self'", "'unsafe-inline'"],
136+
},
137+
},
138+
}));
139+
140+
// Logging middleware
129141
app.use((req, _res, next) => {
130142
console.log(`[REQUEST] ${req.method} ${req.url}`);
131143
console.log(`[REQUEST] Path: ${req.path}`);

packages/todo0/src/mcp-server.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import { z } from 'zod';
33
import { randomUUID } from 'node:crypto';
44
import express from 'express';
5+
import helmet from 'helmet';
56
import * as dotenv from 'dotenv';
67
import * as path from 'path';
78
import { mcpAuthMetadataRouter, getOAuthProtectedResourceMetadataUrl } from '@modelcontextprotocol/sdk/server/auth/router.js';
@@ -341,6 +342,11 @@ async function bootstrap(): Promise<void> {
341342

342343
const app = express();
343344

345+
// Security headers via helmet (API server - restrictive CSP since no HTML served)
346+
app.use(helmet({
347+
contentSecurityPolicy: { directives: { defaultSrc: ["'none'"] } },
348+
}));
349+
344350
// Map to store transports by session ID
345351
const transports: Record<string, StreamableHTTPServerTransport> = {};
346352
// Map to store auth claims by session ID

pnpm-lock.yaml

Lines changed: 12 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)