mirror of
https://github.com/AutoMaker-Org/automaker.git
synced 2026-01-30 06:12:03 +00:00
feat: add middleware to enforce JSON Content-Type for API requests
- Introduced `requireJsonContentType` middleware to ensure that all POST, PUT, and PATCH requests have the Content-Type set to application/json. - This enhancement improves security by preventing CSRF and content-type confusion attacks, ensuring only properly formatted requests are processed.
This commit is contained in:
@@ -18,6 +18,7 @@ import dotenv from 'dotenv';
|
||||
import { createEventEmitter, type EventEmitter } from './lib/events.js';
|
||||
import { initAllowedPaths } from '@automaker/platform';
|
||||
import { authMiddleware, validateWsConnectionToken, checkRawAuthentication } from './lib/auth.js';
|
||||
import { requireJsonContentType } from './middleware/require-json-content-type.js';
|
||||
import { createAuthRoutes } from './routes/auth/index.js';
|
||||
import { createFsRoutes } from './routes/fs/index.js';
|
||||
import { createHealthRoutes, createDetailedHandler } from './routes/health/index.js';
|
||||
@@ -173,6 +174,10 @@ setInterval(() => {
|
||||
}
|
||||
}, VALIDATION_CLEANUP_INTERVAL_MS);
|
||||
|
||||
// Require Content-Type: application/json for all API POST/PUT/PATCH requests
|
||||
// This helps prevent CSRF and content-type confusion attacks
|
||||
app.use('/api', requireJsonContentType);
|
||||
|
||||
// Mount API routes - health and auth are unauthenticated
|
||||
app.use('/api/health', createHealthRoutes());
|
||||
app.use('/api/auth', createAuthRoutes());
|
||||
|
||||
50
apps/server/src/middleware/require-json-content-type.ts
Normal file
50
apps/server/src/middleware/require-json-content-type.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
/**
|
||||
* Middleware to enforce Content-Type: application/json for request bodies
|
||||
*
|
||||
* This security middleware prevents malicious requests by requiring proper
|
||||
* Content-Type headers for all POST, PUT, and PATCH requests.
|
||||
*
|
||||
* Rejecting requests without proper Content-Type helps prevent:
|
||||
* - CSRF attacks via form submissions (which use application/x-www-form-urlencoded)
|
||||
* - Content-type confusion attacks
|
||||
* - Malformed request exploitation
|
||||
*/
|
||||
|
||||
import type { Request, Response, NextFunction } from 'express';
|
||||
|
||||
// HTTP methods that typically include request bodies
|
||||
const METHODS_REQUIRING_JSON = ['POST', 'PUT', 'PATCH'];
|
||||
|
||||
/**
|
||||
* Middleware that requires Content-Type: application/json for POST/PUT/PATCH requests
|
||||
*
|
||||
* Returns 415 Unsupported Media Type if:
|
||||
* - The request method is POST, PUT, or PATCH
|
||||
* - AND the Content-Type header is missing or not application/json
|
||||
*
|
||||
* Allows requests to pass through if:
|
||||
* - The request method is GET, DELETE, OPTIONS, HEAD, etc.
|
||||
* - OR the Content-Type is properly set to application/json (with optional charset)
|
||||
*/
|
||||
export function requireJsonContentType(req: Request, res: Response, next: NextFunction): void {
|
||||
// Skip validation for methods that don't require a body
|
||||
if (!METHODS_REQUIRING_JSON.includes(req.method)) {
|
||||
next();
|
||||
return;
|
||||
}
|
||||
|
||||
const contentType = req.headers['content-type'];
|
||||
|
||||
// Check if Content-Type header exists and contains application/json
|
||||
// Allows for charset parameter: "application/json; charset=utf-8"
|
||||
if (!contentType || !contentType.toLowerCase().includes('application/json')) {
|
||||
res.status(415).json({
|
||||
success: false,
|
||||
error: 'Unsupported Media Type',
|
||||
message: 'Content-Type header must be application/json',
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
next();
|
||||
}
|
||||
Reference in New Issue
Block a user