← back to Apartmentwallpaper
Ideas rail: route through safeImg()+escAttr() (XSS hygiene parity with grid); clarify safeImg comment (redact middleware rewrites images in all modes, not just PG-admin)
9c0a8ae5cadf66d6ecbfea91dbb988c67069bc74 · 2026-06-16 18:22:06 -0700 · Steve Abrams
Files touched
Diff
commit 9c0a8ae5cadf66d6ecbfea91dbb988c67069bc74
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Tue Jun 16 18:22:06 2026 -0700
Ideas rail: route through safeImg()+escAttr() (XSS hygiene parity with grid); clarify safeImg comment (redact middleware rewrites images in all modes, not just PG-admin)
---
public/index.html | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/public/index.html b/public/index.html
index 2079fd3..99a6528 100644
--- a/public/index.html
+++ b/public/index.html
@@ -537,7 +537,8 @@ const LABELS = {"self-adhesive":"Self adhesive"};
function escAttr(s) { return String(s == null ? '' : s).replace(/[&<>"']/g, c => ({ '&':'&','<':'<','>':'>','"':'"',"'":''' }[c])); }
// Image-URL allowlist (defends against XSS via crafted products.json):
// • DW Shopify CDN + designerwallcoverings.com (static-mode absolute URLs)
-// • same-origin /img/<hash> proxy paths (PG-admin mode rewrites images to these)
+// • same-origin /img/<hash> proxy paths (the api-vendor-redact middleware rewrites
+// all product images to these in every mode — static AND PG-admin)
function safeImg(u) { return /^https:\/\/(?:cdn\.shopify\.com|designerwallcoverings\.com)\//.test(u || '') || /^\/img\/[A-Za-z0-9._-]+$/.test(u || '') ? u : '/hero-bg.jpg'; }
function cardHTML(p) {
const eager = state.page === 1;
@@ -1116,11 +1117,11 @@ loadGridPage();
// Curated = deterministic offset slice (every 5th item starting at idx 3) for variety
const curated = items.filter((_, i) => i % 5 === 3).slice(0, 12);
function card(p) {
- const url = (p.image_url || '').replace(/(_\d+x\d*)(\.(jpg|jpeg|png|webp|gif))(\?|$)/i, '$2$4');
+ const url = safeImg((p.image_url || '').replace(/(_\d+x\d*)(\.(jpg|jpeg|png|webp|gif))(\?|$)/i, '$2$4'));
return '<a class="rail-card" href="/sample/' + encodeURIComponent(p.handle_display || p.handle || p.sku) + '">' +
- '<img src="' + url + '" alt="' + (p.title || '').replace(/"/g, '"') + '" loading="lazy">' +
- '<div class="rc-title">' + ((p.title || '').split('|')[0] || '').trim() + '</div>' +
- '<div class="rc-meta">' + (p.vendor || '') + '</div>' +
+ '<img src="' + escAttr(url) + '" alt="' + escAttr(p.title) + '" loading="lazy">' +
+ '<div class="rc-title">' + escAttr(((p.title || '').split('|')[0] || '').trim()) + '</div>' +
+ '<div class="rc-meta">' + escAttr(p.vendor) + '</div>' +
'</a>';
}
const r1 = document.getElementById('railNewest');
← 395eb10 Fix repeated hero image: allow same-origin /img/<hash> proxy
·
back to Apartmentwallpaper
·
Pre-warm /img token map at boot (close cold-start 404 window f2ab8c8 →