From 9814af5c9db398b9d9ce6eb018c2ddd1e9c03198 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 22 Jun 2026 01:39:13 +0000 Subject: [PATCH] chore: publish from staged --- hooks/fix-broken-links/link-fix.ps1 | 13 ++++++++++++- hooks/fix-broken-links/link-fix.sh | 16 ++++++++++++++-- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/hooks/fix-broken-links/link-fix.ps1 b/hooks/fix-broken-links/link-fix.ps1 index f50e2e71..ca3a5310 100644 --- a/hooks/fix-broken-links/link-fix.ps1 +++ b/hooks/fix-broken-links/link-fix.ps1 @@ -158,7 +158,8 @@ function Get-AgentAlts { param([string]$Url,[int]$Max) if (-not (Get-Command copilot -ErrorAction SilentlyContinue)) { return @() } $snappy = $AGENT_TIMEOUT - 5 - $prompt = "In under $snappy seconds, find up to $Max working alternative URLs for the broken link $Url. Hierarchically consider 1. Path and/or page spelling; 2. web.archive.org/wayback; 3. Redirects using redirect destination; 4. The context of the link's text; in order to resolve. Output only the URLs. One per line, and no: prose, numbering, markdown, backticks, special characters, post formatting." + $promptUrl = Get-PromptSafeUrl $Url + $prompt = "In under $snappy seconds, find up to $Max working alternative URLs for the broken link $promptUrl. Hierarchically consider 1. Path and/or page spelling; 2. web.archive.org/wayback; 3. Redirects using redirect destination; 4. The context of the link's text; in order to resolve. Output only the URLs. One per line, and no: prose, numbering, markdown, backticks, special characters, post formatting." $out = '' try { # FIX_BROKEN_LINKS_AGENT marks the child run so a re-entrant hook exits early. @@ -190,6 +191,16 @@ function Get-AgentAlts { return ,$result.ToArray() } +# Prepare a URL for safe embedding inside a prompt string. +# This is defense-in-depth for values that originate from document content. +function Get-PromptSafeUrl { + param([string]$Url) + if ($null -eq $Url) { return '' } + $safe = $Url -replace '[\r\n]+', ' ' + $safe = $safe -replace '[`$()]', '' + return $safe +} + # Up to MAX viable replacement URLs for a broken link, best first: # 1. a working scheme/www/slash variation (verified live 200) # 2. alternatives proposed by the Copilot CLI agent (see Get-AgentAlts) diff --git a/hooks/fix-broken-links/link-fix.sh b/hooks/fix-broken-links/link-fix.sh index 9578c85a..e12f5e91 100644 --- a/hooks/fix-broken-links/link-fix.sh +++ b/hooks/fix-broken-links/link-fix.sh @@ -171,9 +171,10 @@ find_variation() { # from anywhere in the output, trim trailing punctuation, drop the broken URL # itself, and de-duplicate (case-insensitively). Up to MAX lines, one URL each. agent_alts() { - local url="$1" max="$2" prompt out + local url="$1" max="$2" prompt out prompt_url command -v copilot >/dev/null 2>&1 || return 0 - prompt="In under $((AGENT_TIMEOUT - 5)) seconds, find up to ${max} working alternative URLs for the broken link ${url}. Hierarchically consider 1. Path and/or page spelling; 2. web.archive.org/wayback; 3. Redirects using redirect destination; 4. The context of the link's text; in order to resolve. Output only the URLs. One per line, and no: prose, numbering, markdown, backticks, special characters, post formatting." + prompt_url="$(sanitize_prompt_url "$url")" + prompt="In under $((AGENT_TIMEOUT - 5)) seconds, find up to ${max} working alternative URLs for the broken link ${prompt_url}. Hierarchically consider 1. Path and/or page spelling; 2. web.archive.org/wayback; 3. Redirects using redirect destination; 4. The context of the link's text; in order to resolve. Output only the URLs. One per line, and no: prose, numbering, markdown, backticks, special characters, post formatting." # FIX_BROKEN_LINKS_AGENT marks the child run so a re-entrant hook exits early. out="$(FIX_BROKEN_LINKS_AGENT=1 $AGENT_RUN copilot -p "$prompt" \ -s --no-color --model "$AGENT_MODEL" --available-tools 2>/dev/null)" @@ -209,6 +210,17 @@ suggest_alts() { printf '%s\n' "${out[@]}" } +# Prepare a URL for safe embedding inside a shell-built prompt string. +# This is defense-in-depth for values that originate from document content. +sanitize_prompt_url() { + local s="$1" + s="${s//$'\r'/ }" + s="${s//$'\n'/ }" + s="${s//\`/\\\`}" + s="${s//\$/\\\$}" + printf '%s' "$s" +} + # Replace a literal URL everywhere in a file (pure bash, no regex). replace_url() { local file="$1" old="$2" new="$3" content pat