initrftsebfvgyhloutersvbhustdr

This commit is contained in:
ZOMBIIIIIII
2026-05-28 22:40:36 +03:00
parent 444030e424
commit 4c00c6ca1b
4 changed files with 64 additions and 6 deletions

View File

@@ -10,6 +10,7 @@ import { authMiddleware } from './middleware/auth';
import { csrfMiddleware } from './middleware/csrf';
import { globalLimiter, mutateLimiter, sensitiveLimiter, mnemonicRevealLimiter } from './middleware/rate-limit';
import { errorHandler } from './middleware/error-handler';
import { generateCsrfToken } from './services/csrf.service';
import walletRoutes from './routes/wallet.routes';
import relayProxyRoutes from './routes/relay-proxy.routes';
import jumperProxyRoutes from './routes/jumper-proxy.routes';
@@ -41,6 +42,7 @@ app.use(
origin: corsIsWildcard ? '*' : (corsOrigins.length > 0 ? corsOrigins : false),
// Wildcard incompatible с credentials per browser spec — force false при wildcard.
credentials: corsIsWildcard ? false : env.cors.allowCredentials,
exposedHeaders: ['X-CSRF-Token', 'X-Trace-ID'],
}),
);
app.use(express.json({ limit: '64kb' })); // защита от больших payload-DoS
@@ -65,6 +67,30 @@ app.get('/api/health', async (_req, res) => {
// ── Глобальный rate limit на /api/* — ДО docs чтобы не было unauthenticated DoS на swagger.json
app.use('/api', globalLimiter);
app.get('/api/csrf', (_req, res) => {
if (!env.vault.csrfPath) {
res.json({ success: true, data: { enabled: false, csrfToken: null } });
return;
}
try {
const { token, maxAgeSec } = generateCsrfToken();
const crossSiteCookie = !corsIsWildcard && env.cors.allowCredentials;
res.cookie('csrf_token', token, {
httpOnly: false,
secure: crossSiteCookie,
sameSite: crossSiteCookie ? 'none' : 'lax',
maxAge: maxAgeSec * 1000,
path: '/',
});
res.setHeader('Cache-Control', 'no-store');
res.setHeader('X-CSRF-Token', token);
res.json({ success: true, data: { enabled: true, csrfToken: token, maxAgeSec } });
} catch (err: any) {
res.status(503).json({ success: false, error: err.message || 'CSRF token unavailable' });
}
});
// H1 — Swagger gated. В production требуется basic-auth ИЛИ NODE_ENV != production.
// JSON endpoint ОБЯЗАТЕЛЬНО до app.use('/api/docs', ...) — иначе swagger-ui-express
// перехватывает все /api/docs/* и возвращает HTML вместо JSON.