@@ -9,6 +9,7 @@ import { checkBudget } from "./costs";
99import { recordCommandResult } from "./reliability" ;
1010import { readFileSync } from "fs" ;
1111import { join } from "path" ;
12+ import { timingSafeEqual } from "crypto" ;
1213import { createMcpToolHandlers , type MCPToolHandler , type ToolExecutionResult } from "./mcp_dispatcher" ;
1314
1415type PolicyMode = "read_only" | "engagement" | "moderation" ;
@@ -38,7 +39,8 @@ function envOrDotEnv(key: string): string | undefined {
3839 try {
3940 const envPath = join ( import . meta. dir , ".." , ".env" ) ;
4041 const raw = readFileSync ( envPath , "utf-8" ) ;
41- const m = raw . match ( new RegExp ( `^${ key } =["']?([^"'\\n]+)` , "m" ) ) ;
42+ const safeKey = key . replace ( / [ . * + ? ^ $ { } ( ) | [ \] \\ ] / g, "\\$&" ) ;
43+ const m = raw . match ( new RegExp ( `^${ safeKey } =["']?([^"'\\n]+)` , "m" ) ) ;
4244 if ( m ?. [ 1 ] ) return m [ 1 ] . trim ( ) ;
4345 } catch { }
4446 return undefined ;
@@ -664,7 +666,11 @@ async function runStdio(options: MCPServerOptions) {
664666
665667function hasValidBearerToken ( authHeader : string | undefined , expectedToken : string ) : boolean {
666668 if ( ! authHeader || ! authHeader . startsWith ( "Bearer " ) ) return false ;
667- return authHeader . slice ( "Bearer " . length ) . trim ( ) === expectedToken ;
669+ const provided = authHeader . slice ( "Bearer " . length ) . trim ( ) ;
670+ const a = Buffer . from ( provided ) ;
671+ const b = Buffer . from ( expectedToken ) ;
672+ if ( a . length !== b . length ) return false ;
673+ return timingSafeEqual ( a , b ) ;
668674}
669675
670676async function runSSE ( port : number , options : MCPSSEServerOptions ) {
0 commit comments