[object Object]

← back to Stars of Design

Static-bak guard returns plain text, not EJS template

8fc1daa177f2442398081cd08665b480bd28cb3c · 2026-05-19 15:20:35 -0700 · Steve Abrams

The previous version of this guard tried to render public/404.ejs, which
in turn includes partials/head.ejs that depends on res.locals.meta_desc.
That local is wired inside the publicRoutes router-level middleware —
later in the stack than this guard runs — so a request for a .bak/.pre-
path threw "meta_desc is not defined" and surfaced a 500 instead of a
404, defeating the point.

Plain-text response sidesteps the template chain entirely. Verified with
a smoke run: /test.html.bak / /test.bak / /something.pre-refactor.html
all return 404, regular routes still 200.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

Files touched

Diff

commit 8fc1daa177f2442398081cd08665b480bd28cb3c
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Tue May 19 15:20:35 2026 -0700

    Static-bak guard returns plain text, not EJS template
    
    The previous version of this guard tried to render public/404.ejs, which
    in turn includes partials/head.ejs that depends on res.locals.meta_desc.
    That local is wired inside the publicRoutes router-level middleware —
    later in the stack than this guard runs — so a request for a .bak/.pre-
    path threw "meta_desc is not defined" and surfaced a 500 instead of a
    404, defeating the point.
    
    Plain-text response sidesteps the template chain entirely. Verified with
    a smoke run: /test.html.bak / /test.bak / /something.pre-refactor.html
    all return 404, regular routes still 200.
    
    Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---
 server.js | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/server.js b/server.js
index bf1babc..ecc3d51 100644
--- a/server.js
+++ b/server.js
@@ -69,11 +69,14 @@ app.use(cookieParser());
 // Static-bak guard — refuse to serve any URL path that looks like a snapshot
 // or rollback artifact (foo.html.bak, foo.pre-refactor.js, etc.) even if
 // someone accidentally leaves one in public/. Pair with the .gitignore rules
-// for *.bak / *.bak.* / *.pre-*. Returns 404 (not 403) so an attacker can't
-// confirm a snapshot exists by path-probing.
+// for *.bak / *.bak.* / *.pre-*. Returns plain-text 404 (not 403) so an
+// attacker can't confirm a snapshot exists by path-probing, and bypasses
+// the EJS 404 template since the meta-locals it expects aren't wired yet
+// at this point in the middleware stack.
 app.use((req, res, next) => {
   if (/\.bak(?:\.|$)|\.pre-/.test(req.path)) {
-    return res.status(404).render('public/404', { title: 'Not found — Stars of Design' });
+    res.setHeader('Cache-Control', 'no-store');
+    return res.status(404).type('text/plain').send('Not found');
   }
   next();
 });

← e2ee6aa Guard against serving .bak / .pre- snapshot artifacts from p  ·  back to Stars of Design  ·  Add per-site favicon (kills /favicon.ico 404) 06be86b →