When clicking on an image in the chat preview/runtime, the X button to
close the modal appeared misplaced outside the correct area. This
happened because the button was positioned with `position: fixed`,
remaining stuck to the entire page viewport instead of being inside the
modal/chat container.
before:
<img width="490" height="542" alt="image"
src="https://github.com/user-attachments/assets/ed17cf29-6397-46c7-9779-01aec89c3c5b"
/>
after:
<img width="502" height="523" alt="image"
src="https://github.com/user-attachments/assets/8ac64782-6af4-4417-bad1-971450e0f66c"
/>
---------
Co-authored-by: Baptiste Arnaud <baptiste@typebot.io>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
## Summary
- Add `script.onerror` handler in `initGoogleAnalytics` so the promise
resolves even when the GA script fails to load (ad blockers, network
errors), preventing the bot from hanging indefinitely.
- Bump `@typebot.io/js` and `@typebot.io/react` versions to `0.10.2`.
## Test plan
- [ ] Enable a Google Analytics integration block in a bot
- [ ] Block `googletagmanager.com` (e.g. via ad blocker) and verify the
bot still loads
- [ ] Check that `"Failed to load Google Analytics script"` appears in
the console
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
## Summary
- Fix stored XSS vulnerability where `javascript:` URIs in text bubble
links, image click links, and toast popup links could execute arbitrary
JS in visitors' browsers
- Add `sanitizeUrl` utility that allowlists only `http:`, `https:`,
`mailto:`, and `tel:` protocols
- Add explicit `typecheck` Nx targets for `builder` and `viewer`
(Next.js projects don't get one inferred by `@nx/js/typescript`)
- Bump `@typebot.io/js` and `@typebot.io/react` to `0.10.1`
## Test plan
- [ ] Create a bot with a text bubble link set to `javascript:alert(1)`
and verify it renders as `#`
- [ ] Same test with an image click link
- [ ] Verify normal `https://` links still work
- [ ] Run `bunx nx typecheck builder` and `bunx nx typecheck viewer`
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
## Changes
- **Presigned POST → PUT**: Replace `generatePresignedPostPolicy` with
`generatePresignedPutUrl` across all upload endpoints (builder + viewer
v1/v2/v3). This makes uploads compatible with Cloudflare R2 which
doesn't support the S3 POST Object API. Frontend consumers now use `PUT`
with raw file body + `Content-Type`/`Cache-Control` headers instead of
`POST` with FormData.
- **XSS mitigation**: Block dangerous content types (SVG, HTML, XML, JS)
in the builder `generateUploadUrl` endpoint. Restrict frontend `accept`
attributes from `image/*` to an explicit list of safe raster types
(`png, jpeg, gif, webp, avif, bmp, tiff`). Addresses
GHSA-jj87-c343-26vp.
- **Fix file upload URL validation**: `isURL` with `require_tld: true`
rejected `localhost` and `NEXTAUTH_URL` proxy URLs for private files.
Now uses a trusted host allowlist (`localhost`, `NEXTAUTH_URL`,
`S3_PUBLIC_CUSTOM_DOMAIN`) to skip TLD requirement.
- **Docs**: Update S3 CORS policy from `POST` to `PUT`, add Cloudflare
R2 to supported providers list.
- **Bump**: `@typebot.io/js` and `@typebot.io/react` → `0.10.0`
## Verification
- Tested avatar upload on builder with R2 bucket (PUT succeeds, image
displays)
- Verified CORS preflight passes after R2 bucket config
- Confirmed `generateUploadUrl` rejects `image/svg+xml` with 400
- All unit tests pass (`nx affected -t test`)
- Typecheck passes on all affected packages
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>