# Pull Request Template
## Description
- The `0.48` version of the `ddtrace` gem was out of date, which was
causing the application to crash if `DD_AGENT_URL` was configured
- Switch to `datadog` gem, which is the currently maintained gem from DD
Ref: https://github.com/DataDog/dd-trace-rb/releases/tag/v2.0.0
# Pull Request Template
## Description
Fixes
https://linear.app/chatwoot/issue/CW-5432/use-a-different-company-nameemail-for-the-empty-state-in-contacts
## How Has This Been Tested?
### Screenshot
<img width="1044" height="555" alt="image"
src="https://github.com/user-attachments/assets/a414f88f-13ca-4c1e-bb76-cd5b9217d21f"
/>
## Checklist:
- [x] My code follows the style guidelines of this project
- [x] I have performed a self-review of my code
- [ ] I have commented on my code, particularly in hard-to-understand
areas
- [ ] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [ ] I have added tests that prove my fix is effective or that my
feature works
- [x] New and existing unit tests pass locally with my changes
- [ ] Any dependent changes have been merged and published in downstream
modules
Bumps [activerecord](https://github.com/rails/rails) from 7.1.5.1 to
7.1.5.2.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/rails/rails/releases">activerecord's
releases</a>.</em></p>
<blockquote>
<h2>7.1.5.2</h2>
<h2>Active Support</h2>
<ul>
<li>No changes.</li>
</ul>
<h2>Active Model</h2>
<ul>
<li>No changes.</li>
</ul>
<h2>Active Record</h2>
<ul>
<li>
<p>Call inspect on ids in RecordNotFound error</p>
<p>[CVE-2025-55193]</p>
<p><em>Gannon McGibbon</em>, <em>John Hawthorn</em></p>
</li>
</ul>
<h2>Action View</h2>
<ul>
<li>No changes.</li>
</ul>
<h2>Action Pack</h2>
<ul>
<li>No changes.</li>
</ul>
<h2>Active Job</h2>
<ul>
<li>No changes.</li>
</ul>
<h2>Action Mailer</h2>
<ul>
<li>No changes.</li>
</ul>
<h2>Action Cable</h2>
<ul>
<li>No changes.</li>
</ul>
<h2>Active Storage</h2>
<pre><code>Remove dangerous transformations
<p>[CVE-2025-24293]
</code></pre></p>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="ddb56de259"><code>ddb56de</code></a>
Preparing for 7.1.5.2 release</li>
<li><a
href="b279e045fb"><code>b279e04</code></a>
Update CHANGELOGs</li>
<li><a
href="3beef20013"><code>3beef20</code></a>
Call inspect on ids in RecordNotFound error</li>
<li>See full diff in <a
href="https://github.com/rails/rails/compare/v7.1.5.1...v7.1.5.2">compare
view</a></li>
</ul>
</details>
<br />
[](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)
Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.
[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)
---
<details>
<summary>Dependabot commands and options</summary>
<br />
You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/chatwoot/chatwoot/network/alerts).
</details>
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
This PR includes some specific security related fixes
1. Validate the origin of any message events
2. Sanitize URLs before opening them
---------
Co-authored-by: Pranav <pranav@chatwoot.com>
Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
## Reference
https://github.com/chatwoot/chatwoot/pull/12149#issuecomment-3178108388
## Description
setup_webhook was done before the save, and hence the meta webhook
validation might fail because of a race condition where the facebook
validation is done before we saving the entry to the database.
## Type of change
Please delete options that are not relevant.
- [ ] Bug fix (non-breaking change which fixes an issue)
## How Has This Been Tested?
- New inbox creation, webhook validation
- Existing inbox update, webhook validation
-
<img width="614" height="674" alt="image"
src="https://github.com/user-attachments/assets/be223945-deed-475a-82e5-3ae9c54a13fa"
/>
## Checklist:
- [ ] My code follows the style guidelines of this project
- [ ] I have performed a self-review of my code
- [ ] I have commented on my code, particularly in hard-to-understand
areas
- [ ] I have made corresponding changes to the documentation
- [ ] My changes generate no new warnings
- [ ] I have added tests that prove my fix is effective or that my
feature works
- [ ] New and existing unit tests pass locally with my changes
- [ ] Any dependent changes have been merged and published in downstream
modules
---------
Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
Implemented a rescue block for WebPush::TooManyRequests that logs
warnings during rate limiting events. This captures user email and
account ID for better traceability. We will implement a proper
throttling mechanism after identifying patterns across accounts.
# Pull Request Template
## Description
Fixes
https://linear.app/chatwoot/issue/CW-5411/actionviewtemplateerror-activestorageunrepresentableerror
### Problem
API endpoints return 500 errors when conversations contain image
attachments that can't be processed by ActiveStorage (e.g., files with
non-ASCII filenames, corrupted images, or malicious XSS filenames).
Root Cause: Commit 6cab74139 removed the representable? safety check
from thumb_url, causing `ActiveStorage::UnrepresentableError` to bubble
up and crash the API when it encountered a malformed image file.
Fix: Rescue `thumb_url` method to catch UnrepresentableError and return
an empty string while logging problematic names for future debugging.
This ensures the messages/attachments api does not break due to a single
corrupted image file.
## Type of change
- [x] Bug fix (non-breaking change which fixes an issue)
## How Has This Been Tested?
- Added specs
## Checklist:
- [x] My code follows the style guidelines of this project
- [x] I have performed a self-review of my code
- [x] I have commented on my code, particularly in hard-to-understand
areas
- [x] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [x] I have added tests that prove my fix is effective or that my
feature works
- [x] New and existing unit tests pass locally with my changes
- [x] Any dependent changes have been merged and published in downstream
modules
WhatsApp templates without parameters (body-only templates like
notifications, confirmations) were failing to send with the error:
ArgumentError (Unknown legacy format: NilClass). This affected all
parameter-less templates across marketing messages, notifications, and
utility templates.
### Summary
Fixed flaky Instagram webhook specs that failed intermittently in cloud
environments due to shared let blocks creating conflicting inboxes. The
Instagram channel factory already creates an inbox automatically, but
tests were adding extra ones in shared contexts.
Moved channel/inbox creation to isolated test contexts to prevent race
conditions between Facebook Page and Instagram Direct tests.
### Testing
```
for i in {1..30}; do
echo "=== Run $i ==="
RAILS_ENV=test bundle exec rspec spec/jobs/webhooks/instagram_events_job_spec.rb --fail-fast || break
done
```
Previously, intermittent failures could be reproduced locally. With
these changes, tests achieve ~100% pass rate.
WhatsApp template message errors were not being properly handled because
the `@message instance` variable was only set in the `send_message`
method but not in `send_template`. When template sending failed, the
`handle_error` method couldn't update the message status due to the
missing @message reference, resulting in silent failures with no user
feedback.
# Pull Request Template
## Description
This PR fixes RTL alignment issues in the new conversation form, removes
the unused
[`form-checkbox`](https://github.com/chatwoot/chatwoot/pull/12151#discussion_r2266333315)
class name and drops the `app-rtl--wrapper` class, which was previously
used for RTL detection in `rtl.scss` (removed earlier)
Fixes https://linear.app/chatwoot/issue/CW-5410/rtl-issues
## Type of change
- [x] Bug fix (non-breaking change which fixes an issue)
## How Has This Been Tested?
### Screenshots
<img width="868" height="474" alt="image"
src="https://github.com/user-attachments/assets/45995652-2895-49d5-a651-179090c949ec"
/>
<img width="868" height="656" alt="image"
src="https://github.com/user-attachments/assets/a1cb4415-3fd4-4c9a-bc46-5e07e437d757"
/>
<img width="868" height="656" alt="image"
src="https://github.com/user-attachments/assets/77c8981f-364e-4bf0-bea8-a4c42a76d065"
/>
## Checklist:
- [x] My code follows the style guidelines of this project
- [x] I have performed a self-review of my code
- [ ] I have commented on my code, particularly in hard-to-understand
areas
- [ ] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [ ] I have added tests that prove my fix is effective or that my
feature works
- [x] New and existing unit tests pass locally with my changes
- [ ] Any dependent changes have been merged and published in downstream
modules
This PR fixes flaky test failures in the Instagram webhook specs that
were caused by Redis mutex lock conflicts when
tests ran in parallel.
### The Problem:
The InstagramEventsJob uses a Redis mutex with a key based on sender_id
and ig_account_id to prevent race
conditions. However, all test factories were using the same hardcoded
sender_id: 'Sender-id-1', causing multiple
test instances to compete for the same mutex lock when running in
parallel.
### The Solution:
- Updated all Instagram event factories to generate unique sender IDs
using SecureRandom.hex(4)
- Modified test stubs and expectations to work with dynamic sender IDs
instead of hardcoded values
- Ensured each test instance gets its own unique mutex key, eliminating
lock contention
## Summary
- handle Twilio failures per contact when running one-off SMS campaigns
- rescue errors in WhatsApp and generic SMS one-off campaigns so they
continue
- add specs confirming campaigns continue sending when a single contact
fails
fixes: https://github.com/chatwoot/chatwoot/issues/9000
Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
# Pull Request Template
## Description
This PR includes:
1. Previously, the URL fields accepted any value starting with `https`.
Added proper URL validation to ensure valid URLs are entered.
2. Fixed an issue where form save errors displayed `[object Object]` in
the toast due to inconsistent error formatting from the backend.
Fixes https://linear.app/chatwoot/issue/CW-5389/help-center-bugs
## Type of change
- [x] Bug fix (non-breaking change which fixes an issue)
## How Has This Been Tested?
### Loom video
https://www.loom.com/share/63ddca2c5e2e45c99b66153ed146524f?sid=fd25331b-6b67-4722-9b36-1213496a0741
## Checklist:
- [x] My code follows the style guidelines of this project
- [x] I have performed a self-review of my code
- [ ] I have commented on my code, particularly in hard-to-understand
areas
- [ ] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [ ] I have added tests that prove my fix is effective or that my
feature works
- [x] New and existing unit tests pass locally with my changes
- [ ] Any dependent changes have been merged and published in downstream
modules
This update adds support to the coexistence method to Embedded Whatsapp,
allowing users to add their existing whatsapp business number in order
to use it in both places(chatwoot and whatsapp business) at the same
time.
This update require some changes in the permissions for the Meta App, as
described in the Meta Oficial Docs, I'll leave this listed below:
- **history** — describes past messages the business customer has
sent/received
- **smb_app_state_sync** — describes the business customer's current and
new contacts
- **smb_message_echoes** — describes any new messages the business
customer sends with the WhatsApp Business app after having been
onboarded
Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
Co-authored-by: Sojan Jose <sojan@pepalo.com>
Co-authored-by: Tanmay Deep Sharma <32020192+tds-1@users.noreply.github.com>
# Pull Request Template
## Description
This PR increase z-index of filter dropdown to prevent overlap with
other elements.
Fixes
https://linear.app/chatwoot/issue/CW-5394/update-z-index-for-filters
## Type of change
- [x] Bug fix (non-breaking change which fixes an issue)
## How Has This Been Tested?
### Screenshot
<img width="823" height="250" alt="image"
src="https://github.com/user-attachments/assets/5788fc6d-a901-4d6a-8e8b-d4f49cccb12e"
/>
## Checklist:
- [x] My code follows the style guidelines of this project
- [x] I have performed a self-review of my code
- [ ] I have commented on my code, particularly in hard-to-understand
areas
- [ ] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [ ] I have added tests that prove my fix is effective or that my
feature works
- [x] New and existing unit tests pass locally with my changes
- [ ] Any dependent changes have been merged and published in downstream
modules
# Pull Request Template
## Description
Please include a summary of the change and issue(s) fixed. Also, mention
relevant motivation, context, and any dependencies that this change
requires.
Fixes # (issue)
## Type of change
Please delete options that are not relevant.
- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing
functionality not to work as expected)
- [ ] This change requires a documentation update
## How Has This Been Tested?
Please describe the tests that you ran to verify your changes. Provide
instructions so we can reproduce. Please also list any relevant details
for your test configuration.
## Checklist:
- [ ] My code follows the style guidelines of this project
- [ ] I have performed a self-review of my code
- [ ] I have commented on my code, particularly in hard-to-understand
areas
- [ ] I have made corresponding changes to the documentation
- [ ] My changes generate no new warnings
- [ ] I have added tests that prove my fix is effective or that my
feature works
- [ ] New and existing unit tests pass locally with my changes
- [ ] Any dependent changes have been merged and published in downstream
modules
---------
Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
Database CPU utilization was spiking due to expensive notification COUNT
queries. Analysis revealed two critical issues:
1. Missing database index: Notification count queries were performing
table scans without proper indexing
2. Duplicate WHERE clauses: SQL queries contained redundant read_at IS
NULL conditions, causing unnecessary query complexity
### Root Cause Analysis
The expensive queries were:
```
-- 41.61 calls/sec with duplicate condition
SELECT COUNT(*) FROM "notifications"
WHERE "notifications"."user_id" = $1
AND "notifications"."account_id" = $2
AND "notifications"."snoozed_until" IS NULL
AND "notifications"."read_at" IS NULL
AND "notifications"."read_at" IS NULL -- Duplicate!
```
This was caused by a logic error in NotificationFinder#unread_count
introduced in commit cd06b2b33 (PR #8907). The method assumed
@notifications contained all notifications, but @notifications was
already filtered to unread notifications in most cases.
### The Default Query Flow:
1. Frontend calls: NotificationsAPI.getUnreadCount() →
/notifications/unread_count
2. No parameters sent, so params = {}
3. NotificationFinder setup:
- find_all_notifications: WHERE user_id = ? AND account_id = ?
- filter_snoozed_notifications: WHERE snoozed_until IS NULL
- filter_read_notifications: WHERE read_at IS NULL (because
type_included?('read') is false)
4. unread_count called: Adds another WHERE read_at IS NULL
----
### Solution
1. Added Missing Database Index
- Index: (user_id, account_id, snoozed_until, read_at)
2. Fixed Duplicate WHERE Clause Logic