Skip to content

Commit 783bf86

Browse files
committed
Sanitizing URLs before invoking open()
1 parent 2a0665d commit 783bf86

2 files changed

Lines changed: 18 additions & 2 deletions

File tree

src/lib/node-oauth-client-provider.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import {
99
import type { OAuthProviderOptions, StaticOAuthClientMetadata } from './types'
1010
import { readJsonFile, writeJsonFile, readTextFile, writeTextFile, deleteConfigFile } from './mcp-auth-config'
1111
import { StaticOAuthClientInformationFull } from './types'
12-
import { getServerUrlHash, log, debugLog, DEBUG, MCP_REMOTE_VERSION } from './utils'
12+
import { getServerUrlHash, log, debugLog, DEBUG, MCP_REMOTE_VERSION, sanitizeUrl } from './utils'
1313
import { randomUUID } from 'node:crypto'
1414

1515
/**
@@ -172,7 +172,7 @@ export class NodeOAuthClientProvider implements OAuthClientProvider {
172172
if (DEBUG) debugLog('Redirecting to authorization URL', authorizationUrl.toString())
173173

174174
try {
175-
await open(authorizationUrl.toString())
175+
await open(sanitizeUrl(authorizationUrl.toString()))
176176
log('Browser opened automatically.')
177177
} catch (error) {
178178
log('Could not open browser automatically. Please copy and paste the URL above into your browser.')

src/lib/utils.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -704,3 +704,19 @@ export function setupSignalHandlers(cleanup: () => Promise<void>) {
704704
export function getServerUrlHash(serverUrl: string): string {
705705
return crypto.createHash('md5').update(serverUrl).digest('hex')
706706
}
707+
708+
export function sanitizeUrl(raw: string) {
709+
const url = new URL(raw)
710+
if (url.protocol !== 'https:' && url.protocol !== 'http:') {
711+
throw new Error(`Invalid url to pass to open(): ${url}`)
712+
}
713+
url.hostname = encodeURIComponent(url.hostname)
714+
url.pathname = url.pathname.slice(0, 1) + encodeURIComponent(url.pathname.slice(1))
715+
url.search = url.search.slice(0, 1) + Array.from(url.searchParams.entries()).map(sanitizeParam).join('&')
716+
url.hash = url.hash.slice(0, 1) + encodeURIComponent(url.hash.slice(1))
717+
return url.href
718+
}
719+
720+
function sanitizeParam([k, v]: [string, string]) {
721+
return `${encodeURIComponent(k)}${v.length > 0 ? `=${encodeURIComponent(v)}` : ''}`
722+
}

0 commit comments

Comments
 (0)