Skip to content

Commit 8febac4

Browse files
aaronpowellCopilot
andauthored
fix: harden fix-broken-links prompt url handling (#2083)
Sanitize URL input before embedding it in Copilot handoff prompts in both bash and PowerShell hook scripts to prevent command/prompt injection from untrusted link text. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 7d0694f commit 8febac4

2 files changed

Lines changed: 26 additions & 3 deletions

File tree

‎hooks/fix-broken-links/link-fix.ps1‎

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,8 @@ function Get-AgentAlts {
158158
param([string]$Url,[int]$Max)
159159
if (-not (Get-Command copilot -ErrorAction SilentlyContinue)) { return @() }
160160
$snappy = $AGENT_TIMEOUT - 5
161-
$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."
161+
$promptUrl = Get-PromptSafeUrl $Url
162+
$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."
162163
$out = ''
163164
try {
164165
# FIX_BROKEN_LINKS_AGENT marks the child run so a re-entrant hook exits early.
@@ -190,6 +191,16 @@ function Get-AgentAlts {
190191
return ,$result.ToArray()
191192
}
192193

194+
# Prepare a URL for safe embedding inside a prompt string.
195+
# This is defense-in-depth for values that originate from document content.
196+
function Get-PromptSafeUrl {
197+
param([string]$Url)
198+
if ($null -eq $Url) { return '' }
199+
$safe = $Url -replace '[\r\n]+', ' '
200+
$safe = $safe -replace '[`$()]', ''
201+
return $safe
202+
}
203+
193204
# Up to MAX viable replacement URLs for a broken link, best first:
194205
# 1. a working scheme/www/slash variation (verified live 200)
195206
# 2. alternatives proposed by the Copilot CLI agent (see Get-AgentAlts)

‎hooks/fix-broken-links/link-fix.sh‎

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -171,9 +171,10 @@ find_variation() {
171171
# from anywhere in the output, trim trailing punctuation, drop the broken URL
172172
# itself, and de-duplicate (case-insensitively). Up to MAX lines, one URL each.
173173
agent_alts() {
174-
local url="$1" max="$2" prompt out
174+
local url="$1" max="$2" prompt out prompt_url
175175
command -v copilot >/dev/null 2>&1 || return 0
176-
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."
176+
prompt_url="$(sanitize_prompt_url "$url")"
177+
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."
177178
# FIX_BROKEN_LINKS_AGENT marks the child run so a re-entrant hook exits early.
178179
out="$(FIX_BROKEN_LINKS_AGENT=1 $AGENT_RUN copilot -p "$prompt" \
179180
-s --no-color --model "$AGENT_MODEL" --available-tools 2>/dev/null)"
@@ -209,6 +210,17 @@ suggest_alts() {
209210
printf '%s\n' "${out[@]}"
210211
}
211212

213+
# Prepare a URL for safe embedding inside a shell-built prompt string.
214+
# This is defense-in-depth for values that originate from document content.
215+
sanitize_prompt_url() {
216+
local s="$1"
217+
s="${s//$'\r'/ }"
218+
s="${s//$'\n'/ }"
219+
s="${s//\`/\\\`}"
220+
s="${s//\$/\\\$}"
221+
printf '%s' "$s"
222+
}
223+
212224
# Replace a literal URL everywhere in a file (pure bash, no regex).
213225
replace_url() {
214226
local file="$1" old="$2" new="$3" content pat

0 commit comments

Comments
 (0)