diff --git a/skill/scripts/serve-question.mjs b/skill/scripts/serve-question.mjs
index be5965f20..e08052c48 100644
--- a/skill/scripts/serve-question.mjs
+++ b/skill/scripts/serve-question.mjs
@@ -1568,12 +1568,16 @@ ${buildPath?.toggle ? `
`;
}
+// Browsers omit the :80 suffix on the default HTTP port, so a server on
+// --port 80 sees bare loopback hosts and origins.
function allowedHost(host, port) {
- return host === `127.0.0.1:${port}` || host === `localhost:${port}`;
+ if (host === `127.0.0.1:${port}` || host === `localhost:${port}`) return true;
+ return port === 80 && (host === '127.0.0.1' || host === 'localhost');
}
function allowedOrigin(origin, port) {
- return origin === `http://127.0.0.1:${port}` || origin === `http://localhost:${port}`;
+ if (origin === `http://127.0.0.1:${port}` || origin === `http://localhost:${port}`) return true;
+ return port === 80 && (origin === 'http://127.0.0.1' || origin === 'http://localhost');
}
function rejectDetachedPost(req, res, url, port) {
diff --git a/tests/serve-question.test.mjs b/tests/serve-question.test.mjs
index bd5194d99..02f3daa1a 100644
--- a/tests/serve-question.test.mjs
+++ b/tests/serve-question.test.mjs
@@ -185,6 +185,14 @@ describe('serve-question', () => {
});
assert.equal(spoofedHostGet.status, 403);
+ // The bare-host allowance exists only for --port 80, where browsers omit
+ // the suffix; on any other port a portless Host stays rejected.
+ const bareHostGet = await rawRequest(port, {
+ path: '/',
+ headers: { Host: '127.0.0.1' },
+ });
+ assert.equal(bareHostGet.status, 403);
+
const slashSlash = await rawRequest(port, {
path: '//',
headers: { Host: goodHost },