exempt captcha keys from unknown_fields validation
This commit is contained in:
@@ -34,6 +34,15 @@ export type FormValidationResult =
|
||||
/** Field block types that don't carry a submittable value. */
|
||||
const NON_DATA_BLOCKS = new Set(['message'])
|
||||
|
||||
/**
|
||||
* Keys injected by the captcha widget itself, not by the form definition.
|
||||
* Cloudflare Turnstile adds a hidden <input name="cf-turnstile-response"> after
|
||||
* a successful challenge; reCAPTCHA adds 'g-recaptcha-response'. Since the
|
||||
* plugin drives Turnstile end-to-end, these are legitimate artifacts — they
|
||||
* must not count as "unknown fields" and trip the anti-tampering check.
|
||||
*/
|
||||
const CAPTCHA_KEYS = new Set(['cf-turnstile-response', 'g-recaptcha-response'])
|
||||
|
||||
/** Hard ceiling on a single field's length, independent of the form config. */
|
||||
const MAX_FIELD_LENGTH = 5000
|
||||
|
||||
@@ -95,8 +104,10 @@ export async function validateSubmission(
|
||||
}
|
||||
|
||||
// Reject outright if the payload carried keys the form doesn't define — a
|
||||
// sign the request wasn't produced by the rendered form.
|
||||
const unknownKeys = Object.keys(data).filter((k) => !known.has(k))
|
||||
// sign the request wasn't produced by the rendered form. Captcha keys are
|
||||
// exempt: the widget injects them into the rendered form, so they're expected,
|
||||
// not tampering.
|
||||
const unknownKeys = Object.keys(data).filter((k) => !known.has(k) && !CAPTCHA_KEYS.has(k))
|
||||
if (unknownKeys.length > 0) {
|
||||
return { kind: 'unknown_fields', ok: false, reason: 'invalid' }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user