@@ -19,7 +19,7 @@ import { Transport } from "@modelcontextprotocol/sdk/shared/transport.js";
19
19
import express from "express" ;
20
20
import { findActualExecutable } from "spawn-rx" ;
21
21
import mcpProxy from "./mcpProxy.js" ;
22
- import { randomUUID , randomBytes } from "node:crypto" ;
22
+ import { randomUUID , randomBytes , timingSafeEqual } from "node:crypto" ;
23
23
24
24
const SSE_HEADERS_PASSTHROUGH = [ "authorization" ] ;
25
25
const STREAMABLE_HTTP_HEADERS_PASSTHROUGH = [
@@ -120,14 +120,38 @@ const authMiddleware = (req: express.Request, res: express.Response, next: expre
120
120
return next ( ) ;
121
121
}
122
122
123
- const authHeader = req . headers . authorization ;
124
- if ( ! authHeader || authHeader !== `Bearer ${ sessionToken } ` ) {
123
+ const sendUnauthorized = ( ) => {
125
124
res . status ( 401 ) . json ( {
126
125
error : "Unauthorized" ,
127
126
message : "Authentication required. Use the session token shown in the console when starting the server."
128
127
} ) ;
128
+ } ;
129
+
130
+ const authHeader = req . headers . authorization ;
131
+ if ( ! authHeader || ! authHeader . startsWith ( 'Bearer ' ) ) {
132
+ sendUnauthorized ( ) ;
129
133
return ;
130
134
}
135
+
136
+ const providedToken = authHeader . substring ( 7 ) ; // Remove 'Bearer ' prefix
137
+ const expectedToken = sessionToken ;
138
+
139
+ // Convert to buffers for timing-safe comparison
140
+ const providedBuffer = Buffer . from ( providedToken ) ;
141
+ const expectedBuffer = Buffer . from ( expectedToken ) ;
142
+
143
+ // Check length first to prevent timing attacks
144
+ if ( providedBuffer . length !== expectedBuffer . length ) {
145
+ sendUnauthorized ( ) ;
146
+ return ;
147
+ }
148
+
149
+ // Perform timing-safe comparison
150
+ if ( ! timingSafeEqual ( providedBuffer , expectedBuffer ) ) {
151
+ sendUnauthorized ( ) ;
152
+ return ;
153
+ }
154
+
131
155
next ( ) ;
132
156
} ;
133
157
@@ -444,7 +468,7 @@ app.get("/health", (req, res) => {
444
468
} ) ;
445
469
} ) ;
446
470
447
- app . get ( "/config" , ( req , res ) => {
471
+ app . get ( "/config" , originValidationMiddleware , authMiddleware , ( req , res ) => {
448
472
try {
449
473
res . json ( {
450
474
defaultEnvironment,
0 commit comments