- Verify Meta WhatsApp webhooks with optional app secrets while
preserving soft compatibility for existing credentials.
- Add optional 360Dialog webhook secret validation and update flows for
existing WhatsApp credentials.
- Validate Meta WABA and phone number access, then auto-subscribe the
Meta app to the WABA during setup.
- Clear and disable WhatsApp integration when the active credentials are
removed, including published bot state.
- Preserve raw webhook request bodies, document preview app secret
configuration, and add focused webhook verification tests.
- Update related tooling, Biome ignore rules, opensrc guidance, and
small formatting/type-safety cleanup.
## Summary
Self-hosted deployments often have legitimate internal corporate APIs on
RFC1918 ranges (10/8, 172.16/12, 192.168/16) — e.g., a backend chat API
exposed only on the internal cluster network. Since v3.14, the SSRF
mitigation introduced for [CVE-2025-64709 /
GHSA-8gq9-rw7v-3jpr](https://github.com/baptisteArno/typebot.io/security/advisories/GHSA-8gq9-rw7v-3jpr)
blocks every private range unconditionally, which prevents HTTP Request
blocks (and Function blocks via fetch) from reaching those APIs without
exposing them to the public internet.
The advisory itself listed hostname allowlisting as one of the
recommended mitigations (item #5: "Implement an SSRF-safe proxy or apply
hostname allowlists for outgoing requests"), and this PR implements it
as an opt-in env var.
## What changes
- New env var `SSRF_ALLOWED_HOSTS` (comma-separated hostnames) parsed in
`packages/env`
- `validateHttpReqUrl` now accepts an `allowedHosts` parameter
(symmetric with the existing `lookupHost` injection point); the env var
is the default
- When the URL's hostname matches an entry, `validateIPAddress` is
called with `{ allowPrivateRanges: true }`, which **only** skips the
RFC1918 range checks (10/8, 172.16/12, 192.168/16)
## What the allowlist does NOT relax
Every other protection remains active even for allowlisted hosts:
- ✅ Link-local 169.254.0.0/16 — **the actual CVE vector** (AWS/GCP/Azure
metadata)
- ✅ Loopback 127.0.0.0/8 and IPv6 ::1
- ✅ 0.0.0.0/8
- ✅ IPv6 link-local fe80::/10 and unique local fc00::/7
- ✅ Cloud metadata hostnames (\`metadata.google.internal\`,
\`metadata.goog\`, \`metadata\`)
- ✅ \`localhost\` in production
- ✅ Decimal/hex/octal IP encoding bypasses
- ✅ IMDS bypass headers (\`X-aws-ec2-metadata-token*\`,
\`Metadata-Flavor\`)
This is the deliberate design: **even if an attacker controls DNS for an
allowlisted hostname and points it to 169.254.169.254, the link-local
check still fires.** The allowlist intentionally narrows what's relaxed
— corp LAN access, not metadata-service access.
## Test plan
- [x] All existing 53 SSRF tests still pass unchanged (default behavior
preserved when env unset)
- [x] New \`describe\` block covering 14 cases:
- RFC1918 hostnames pass when listed (10/8, 172.16/12, 192.168/16,
direct IP literal)
- Link-local **still blocks** for allowlisted host (DNS hijack defense)
- Loopback **still blocks** for allowlisted host
- Direct \`169.254.169.254\` IP literal **still blocks** even when
listed
- \`metadata.google.internal\` **still blocks** even when listed
- Decimal-encoded metadata IP **still blocks** even when listed
- Default behavior preserved when \`allowedHosts\` is undefined or empty
- Hostname not in allowlist still blocks
- Case-insensitive matching (URL parser normalizes hostname)
- No subdomain wildcarding (exact match only)
- [x] \`bun test\` green: 63/63 in \`validateHttpReqUrl.test.ts\`
- [x] \`tsc --noEmit\` green for \`packages/lib\` and \`packages/env\`
- [x] Full \`nx affected\` test suite green (whatsapp, feature-flags,
spaces, rich-text, root, emails, bot-engine, results, builder, lib — all
passed)
## Use case
Currently, self-hosters facing this hit dead-ends: their internal corp
DNS resolves to 10.x, the validator rejects it, and the only escape
valves are (a) expose the API publicly (security regression — adds
attack surface), (b) downgrade to ≤ v3.13.x (re-introduces the
vulnerable code path), or (c) maintain a fork with the validator patched
(fragile, breaks on every upgrade). An opt-in env var resolves this
without weakening the core mitigation.
I'm opening a companion issue (#2475) explaining the use case in more
detail and to gather feedback if a different design is preferred — happy
to iterate.
- Revert #2487 (trigger_onepick OAuth param) and #2486 (setAppId +
NEXT_PUBLIC_GOOGLE_SHEETS_APP_ID env var) which broke the Google Sheets
picker in production.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
- Call `PickerBuilder.setAppId()` with the Cloud Project number when
building the Google Sheets picker (required by Google when the OAuth
flow uses the `drive.file` scope, otherwise the picker iframe returns
401).
- Add new optional client env var `NEXT_PUBLIC_GOOGLE_SHEETS_APP_ID` in
`packages/env`.
- Document the new variable and setup step in
`apps/docs/self-hosting/configuration.mdx`.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Move builder, viewer, and workflows onto shared telemetry helpers so request logging, OTLP config, and workflow failures are reported consistently across runtimes.
Adds onboarding email workflow with delayed send and suppression checks.
Introduces unsubscribe/resubscribe UI and API endpoints. Wires workflows
RPC config changes for user onboarding.
Closes#1575
Note: Need to create a new environment variable named
`NEXT_PUBLIC_PEXELS_API_KEY` to store the API Key obtained from Pexels!
https://github.com/user-attachments/assets/4250f799-0bd7-48e9-b9a8-4bc188ad7704
---------
Co-authored-by: Baptiste Arnaud <baptiste.arnaud95@gmail.com>
Co-authored-by: younesbenallal <younes.benallal.06@gmail.com>
Closes#1154
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
- **New Features**
- Added authentication functionality for user sessions in chat API.
- Introduced chat-related API endpoints for starting, previewing, and
continuing chat sessions, and streaming messages.
- Implemented WhatsApp API webhook handling for receiving and processing
messages.
- Added environment variable `NEXT_PUBLIC_CHAT_API_URL` for chat API URL
configuration.
- **Bug Fixes**
- Adjusted file upload logic to correctly determine the API host.
- Fixed message streaming URL in chat integration with OpenAI.
- **Documentation**
- Updated guides for creating blocks, local installation, self-hosting,
and deployment to use `bun` instead of `pnpm`.
- **Refactor**
- Refactored chat API functionalities to use modular architecture.
- Simplified client log saving and session update functionalities by
using external functions.
- Transitioned package management and workflow commands to use `bun`.
- **Chores**
- Switched to `bun` for package management in Dockerfiles and GitHub
workflows.
- Added new Dockerfile for chat API service setup with Bun framework.
- Updated `.prettierignore` and documentation with new commands.
- **Style**
- No visible changes to end-users.
- **Tests**
- No visible changes to end-users.
- **Revert**
- No reverts in this release.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
When using the whatsapp oficial api or another that use the same schema,
with env we can modify the number of groups that the interactive group
will be split.
---------
Co-authored-by: Baptiste Arnaud <baptiste.arnaud95@gmail.com>
Co-authored-by: Baptiste Arnaud <contact@baptiste-arnaud.fr>
refs #1117
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
- **Refactor**
- Dynamically construct API URLs for WhatsApp features using environment
variables for improved reliability and configurability.
- Updated `sendWhatsAppMessage` function to use
`env.WHATSAPP_CLOUD_API_URL` for URL construction, allowing for more
dynamic configuration.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: Baptiste Arnaud <baptiste.arnaud95@gmail.com>