mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-06-21 14:21:46 +00:00
fix: prevent Invalid URL crash when APP_URL lacks a protocol (#972)
* fix: prevent Invalid URL crash when APP_URL lacks a protocol (issue #970) - Add getMcpSafeUrl() to notifications.ts: wraps getAppUrl() and guarantees a result that satisfies the MCP SDK's checkIssuerUrl requirement (https:// or http://localhost). Non-HTTPS, non-localhost URLs fall back to http://localhost:{PORT} instead of propagating an "Issuer URL must be HTTPS" error. - Switch app.ts, mcp/index.ts, mcp/oauthProvider.ts, and oauthService.ts to import getMcpSafeUrl instead of getAppUrl for all MCP resource URL construction, so a misconfigured APP_URL never crashes the metadata router initialisation. - Restrict the SDK metadata router middleware to /.well-known/* paths only. Previously it was invoked on every request; in production the lazy getMetaRouter() init ran on GET / and threw "Invalid URL" when APP_URL had no scheme, returning 500 for every page load. - Log a startup warning when APP_URL is set but not usable, and include the resolved App URL in the startup banner so operators can confirm the correct value at a glance. - Update oauth.test.ts mock to target notifications.getMcpSafeUrl. * fix: show getAppUrl in banner and add two separate APP_URL startup checks - Banner now displays getAppUrl() (the resolved app URL) rather than getMcpSafeUrl() so operators see the actual configured value - Two independent startup warnings after the banner when APP_URL is set: 1. whether APP_URL is a valid URL (parseable by new URL()) 2. whether APP_URL is MCP-safe (https:// or http://localhost) - Fix getMcpSafeUrl() fallback port to use Number(PORT) || 3001, consistent with how index.ts parses PORT * fix: update oidc.ts to import getAppUrl from notifications
This commit is contained in:
@@ -46,13 +46,42 @@ function getSmtpConfig(): SmtpConfig | null {
|
||||
|
||||
// Exported for use by notificationService
|
||||
export function getAppUrl(): string {
|
||||
if (process.env.APP_URL) return process.env.APP_URL;
|
||||
if (process.env.APP_URL) {
|
||||
try {
|
||||
const _ = new URL(process.env.APP_URL);
|
||||
return process.env.APP_URL.replace(/\/+$/, '');
|
||||
} catch (_ignored) {
|
||||
}
|
||||
}
|
||||
const origins = process.env.ALLOWED_ORIGINS;
|
||||
if (origins) {
|
||||
const first = origins.split(',')[0]?.trim();
|
||||
if (first) return first.replace(/\/+$/, '');
|
||||
if (first) {
|
||||
try {
|
||||
const _ = new URL(first);
|
||||
return first.replace(/\/+$/, '');
|
||||
} catch (_ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
const port = process.env.PORT || '3000';
|
||||
const port = Number(process.env.PORT) || 3001;
|
||||
return `http://localhost:${port}`;
|
||||
}
|
||||
|
||||
/** Returns a URL guaranteed to satisfy the MCP SDK's issuer requirements (HTTPS or localhost).
|
||||
* Falls back to http://localhost:{PORT} when APP_URL/ALLOWED_ORIGINS use a non-HTTPS, non-localhost scheme
|
||||
* that would cause checkIssuerUrl to throw "Issuer URL must be HTTPS". */
|
||||
export function getMcpSafeUrl(): string {
|
||||
const candidate = getAppUrl();
|
||||
try {
|
||||
const u = new URL(candidate);
|
||||
if (u.protocol === 'https:' || u.hostname === 'localhost' || u.hostname === '127.0.0.1') {
|
||||
return candidate;
|
||||
}
|
||||
} catch {
|
||||
// candidate was somehow invalid — fall through to localhost
|
||||
}
|
||||
const port = Number(process.env.PORT) || 3001;
|
||||
return `http://localhost:${port}`;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user