← back to Sample Followup Sweep
Require visible owned compliance content
297d26af095fcdfc7da7cc14a0cb0552d5a79185 · 2026-08-28 14:44:09 -0700 · Steve Abrams
Files touched
M README.mdM lib/pre-send-gate.jsM test/pre-send-gate.test.jsM verification/e2e-proof.json
Diff
commit 297d26af095fcdfc7da7cc14a0cb0552d5a79185
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Fri Aug 28 14:44:09 2026 -0700
Require visible owned compliance content
---
README.md | 4 ++++
lib/pre-send-gate.js | 44 ++++++++++++++++++++++++++++++++++----------
test/pre-send-gate.test.js | 21 +++++++++++++++++++++
verification/e2e-proof.json | 8 ++++++--
4 files changed, 65 insertions(+), 12 deletions(-)
diff --git a/README.md b/README.md
index 94b7de1..a8bc347 100644
--- a/README.md
+++ b/README.md
@@ -25,6 +25,10 @@ blocks unless the sender resolves to `info@designerwallcoverings.com`, the body
contains DW's physical postal address and a working opt-out link, and the subject
is present without a misleading `Re:`/`Fwd:` prefix. A block performs no network
request and returns `PRE_SEND_COMPLIANCE_BLOCKED` (HTTP 422 in the console API).
+Address text and opt-out anchors must be visibly rendered; comments and non-rendered
+elements (`script`, `style`, `template`, `noscript`, hidden blocks) never count.
+The current approved opt-out is the `info@designerwallcoverings.com` mailto link.
+HTTPS opt-outs fail closed until a canonical DW-owned endpoint is explicitly registered.
## The one FileMaker dependency (for hands-free phases 1 & 6)
diff --git a/lib/pre-send-gate.js b/lib/pre-send-gate.js
index 9dda896..8027178 100644
--- a/lib/pre-send-gate.js
+++ b/lib/pre-send-gate.js
@@ -3,24 +3,48 @@
const REQUIRED_FROM = 'info@designerwallcoverings.com';
const ADDRESS_PATTERN = /15442\s+Ventura\s+Blvd(?:\.|\s)*(?:#|Suite)?\s*102[\s\S]*Sherman\s+Oaks,?\s*CA\s+91403/i;
const MISLEADING_SUBJECT_PATTERN = /\b(?:re|fw|fwd)\s*:/i;
+const NON_RENDERED_ELEMENTS = 'script|style|template|noscript|head|svg|canvas';
-function stripHtmlComments(value) {
- return String(value || '').replace(/<!--[\s\S]*?-->/g, '');
+function decodeHtmlEntities(value) {
+ return String(value || '')
+ .replace(/ | | /gi, ' ')
+ .replace(/&/gi, '&')
+ .replace(/</gi, '<')
+ .replace(/>/gi, '>')
+ .replace(/"/gi, '"')
+ .replace(/'|'/gi, "'")
+ .replace(/&#(\d+);/g, (_, code) => String.fromCodePoint(Number(code)))
+ .replace(/&#x([0-9a-f]+);/gi, (_, code) => String.fromCodePoint(parseInt(code, 16)));
+}
+
+function sanitizeRenderedHtml(value) {
+ let html = String(value || '').replace(/<!--[\s\S]*?-->/g, '');
+ html = html.replace(new RegExp(`<(${NON_RENDERED_ELEMENTS})\\b[^>]*>[\\s\\S]*?<\\/\\1\\s*>`, 'gi'), '');
+ const hiddenBlock = /<([a-z][\w:-]*)\b(?=[^>]*(?:\bhidden(?:\s*=\s*(?:["'][^"']*["']|[^\s>]+))?|\baria-hidden\s*=\s*(["'])?true\2|\bstyle\s*=\s*(["'])[^"']*(?:display\s*:\s*none|visibility\s*:\s*hidden)[^"']*\3))[^>]*>[\s\S]*?<\/\1\s*>/gi;
+ let previous;
+ do { previous = html; html = html.replace(hiddenBlock, ''); } while (html !== previous);
+ return html;
+}
+
+function visibleTextFromHtml(body) {
+ const rendered = sanitizeRenderedHtml(body)
+ .replace(/<(?:br|\/p|\/div|\/li|\/tr|\/h[1-6])\b[^>]*>/gi, ' ')
+ .replace(/<[^>]*>/g, ' ');
+ return decodeHtmlEntities(rendered).replace(/\s+/g, ' ').trim();
}
function hasWorkingOptOutLink(body) {
- const visible = stripHtmlComments(body);
- const hrefs = [...visible.matchAll(/<a\b[^>]*\bhref\s*=\s*(["'])(.*?)\1[^>]*>/gi)].map((match) => match[2].trim());
+ const rendered = sanitizeRenderedHtml(body);
+ const hrefs = [...rendered.matchAll(/<a\b[^>]*\bhref\s*=\s*(["'])(.*?)\1[^>]*>/gi)].map((match) => decodeHtmlEntities(match[2].trim()));
return hrefs.some((href) => {
try {
const url = new URL(href);
const optOutSignal = `${url.pathname} ${url.search} ${url.hash}`;
if (!/(?:unsubscribe|opt[-_ ]?out)/i.test(optOutSignal)) return false;
if (url.protocol === 'mailto:') return url.pathname.toLowerCase() === REQUIRED_FROM;
- if (url.protocol !== 'https:') return false;
- const host = url.hostname.toLowerCase();
- if (!host.includes('.') || host === 'invalid.example' || host.endsWith('.invalid') || host.endsWith('.example') || host.endsWith('.test') || host === 'localhost') return false;
- return true;
+ // No canonical DW-hosted unsubscribe endpoint is registered yet. Fail closed
+ // instead of treating an attacker-controlled HTTPS URL as a working opt-out.
+ return false;
} catch {
return false;
}
@@ -32,7 +56,7 @@ function assertPreSendCompliance({ from, subject, body }) {
if (String(from || '').trim().toLowerCase() !== REQUIRED_FROM) errors.push(`From must be ${REQUIRED_FROM}`);
if (!String(subject || '').trim()) errors.push('Subject is required');
if (MISLEADING_SUBJECT_PATTERN.test(String(subject || ''))) errors.push('Subject must not imply a reply or forward');
- if (!ADDRESS_PATTERN.test(String(body || ''))) errors.push('Body must include the DW physical postal address');
+ if (!ADDRESS_PATTERN.test(visibleTextFromHtml(body))) errors.push('Body must include the DW physical postal address in visible content');
if (!hasWorkingOptOutLink(body)) errors.push('Body must include a working unsubscribe or opt-out link');
if (errors.length) {
const error = new Error(`PRE-SEND COMPLIANCE GATE BLOCKED: ${errors.join('; ')}`);
@@ -43,4 +67,4 @@ function assertPreSendCompliance({ from, subject, body }) {
return true;
}
-module.exports = { assertPreSendCompliance, hasWorkingOptOutLink, REQUIRED_FROM };
+module.exports = { assertPreSendCompliance, hasWorkingOptOutLink, sanitizeRenderedHtml, visibleTextFromHtml, REQUIRED_FROM };
diff --git a/test/pre-send-gate.test.js b/test/pre-send-gate.test.js
index 4921f82..16922bb 100644
--- a/test/pre-send-gate.test.js
+++ b/test/pre-send-gate.test.js
@@ -36,4 +36,25 @@ for (const fakeLink of [
assert.throws(() => assertPreSendCompliance({ from: REQUIRED_FROM, subject: compliant.subject, body: bodyWithoutLink + fakeLink }), { code: 'PRE_SEND_COMPLIANCE_BLOCKED' });
}
+const bodyWithoutAddress = compliant.html
+ .replace(/Designer Wallcoverings · 15442 Ventura Blvd\. #102 · Sherman Oaks, CA 91403<br>/, '')
+ .replace(/Designer Wallcoverings<br>\s*15442 Ventura Blvd\. #102<br>\s*Sherman Oaks, CA 91403<br>/, '');
+for (const hiddenAddress of [
+ '<div hidden>15442 Ventura Blvd. #102, Sherman Oaks, CA 91403</div>',
+ '<div style="display:none">15442 Ventura Blvd. #102, Sherman Oaks, CA 91403</div>',
+ '<script>const address = "15442 Ventura Blvd. #102, Sherman Oaks, CA 91403"</script>',
+ '<template>15442 Ventura Blvd. #102, Sherman Oaks, CA 91403</template>',
+]) {
+ assert.throws(() => assertPreSendCompliance({ from: REQUIRED_FROM, subject: compliant.subject, body: bodyWithoutAddress + hiddenAddress }), { code: 'PRE_SEND_COMPLIANCE_BLOCKED' });
+}
+
+const scriptOnly = bodyWithoutLink + '<script>document.write(`<a href="mailto:info@designerwallcoverings.com?subject=Unsubscribe">unsubscribe</a>`)</script>';
+assert.throws(() => assertPreSendCompliance({ from: REQUIRED_FROM, subject: compliant.subject, body: scriptOnly }), { code: 'PRE_SEND_COMPLIANCE_BLOCKED' });
+
+const attackerOwned = bodyWithoutLink + '<a href="https://attacker.example.org/unsubscribe">unsubscribe</a>';
+assert.throws(() => assertPreSendCompliance({ from: REQUIRED_FROM, subject: compliant.subject, body: attackerOwned }), { code: 'PRE_SEND_COMPLIANCE_BLOCKED' });
+
+const reconciledFooter = `<div><p>Ship to:<br>Designer Wallcoverings<br>15442 Ventura Blvd. #102<br>Sherman Oaks, CA 91403<br>1-888-373-4564</p><p>Thank you!<br>Showroom Manager</p><p>Designer Wallcoverings · 15442 Ventura Blvd. #102 · Sherman Oaks, CA 91403<br>To stop receiving sample follow-up emails, <a href="mailto:info@designerwallcoverings.com?subject=Unsubscribe%20from%20sample%20follow-ups">unsubscribe here</a>.</p></div>`;
+assert.equal(assertPreSendCompliance({ from: REQUIRED_FROM, subject: 'Sample Follow-Up — Outstanding Memos — Designer Wallcoverings', body: reconciledFooter }), true);
+
console.log('pre-send compliance gate: PASS');
diff --git a/verification/e2e-proof.json b/verification/e2e-proof.json
index b01e050..242050a 100644
--- a/verification/e2e-proof.json
+++ b/verification/e2e-proof.json
@@ -1,5 +1,5 @@
{
- "intent": "Centralize fail-closed compliance enforcement for all sendable George transports and Gmail draft artifacts",
+ "intent": "Centralize fail-closed compliance enforcement and require visibly rendered, DW-owned compliance content",
"risk_tier": "R3",
"environment": "local repository only; injected HTTP spy; no George/Gmail/FileMaker/production network calls",
"ticket": "TK-10940-centralize-sample-follow-up-pre-send-com",
@@ -13,7 +13,7 @@
{
"boundary": "compliance parser",
"verdict": "PASS",
- "evidence": "test/pre-send-gate.test.js rejects HTML comments, plain-text mailto tokens, and https://invalid.example/unsubscribe while accepting lib/compose.js output"
+ "evidence": "test/pre-send-gate.test.js rejects comments, script/template/hidden address text, script-only links, plain-text mailto tokens, invalid.example, and attacker.example.org while accepting lib/compose.js and reconciled-footer output"
},
{
"boundary": "George /api/send and /api/drafts",
@@ -44,6 +44,10 @@
"opt-out anchor hidden in HTML comment",
"plain-text mailto token",
"reserved invalid.example unsubscribe URL",
+ "attacker-owned HTTPS unsubscribe URL",
+ "postal address hidden with hidden/display:none",
+ "postal address present only in script/template",
+ "opt-out link present only in script",
"blocked transport makes zero requests"
],
"cleanup": "No external or persistent test state created; repository verification artifact intentionally retained",
← 984ab8e Centralize sample follow-up compliance enforcement
·
back to Sample Followup Sweep
·
Record cycle 3 compliance proof identity a3c2bbb →