Skip to content

Commit 9a5c512

Browse files
committed
feat(security): add helmet middleware for HTTP security headers
Apply helmet at the Express layer to inject hardened response headers (CSP, HSTS, frame and cross-origin policies) that protect browser clients against injection vulnerabilities. The CSP connect-src is widened to https://*.stellar.org so the app can still reach the required Stellar blockchain APIs (Horizon and Soroban RPC, mainnet and testnet). Closes #84.
1 parent 02e55f2 commit 9a5c512

3 files changed

Lines changed: 75 additions & 33 deletions

File tree

package-lock.json

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

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
"compression": "^1.8.1",
5555
"dotenv": "^17.4.2",
5656
"express": "^5.2.1",
57+
"helmet": "^8.2.0",
5758
"ioredis": "^5.6.1",
5859
"joi": "^17.13.3",
5960
"prisma": "^7.8.0",

src/main.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import './tracing/tracing.bootstrap';
22
import { NestFactory } from '@nestjs/core';
33
import { ValidationPipe } from '@nestjs/common';
44
import compression from 'compression';
5+
import helmet from 'helmet';
56
import { AppModule } from './app.module';
67
import { ConfigService } from './config/config.service';
78
import { JsonLoggerService } from './common/logger/json-logger.service';
@@ -20,6 +21,29 @@ async function bootstrap() {
2021

2122
const configService = app.get(ConfigService);
2223

24+
// ── HTTP security headers (issue #84) ─────────────────────────────────────
25+
// Helmet injects a hardened set of response headers (CSP, HSTS, frame and
26+
// cross-origin policies, etc.) to protect browser clients against injection
27+
// vulnerabilities. The CSP connect-src is widened to the Stellar network so
28+
// the app can still reach the required blockchain API systems (Horizon and
29+
// Soroban RPC, on both mainnet and testnet).
30+
app.use(
31+
helmet({
32+
contentSecurityPolicy: {
33+
useDefaults: true,
34+
directives: {
35+
defaultSrc: ["'self'"],
36+
connectSrc: ["'self'", 'https://*.stellar.org'],
37+
objectSrc: ["'none'"],
38+
frameAncestors: ["'self'"],
39+
upgradeInsecureRequests: [],
40+
},
41+
},
42+
// This service is a JSON API consumed by separate frontend origins.
43+
crossOriginResourcePolicy: { policy: 'cross-origin' },
44+
}),
45+
);
46+
2347
// ── CORS – restrict to known frontend origins (issue #85) ─────────────────
2448
const allowedOrigins = configService.getAllowedOrigins();
2549

0 commit comments

Comments
 (0)