← back to Commercialrealestate
crcp parcel detail: safeHref protocol whitelist (XSS fix) + drop dead deal_city drill → plain text (TK-10482 contrarian blockers)
60799a11742ec29bcaaa686bf295b7c386e63ab3 · 2026-08-12 08:41:14 -0700 · Steve Abrams
Files touched
Diff
commit 60799a11742ec29bcaaa686bf295b7c386e63ab3
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Wed Aug 12 08:41:14 2026 -0700
crcp parcel detail: safeHref protocol whitelist (XSS fix) + drop dead deal_city drill → plain text (TK-10482 contrarian blockers)
---
public/parcel.html | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/public/parcel.html b/public/parcel.html
index 702a4f3..2be28a3 100644
--- a/public/parcel.html
+++ b/public/parcel.html
@@ -57,7 +57,9 @@ const AIN=(location.pathname.match(/\/(?:parcel|deal)\/(\d+)/)||[])[1]
// href-drill helpers: every data point links to its deeper data.
const dfLink=(field,val,label)=>val==null||val===''?esc(label==null?'':label)
:`<a class="drill" href="/deals-flow.html?${field}=${encodeURIComponent(val)}" title="See all ${esc(field)} = ${esc(val)} deals">${esc(label==null?val:label)}</a>`;
-const ext=(url,label,title)=>`<a class="ext" href="${esc(url)}" target="_blank" rel="noopener noreferrer" title="${esc(title||'')}">${esc(label)} ↗</a>`;
+// safeHref: protocol whitelist so a hostile feed value (javascript:/data:) can never land in an href (TK-10482 contrarian BLOCKER fix; mirrors usre deals.html safeHref).
+const safeHref=u=>{try{const p=new URL(String(u==null?'':u),location.origin);return (p.protocol==='http:'||p.protocol==='https:')?p.href:'#';}catch(e){return '#';}};
+const ext=(url,label,title)=>`<a class="ext" href="${esc(safeHref(url))}" target="_blank" rel="noopener noreferrer" title="${esc(title||'')}">${esc(label)} ↗</a>`;
const kv=(k,v)=>(v==null||v==='')?'':`<div class="kv"><span class="k">${esc(k)}</span><span class="v">${v}</span></div>`;
async function load(){
@@ -87,7 +89,7 @@ function render(d){
html+=`<div class="panel"><h3>Parcel</h3>`
+kv('AIN', `<b>${esc(p.ain||AIN)}</b> · ${ext(d.portal_url||('https://portal.assessor.lacounty.gov/parceldetail/'+AIN),'assessor record','Open the LA County Assessor public record')}`)
+kv('Address', esc(p.address))
- +kv('City', dfLink('deal_city',(deal&&deal.deal_city)||p.city, p.city))
+ +kv('City', esc(((deal&&deal.deal_city)||p.city)||'')) /* deals-flow.json exposes no deal_city filter key → render city as TEXT, no silent dead-end drill (TK-10482 contrarian BLOCKER fix) */
+kv('ZIP', esc(p.zip))
+kv('Use / type', dfLink('use', (deal&&deal.use)||p.use_desc||p.use_type, p.use_desc||p.use_type||(deal&&deal.use)))
+kv('Year built', dfLink('year_built', p.year_built, p.year_built))
← 9cde5e2 crcp: full property→parcel/deal DETAIL drill-down (TK-10482)
·
back to Commercialrealestate
·
just-listed: harden esc() against attribute-breakout XSS + f 6926884 →