sched: SECURITY — закрыть /mcp и / (morda) без токена; auth-гвард на входе (кроме /api/health + static UI)
This commit is contained in:
@@ -51,10 +51,28 @@ const mcpHandler = createMcpHttpHandler({ client: mcpClient, readonly: process.e
|
||||
let uiBundle = null;
|
||||
try { uiBundle = readFileSync(DEFAULT_UI_BUNDLE); } catch { /* bundle missing → morda 404s its script */ }
|
||||
|
||||
// One HTTP server, auth at the boundary: everything EXCEPT /api/health (probe, open) and
|
||||
// /sched-ui.bundle.js (static UI assets) requires `Authorization: Bearer SCHED_ADMIN_KEY`.
|
||||
// This closes the MCP + admin API + morda exposed WITHOUT a token (vitya found /mcp open).
|
||||
const AUTH_OPEN_PATHS = ['/api/health'];
|
||||
function isOpenPath(p) {
|
||||
return AUTH_OPEN_PATHS.includes(p) || p === '/sched-ui.bundle.js';
|
||||
}
|
||||
function isAuthorized(req) {
|
||||
if (!ADMIN_KEY) return true; // dev mode, open
|
||||
const h = req.headers.authorization;
|
||||
return h === `Bearer ${ADMIN_KEY}`;
|
||||
}
|
||||
|
||||
const server = createServer(async (req, res) => {
|
||||
const url = new URL(req.url ?? '/', `http://${req.headers.host ?? 'localhost'}`);
|
||||
const p = url.pathname;
|
||||
try {
|
||||
if (!isOpenPath(p) && !isAuthorized(req)) {
|
||||
res.writeHead(401, { 'content-type': 'application/json' });
|
||||
res.end(JSON.stringify({ error: 'unauthorized' }));
|
||||
return;
|
||||
}
|
||||
if (p === '/api' || p.startsWith('/api/')) {
|
||||
req.url = p.replace(/^\/api/, '') + url.search; // strip /api mount prefix
|
||||
await adminApi.handleRequest(req, res);
|
||||
|
||||
Reference in New Issue
Block a user