Files
PersonalBlog/js/newsletter-config.js
T
implementer 86aa3afbbf
CI / Run tests (pull_request) Successful in 15s
CI / Secret scan (gitleaks) (pull_request) Failing after 12s
refactor: newsletter signup posts no credential (SEC-14-R1 option a)
Rework PR #15 per security review SEC-14-R1: the client no longer carries
an API token. js/newsletter-config.js ships only the non-secret endpoint,
enforced https-only at config load time via validateEndpoint() (mirroring
the protocol allowlist in js/reading-list.js); js/newsletter.js POSTs
email-only with no Authorization header. Failure paths keep the single
user-safe message that never leaks token, endpoint, status, or raw body;
success still shows the confirmation. CI gains a gitleaks step that fails
on any secret hit; README documents the server-side token, the residual
signup-abuse risk, and the authoritative server-side validation follow-up.
2026-08-26 11:27:11 +00:00

45 lines
1.4 KiB
JavaScript

/**
* Newsletter signup configuration.
*
* Only the non-secret serverless endpoint URL lives here. The serverless
* function authenticates with an API token it reads from platform env/secrets
* at deploy time — never from this module and never from any client-served
* asset. Do NOT add a token or any other secret to this file: the client must
* never carry a credential, and anything committed here is public.
*/
/** True when the value is an absolute URL whose protocol is https:. */
export function isHttpsUrl(value) {
try {
return new URL(String(value)).protocol === "https:";
} catch {
return false;
}
}
/**
* Enforce the https-only rule on a configured endpoint, mirroring the protocol
* allowlist pattern in js/reading-list.js (tightened to https). Throws when the
* endpoint would silently downgrade submissions to plaintext.
*
* @param {string} endpoint
* @returns {true}
*/
export function validateEndpoint(endpoint) {
if (!isHttpsUrl(endpoint)) {
throw new Error("NEWSLETTER_ENDPOINT must be an https:// URL");
}
return true;
}
/**
* The serverless endpoint the signup form POSTs to.
*
* https-only is asserted here at config load time (and covered by tests), so a
* deployer pointing this at an http:// URL fails fast instead of shipping a
* downgraded endpoint.
*/
export const NEWSLETTER_ENDPOINT = "https://example.com/api/newsletter-subscribers";
validateEndpoint(NEWSLETTER_ENDPOINT);