From fc90a71787edaf2e00531366534e72f3e7882a9d Mon Sep 17 00:00:00 2001 From: TeoSlayer Date: Mon, 22 Jun 2026 17:37:09 +0300 Subject: [PATCH] Escape user input in publish review to prevent XSS --- src/pages/publish.astro | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/pages/publish.astro b/src/pages/publish.astro index ed5dce4..3f6f47f 100644 --- a/src/pages/publish.astro +++ b/src/pages/publish.astro @@ -532,17 +532,19 @@ async function refreshPreview(){ function renderReview(){ const s=submission(); + // Each value carries already-escaped HTML; the only markup allowed in a value + // is the
separators in Methods. All user-controlled text goes through esc(). const rows=[ - ['App ID',s.id],['Version',s.version],['Description',s.description], - ['Backend',s.backend.base_url], - ...(s.backend.headers.map(h=>['Header',h.name+': '+h.value])), - ['Methods',s.methods.map(m=>`${m.name} (${m.http.verb} ${m.http.path}, ${m.latency})`).join('
')||'—'], - ['Display name',s.listing.display_name],['License',s.listing.license], - ['App description',s.listing.app_description],['Categories',(s.listing.categories||[]).join(', ')], + ['App ID',esc(s.id)],['Version',esc(s.version)],['Description',esc(s.description)], + ['Backend',esc(s.backend.base_url)], + ...(s.backend.headers.map(h=>['Header',esc(h.name+': '+h.value)])), + ['Methods',s.methods.map(m=>esc(`${m.name} (${m.http.verb} ${m.http.path}, ${m.latency})`)).join('
')], + ['Display name',esc(s.listing.display_name)],['License',esc(s.listing.license)], + ['App description',esc(s.listing.app_description)],['Categories',esc((s.listing.categories||[]).join(', '))], ['App type','HTTP API'], - ['Vendor',s.vendor.name+(s.vendor.url?' · '+s.vendor.url:'')],['Email',s.email], - ['Agent usage',s.vendor.agent_usage],['Capabilities',s.vendor.capabilities], - ['Signed by',s.release.signer_name], + ['Vendor',esc(s.vendor.name+(s.vendor.url?' · '+s.vendor.url:''))],['Email',esc(s.email)], + ['Agent usage',esc(s.vendor.agent_usage)],['Capabilities',esc(s.vendor.capabilities)], + ['Signed by',esc(s.release.signer_name)], ]; document.getElementById('review-tbl').innerHTML=rows.map(([k,v])=>`${esc(k)}${v||''}`).join(''); }