Gatilab Products

Release Notes

Improvements, fixes, and the details behind each release.

Core Forms

Build forms, collect submissions, and connect the actions your site needs.

View Product
← All Core Forms Releases
Beta

Core Forms 4.2.0-beta

Pre-release. Distribution channel for testers before 4.2.0 GA.

WhatsApp, three ways

  • WhatsApp Cloud API action. Meta Graph API. Template + free-form modes. Global creds (Settings → WhatsApp Cloud API) with per-action override. Includes a Test connection button that pings /v21.0/{phone_number_id} and reports verified business name + quality rating.
  • Twilio WhatsApp action. Reuses your existing Twilio SID/token; posts to the whatsapp: channel. Optional Content Template SID for business-initiated outreach.
  • Click-to-WhatsApp redirect. Generates a wa.me deep link with the submission pre-filled into the chat draft and injects it as the post-submit redirect.

The cf_form_redirect_url filter now fires on every successful submission (not just when a per-form Redirect URL is set) and receives the Submission as a 4th argument. Existing 3-arg handlers keep working.

Contact Form 7 → Core Forms migration

New page at Core Forms → Import (CF7). Scans every wpcf7_contact_form post and converts: - Shortcode markup → plain HTML (text, email, tel, url, number, date, hidden, textarea, select, checkbox, radio, acceptance, file, submit, recaptcha) - CF7 mail template → Core Forms Send Email action - _messages meta → cf_message_* post meta (so your custom success/validation/spam copy carries over)

Each row in the importer table has a "Preview converted HTML" disclosure so you can sanity-check before committing. CF7 stays installed and untouched — run both side-by-side during cutover. Flamingo submission import is out of scope.

Operational polish

  • WhatsApp activity in Email Logs. Both Cloud API and Twilio sends log through the existing cf_email_logs table. The Type column labels them; Resend is suppressed for non-email rows (which would otherwise try to wp_mail a phone number).
  • cf_log_email() now switches between sanitize_email and sanitize_text_field based on action type.

Security hardening (14 audit findings fixed)

  • CSRF default flipped on. New installs get enable_nonce=1. Existing installs are preserved at 0 via a 4.2.0 migration that writes the prior value explicitly into stored settings. Sites that have always cached aggressively can keep nonces off; sites that haven't been should turn them on.
  • Submission mass-assignment closed. Forms::process() intersects POST keys with field names declared in the form markup. Filterable via cf_allowed_field_names.
  • Headless API key is header-only. The ?cf_key= query-string fallback is gone (leaked into logs/history/Referer).
  • Headless CORS allowlist. New textarea at Settings → Headless → Allowed origins. Empty preserves 4.1 behavior with an admin warning.
  • Workflow /actions/test requires manage_options. No longer a wp_mail / wp_remote / paid-SMS-anywhere primitive in editor-level hands.
  • Webhook SSRF guard. New cf_is_safe_outbound_url() helper rejects loopback, RFC1918, link-local, IPv6 unique-local, and non-HTTP schemes. Webhook auth header name/value also strip CR/LF.
  • Email header CRLF injection closed. New cf_esc_email_header() sanitizer replaces strip_tags on every header substitution in Email, Emailit, and Autoresponder actions.
  • Custom CSS </style> escape closed. The previous regex pattern didn't consume the closing >. Now strips every < from custom CSS at both save and render time.
  • process_save_form gains inline cap+nonce check (defense in depth — matches the existing guard on process_create_form).
  • Two ghost wp_ajax_* handlers removed (registered methods that didn't exist; calling them returned a fatal).
  • Polls trust REMOTE_ADDR only. HTTP_CLIENT_IP and HTTP_X_FORWARDED_FOR no longer honored by default. Opt back in via cf_poll_trust_forwarded_for for sites behind a trusted reverse proxy.
  • Draft saves rate-limited to 30 new drafts per IP+form per minute (filterable via cf_draft_save_rate_limit).
  • File upload blocklist extended with html, htm, xhtml, xml, xsl, xslt. Closes a stored-XSS path where nginx (which ignores the uploads .htaccess) served uploaded HTML as text/html on the WP origin.
  • Honeypot returns opaque success on missing/populated field instead of WordPress's silent 0 response — bots can no longer distinguish "rejected" from "accepted but never processed."

Upgrade notes

  • Backwards-compatible: the CSRF migration only writes enable_nonce=0 into installs that had no explicit value before, so existing form-bearing cached pages keep working.
  • Behavior changes worth knowing:
  • Webhooks pointing at 127.0.0.1, 192.168.*, 10.*, etc. will now fail. Local dev environments needing the loopback can override via the cf_is_safe_outbound_url filter.
  • Forms with JS-injected fields not present in the static markup will have those keys dropped. Use the cf_allowed_field_names filter to opt them in.
  • Editor-role users with edit_forms can no longer test arbitrary actions via the REST endpoint — they can still test by saving the action first.

Full commit: b37bfae