diff --git a/src/browser/OscLinkProvider.ts b/src/browser/OscLinkProvider.ts index c621ddf2..648ffa44 100644 --- a/src/browser/OscLinkProvider.ts +++ b/src/browser/OscLinkProvider.ts @@ -66,14 +66,30 @@ export class OscLinkProvider implements ILinkProvider { y } }; - // OSC links always use underline and pointer decorations - result.push({ - text, - range, - activate: (e, text) => (linkHandler ? linkHandler.activate(e, text, range) : defaultActivate(e, text)), - hover: (e, text) => linkHandler?.hover?.(e, text, range), - leave: (e, text) => linkHandler?.leave?.(e, text, range) - }); + + let ignoreLink = false; + if (!linkHandler?.allowNonHttpProtocols) { + try { + const parsed = new URL(text); + if (!['http:', 'https:'].includes(parsed.protocol)) { + ignoreLink = true; + } + } catch (e) { + // Ignore invalid URLs to prevent unexpected behaviors + ignoreLink = true; + } + } + + if (!ignoreLink) { + // OSC links always use underline and pointer decorations + result.push({ + text, + range, + activate: (e, text) => (linkHandler ? linkHandler.activate(e, text, range) : defaultActivate(e, text)), + hover: (e, text) => linkHandler?.hover?.(e, text, range), + leave: (e, text) => linkHandler?.leave?.(e, text, range) + }); + } } finishLink = false; diff --git a/typings/xterm.d.ts b/typings/xterm.d.ts index b652491a..dc7c38b2 100644 --- a/typings/xterm.d.ts +++ b/typings/xterm.d.ts @@ -1179,6 +1179,13 @@ declare module 'xterm' { * @param range The buffer range of the link. */ leave?(event: MouseEvent, text: string, range: IBufferRange): void; + + /** + * Whether to receive non-HTTP URLs from LinkProvider. When false, any usage of non-HTTP URLs + * will be ignored. Enabling this option without proper protection in `activate` function + * may cause security issues such as XSS. + */ + allowNonHttpProtocols?: boolean; } /**