Skip to content

Security ​

submito is careful about how it puts text on the page. It does not replace server-side validation, authorization, CSRF protection or rate limiting.

Messages are text, never HTML ​

Every message from validation or from your server is written with textContent: inline errors, the built-in dialog and the dialog list. With SweetAlert2, messages are passed as text, and an html key in the swal option is dropped.

If you use callback, keep it that way: never put response.message or response.data into innerHTML.

Client validation is not a boundary ​

Required fields, formats, the math captcha and phone checks all run in the browser and can be bypassed. Your endpoint must:

  • validate every field again
  • check authorization
  • rate-limit and log abuse
  • verify captcha tokens with the provider

Captchas ​

ProtectionServer check
Math captchaWeak: the answer is in the DOMOptional sum check
reCAPTCHA v3Score-based bot detectionRequired: siteverify with your secret key
TurnstileCloudflare challengeRequired: siteverify with your secret key

Tokens prove nothing until your server verifies them. Keep secret keys in environment variables, never in front-end code or the repository.

CSRF ​

submito sends cookies for same-origin requests (the fetch default), so session-based backends need CSRF protection. Either keep the framework's hidden field in the form:

html
<form id="contact" action="/contact" method="post">
  <input type="hidden" name="_token" value="{{ csrf_token() }}" />
  …
</form>

or send the token as a header:

js
submito.newForm({
  form: '#contact',
  headers: () => ({
    'X-CSRF-Token': document.querySelector('meta[name="csrf-token"]').content,
  }),
});

Validate it on every state-changing request.

File uploads ​

The accept attribute is only a hint. Check type, size and content on the server, and store uploads outside the web root.

Third-party scripts ​

Optional integrations are globals you load yourself (intlTelInput, Swal, grecaptcha, turnstile). submito itself fetches one script, intl-tel-input's utils from jsDelivr, and only when you enable iti without providing loadUtils. Load third-party scripts from sources you trust, pin their versions, and use integrity attributes where the CDN supports them.

Content Security Policy ​

With a strict CSP, allow the origins of the integrations you use (for example https://challenges.cloudflare.com for Turnstile, https://www.google.com and https://www.gstatic.com for reCAPTCHA, https://cdn.jsdelivr.net for intl-tel-input utils). The built-in dialog injects one <style> element; see Response UI if inline styles are blocked.

Released under the MIT License.