some sec hardenings

This commit is contained in:
Oliver Kieselbach
2026-03-31 04:56:07 +02:00
parent 2625d1f948
commit 31f8d2af37
5 changed files with 26 additions and 21 deletions
@@ -1 +1 @@
732
733
@@ -192,10 +192,25 @@ namespace AutopilotMonitor.Functions.Functions.Ingest
{
// X-Forwarded-For can contain "client, proxy1, proxy2" — take the first
var ip = fwd.Split(',')[0].Trim();
// Strip port if present (e.g., "1.2.3.4:12345")
// Handle bracketed IPv6 with port: [::1]:12345
if (ip.StartsWith('['))
{
var closeBracket = ip.IndexOf(']');
if (closeBracket > 0)
ip = ip.Substring(1, closeBracket - 1);
return ip;
}
// Bare IPv6 (contains multiple colons): return as-is
if (ip.IndexOf(':') != ip.LastIndexOf(':'))
return ip;
// IPv4 with optional port: strip port (e.g., "1.2.3.4:12345")
var colonIdx = ip.LastIndexOf(':');
if (colonIdx > 0 && !ip.Contains(']')) // avoid stripping IPv6
if (colonIdx > 0)
ip = ip.Substring(0, colonIdx);
return ip;
}
}
@@ -9,7 +9,7 @@
*/
import type { Request, Response, NextFunction } from 'express';
import { extractTokenClaims, isTokenExpired } from './auth.js';
import { setCurrentToken, runWithToken } from './client.js';
import { runWithToken } from './client.js';
const BASE_URL = process.env.AUTOPILOT_API_URL ?? 'https://autopilotmonitor-api.azurewebsites.net';
@@ -148,11 +148,8 @@ export function accessGuard(req: Request, res: Response, next: NextFunction): vo
return;
}
// Set token for pass-through to backend API.
// runWithToken scopes the token to this async context so concurrent
// sessions cannot overwrite each other's tokens on the event loop.
// setCurrentToken is kept as fallback during the transition.
setCurrentToken(token);
// Scope the token to this async context so concurrent sessions
// cannot overwrite each other's tokens on the event loop.
runWithToken(token, () => next());
})
.catch(() => {
@@ -23,19 +23,8 @@ export function runWithToken<T>(token: string, fn: () => T): T {
return tokenStore.run(token, fn);
}
/**
* @deprecated Use `runWithToken` instead. Kept for backward compatibility
* during the transition — sets a fallback global token for code paths that
* haven't migrated to `runWithToken` yet.
*/
let _fallbackToken: string | undefined;
export function setCurrentToken(token: string | undefined): void {
_fallbackToken = token;
}
export function getCurrentToken(): string | undefined {
return tokenStore.getStore() ?? _fallbackToken;
return tokenStore.getStore();
}
async function apiFetch(path: string, options: RequestInit = {}): Promise<unknown> {
@@ -270,6 +270,10 @@ export function registerAdminTools(server: McpServer): void {
);
// ── Admin Diagnostic Tools ────────────────────────────────────────────
// Security note: query_table and query_backend_logs accept arbitrary OData/KQL
// expressions. This is by design — these are trusted-admin-only diagnostic tools
// gated by GlobalAdmin RBAC on the backend. No client-side filter allowlist is
// needed because the backend enforces the same permission boundary.
// Tool 20: list_tables
server.tool(