← back to Dw Photo Capture
Add bounded public /marketing/ static route (images only, traversal-safe) + color-coordinate demo GIF for email hosting
ba0e274160d6095578e16e3783388ecfe3a2e7d2 · 2026-07-29 07:37:50 -0700 · Steve Abrams
Files touched
A public-marketing/color-coordinate-wm.gifM server.js
Diff
commit ba0e274160d6095578e16e3783388ecfe3a2e7d2
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Wed Jul 29 07:37:50 2026 -0700
Add bounded public /marketing/ static route (images only, traversal-safe) + color-coordinate demo GIF for email hosting
---
public-marketing/color-coordinate-wm.gif | Bin 0 -> 1197618 bytes
server.js | 30 +++++++++++++++++++++++++++++-
2 files changed, 29 insertions(+), 1 deletion(-)
diff --git a/public-marketing/color-coordinate-wm.gif b/public-marketing/color-coordinate-wm.gif
new file mode 100644
index 0000000..0a5a24c
Binary files /dev/null and b/public-marketing/color-coordinate-wm.gif differ
diff --git a/server.js b/server.js
index 06839cd..4c68f5e 100644
--- a/server.js
+++ b/server.js
@@ -918,7 +918,7 @@ const appHandler = (req, res) => {
// public (no-auth) paths: health + the home-screen-install assets iOS fetches without creds
const PUBLIC = ['/healthz', '/icon-180.png', '/icon-512.png', '/apple-touch-icon.png', '/manifest.webmanifest', '/apps/similar', '/apps/color-index', '/apps/color-widen', '/apps/color-dots'];
const _p = req.url.split('?')[0];
- if (!PUBLIC.includes(_p) && !checkAuth(req)) {
+ if (!PUBLIC.includes(_p) && !_p.startsWith('/marketing/') && !checkAuth(req)) {
res.writeHead(401, { 'WWW-Authenticate': 'Basic realm="DW Photo Capture"' });
return res.end('Auth required');
}
@@ -926,6 +926,34 @@ const appHandler = (req, res) => {
if (u.pathname === '/healthz') return send(res, 200, { ok: true });
+ // ── Public marketing assets (email images) — TIGHTLY bounded static serve ──
+ // No auth (allowed in the PUBLIC gate above). NOT a generic file server:
+ // · Fixed dir public-marketing/ — never user-controlled.
+ // · Basename-only + strict regex allowlist (images only); rejects any '..' / slash.
+ // · Resolved path must stay inside the dir (path-traversal guard).
+ if (_p.startsWith('/marketing/')) {
+ const name = _p.slice('/marketing/'.length);
+ if (name.includes('/') || name.includes('..') ||
+ !/^[A-Za-z0-9._-]+\.(gif|png|jpe?g|webp)$/.test(name)) {
+ return send(res, 404, { err: 'not found' });
+ }
+ const MDIR = path.join(ROOT, 'public-marketing');
+ const fp = path.join(MDIR, name);
+ if (!fp.startsWith(MDIR + path.sep)) return send(res, 404, { err: 'not found' });
+ return fs.readFile(fp, (e, buf) => {
+ if (e) return send(res, 404, { err: 'not found' });
+ const ext = name.split('.').pop().toLowerCase();
+ const ct = { gif: 'image/gif', png: 'image/png', jpg: 'image/jpeg',
+ jpeg: 'image/jpeg', webp: 'image/webp' }[ext] || 'application/octet-stream';
+ res.writeHead(200, {
+ 'Content-Type': ct,
+ 'Cache-Control': 'public, max-age=604800',
+ 'Access-Control-Allow-Origin': '*'
+ });
+ res.end(buf);
+ });
+ }
+
// ── PDP CLIP "More like this" proxy (GATED-STEP-1, shipped) ─────────────────
// Public (no basic-auth) but TIGHTLY bounded: NOT a generic proxy.
// · SSRF guard: fixed upstream host+path 127.0.0.1:9914/similar — never user-controlled.
← d204283 auto-save: 2026-07-29T04:35:46 (1 files) — data/color-dots.j
·
back to Dw Photo Capture
·
chore: v1.6.0 — public /marketing static route for email ass 3116235 →