removed duplicate reference of allowed_origin in env (bruh moment)
All checks were successful
Deploy Jody's App / build-and-deploy (push) Successful in 33s

This commit is contained in:
2026-02-18 22:23:08 -06:00
parent 5f0d87ce2a
commit 30e6c23bac
3 changed files with 33 additions and 4 deletions

View File

@@ -1,6 +1,6 @@
NODE_ENV=production NODE_ENV=production
PORT=8787 PORT=8787
CONTACT_ALLOWED_ORIGIN=https://jodyholt.com CONTACT_ALLOWED_ORIGIN=https://www.jodyholt.com
TURNSTILE_SECRET_KEY=0x4AAAAAACfQyRwRzwsEMIfVtCSkjz7__Yc TURNSTILE_SECRET_KEY=0x4AAAAAACfQyRwRzwsEMIfVtCSkjz7__Yc
TURNSTILE_EXPECTED_HOSTNAME=jodyholt.com TURNSTILE_EXPECTED_HOSTNAME=jodyholt.com
TURNSTILE_EXPECTED_ACTION=contact_form TURNSTILE_EXPECTED_ACTION=contact_form
@@ -18,4 +18,3 @@ RATE_LIMIT_WINDOW_MS=600000
RATE_LIMIT_MAX=5 RATE_LIMIT_MAX=5
HONEYPOT_FIELD=website HONEYPOT_FIELD=website
MIN_SUBMIT_TIME_MS=3000 MIN_SUBMIT_TIME_MS=3000
CONTACT_ALLOWED_ORIGIN=https://www.jodyholt.com

View File

@@ -16,6 +16,18 @@ type ApiErrorResponse = {
const app = express(); const app = express();
app.set("trust proxy", 1); app.set("trust proxy", 1);
const normalizeOrigin = (value: string): string =>
value
.trim()
.replace(/^['"]|['"]$/g, "")
.replace(/\/+$/g, "")
.toLowerCase();
const allowedOrigins = config.CONTACT_ALLOWED_ORIGIN
.split(",")
.map(normalizeOrigin)
.filter((value, index, all) => value.length > 0 && all.indexOf(value) === index);
app.use( app.use(
pinoHttp({ pinoHttp({
level: config.NODE_ENV === "production" ? "info" : "debug", level: config.NODE_ENV === "production" ? "info" : "debug",
@@ -30,7 +42,13 @@ app.use(helmet());
app.use( app.use(
cors({ cors({
origin(origin, callback) { origin(origin, callback) {
if (!origin || origin === config.CONTACT_ALLOWED_ORIGIN) { if (!origin) {
callback(null, true);
return;
}
const normalizedOrigin = normalizeOrigin(origin);
if (allowedOrigins.includes(normalizedOrigin)) {
callback(null, true); callback(null, true);
return; return;
} }

View File

@@ -7,6 +7,18 @@ type TurnstileVerifyResponse = {
"error-codes"?: string[]; "error-codes"?: string[];
}; };
const normalizeHostname = (value: string): string =>
value
.trim()
.replace(/^['"]|['"]$/g, "")
.replace(/\.+$/g, "")
.toLowerCase();
const expectedHostnames = config.TURNSTILE_EXPECTED_HOSTNAME
.split(",")
.map(normalizeHostname)
.filter((value, index, all) => value.length > 0 && all.indexOf(value) === index);
export async function verifyTurnstileToken( export async function verifyTurnstileToken(
token: string, token: string,
remoteIp?: string, remoteIp?: string,
@@ -36,7 +48,7 @@ export async function verifyTurnstileToken(
return { ok: false, reason: codes }; return { ok: false, reason: codes };
} }
if (result.hostname !== config.TURNSTILE_EXPECTED_HOSTNAME) { if (!result.hostname || !expectedHostnames.includes(normalizeHostname(result.hostname))) {
return { ok: false, reason: "hostname_mismatch" }; return { ok: false, reason: "hostname_mismatch" };
} }