Root cause
Injection & unsafe execution introduced
The hyperlink helper directly interpolates the supplied URI and display text.
How AI contributed: Direct introductionPublished May 18, 2026 in
jarrodwatts/claude-hudAll 2 findings in this repository
Provisional finding. Full causal and release verification remains incomplete.
Root cause
The hyperlink helper directly interpolates the supplied URI and display text.
Fix
The replacement sanitizes and validates hyperlink destinations before emitting a link.
Case facts
@@ -2,6 +4,13 @@ import { getModelName, getProviderLabel } from '../../stdin.js'; import { getOutputSpeed } from '../../speed-tracker.js';-import { git as gitColor, gitBranch as gitBranchColor, label, model as modelColor, project as projectColor, red, custom as customColor } from '../colors.js';+import { git as gitColor, gitBranch as gitBranchColor, label, model as modelColor, project as projectColor, red, green, yellow, dim, custom as customColor } from '../colors.js';++/** Wrap text in an OSC 8 terminal hyperlink (works in iTerm2, WezTerm, Kitty, Ghostty, etc.) */+function hyperlink(uri: string, text: string): string {+ const ESC = '\x1b';+ const ST = '\\';+ return `${ESC}]8;;${uri}${ESC}${ST}${text}${ESC}]8;;${ESC}${ST}`;+} export function renderProjectLine(ctx: RenderContext): string | null { const display = ctx.config?.display;@@ -16,0 +35,18 @@+ if (relative === '' || (!relative.startsWith('..') && !path.isAbsolute(relative))) {+ return resolvedPath;+ }+ return null;+}++function safeHyperlink(uri: string | undefined | null, text: string): string {+ if (!uri) {+ return text;+ }++ const sanitizedUri = sanitizeDisplayText(uri);+ try {+ const parsed = new URL(sanitizedUri);+ if (parsed.protocol !== 'https:' && parsed.protocol !== 'file:') {+ return text;+ }+ return hyperlink(parsed.toString(), text);AI-assisted change 335b1c954f0ee8b78328f66fa8e433561776c3dce7ada1ad78eae457b8233855 · Fix 3e2585361a327567ed9a9bb41389f0efd78b601205133d52459a6eb736496d1d