CVE-2026-128069
rails-html-sanitizer: Possible XSS via shared scrubber state in concurrent calls
Summary
Rails::HTML::SafeListSanitizer (both the HTML4 and HTML5 variants) shares one Rails::HTML::PermitScrubber across every sanitize call on the same instance, assigning its tags and attributes on each call without synchronization. Two concurrent sanitize calls with different tags: or attributes: options can interleave, so one call is scrubbed with the other call's allowlist.
- Versions affected:
< 1.7.2 - Not affected: none
- Fixed versions:
1.7.2
Impact
Action View memoizes a single SafeListSanitizer per helper module and uses it for every sanitize call in the process, so in a multi-threaded server (for example Puma) all requests share the same PermitScrubber. If any code path calls sanitize with a more permissive allowlist, an attacker who can trigger that path concurrently with another request can cause the other request to be sanitized with the permissive allowlist. If the permissive allowlist admits script or an event-handler attribute, the strict call emits it unchanged, which is a cross-site scripting vector when the strict output is stored or rendered to other users.
Applications are affected only if they run more than one thread per process and some sanitize call passes tags: or attributes: options that differ from another call's, including a call that passes no options and so uses the defaults. Applications that use a single configuration everywhere, pass their own scrubber:, or run single-threaded are not affected.
Workarounds
Use the same allowlist for every sanitize call, or pass a scrubber: built per call (Rails::HTML::PermitScrubber.new with tags= and attributes= set) instead of tags: and attributes: options.
Credit
Reported by hiumee via HackerOne.
Attack profile
How easy it is to exploit
- Attack vector
- Network
- Complexity
- High
- Privileges needed
- None
- User interaction
- Required
What an attacker can affect
- Confidentiality
- Low
- Integrity
- Low
- Availability
- None
What each source reports
GitHub Advisories Score usedGHSA-h7wh-q2qr-458c 4.7
rails-html-sanitizer: Possible XSS via shared scrubber state in concurrent calls
Summary
Rails::HTML::SafeListSanitizer (both the HTML4 and HTML5 variants) shares one Rails::HTML::PermitScrubber across every sanitize call on the same instance, assigning its tags and attributes on each call without synchronization. Two concurrent sanitize calls with different tags: or attributes: options can interleave, so one call is scrubbed with the other call's allowlist.
- Versions affected:
< 1.7.2 - Not affected: none
- Fixed versions:
1.7.2
Impact
Action View memoizes a single SafeListSanitizer per helper module and uses it for every sanitize call in the process, so in a multi-threaded server (for example Puma) all requests share the same PermitScrubber. If any code path calls sanitize with a more permissive allowlist, an attacker who can trigger that path concurrently with another request can cause the other request to be sanitized with the permissive allowlist. If the permissive allowlist admits script or an event-handler attribute, the strict call emits it unchanged, which is a cross-site scripting vector when the strict output is stored or rendered to other users.
Applications are affected only if they run more than one thread per process and some sanitize call passes tags: or attributes: options that differ from another call's, including a call that passes no options and so uses the defaults. Applications that use a single configuration everywhere, pass their own scrubber:, or run single-threaded are not affected.
Workarounds
Use the same allowlist for every sanitize call, or pass a scrubber: built per call (Rails::HTML::PermitScrubber.new with tags= and attributes= set) instead of tags: and attributes: options.
Credit
Reported by hiumee via HackerOne.
- Record
GHSA-h7wh-q2qr-458c- CVSS 3.1
- 4.7 Medium
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:C/C:L/I:L/A:N - Weakness
- CWE-79, CWE-362
- Updated
- 2026-11-13
OSVGHSA-h7wh-q2qr-458c 4.7
rails-html-sanitizer: Possible XSS via shared scrubber state in concurrent calls
Summary
Rails::HTML::SafeListSanitizer (both the HTML4 and HTML5 variants) shares one Rails::HTML::PermitScrubber across every sanitize call on the same instance, assigning its tags and attributes on each call without synchronization. Two concurrent sanitize calls with different tags: or attributes: options can interleave, so one call is scrubbed with the other call's allowlist.
- Versions affected:
< 1.7.2 - Not affected: none
- Fixed versions:
1.7.2
Impact
Action View memoizes a single SafeListSanitizer per helper module and uses it for every sanitize call in the process, so in a multi-threaded server (for example Puma) all requests share the same PermitScrubber. If any code path calls sanitize with a more permissive allowlist, an attacker who can trigger that path concurrently with another request can cause the other request to be sanitized with the permissive allowlist. If the permissive allowlist admits script or an event-handler attribute, the strict call emits it unchanged, which is a cross-site scripting vector when the strict output is stored or rendered to other users.
Applications are affected only if they run more than one thread per process and some sanitize call passes tags: or attributes: options that differ from another call's, including a call that passes no options and so uses the defaults. Applications that use a single configuration everywhere, pass their own scrubber:, or run single-threaded are not affected.
Workarounds
Use the same allowlist for every sanitize call, or pass a scrubber: built per call (Rails::HTML::PermitScrubber.new with tags= and attributes= set) instead of tags: and attributes: options.
Credit
Reported by hiumee via HackerOne.
- Record
GHSA-h7wh-q2qr-458c- CVSS 3.1
- 4.7 Medium
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:C/C:L/I:L/A:N - Weakness
- CWE-362, CWE-79
- Updated
- 2026-11-13
Affected packages
| Package | Affected | Fixed |
|---|---|---|
rails-html-sanitizerRubyGems | before 1.7.2 | 1.7.2 |
rails-html-sanitizerRubyGems | before 1.7.2, plus listed versions 1.0.01.0.11.0.21.0.31.0.4 Show 16 moreShow less1.1.01.2.01.3.01.4.01.4.11.4.21.4.31.4.41.5.01.6.01.6.0.rc11.6.0.rc21.6.11.6.21.7.01.7.1 | 1.7.2 |
History
| Recorded | Changed | Sources |
|---|---|---|
| affected, references | OSV | |
| first indexed | GitHub Advisories |
Dates are when Every CVE recorded each change. Upstream dates may differ.
In short
CVE-2026-128069 is a medium vulnerability (CVSS 4.7) in rails-html-sanitizer, published November 13, 2026. No source lists public exploit code. Fixed in rails-html-sanitizer 1.7.2.
References
github.com/rails/rails-html-sanitizer/security/advisories/GHSA-h7wh-q2qr-458c
github.com/rails/rails-html-sanitizer/issues/228
github.com/rails/rails-html-sanitizer/commit/15f764c3563d5dd9b97ad32eaa7454577ccec4b9
github.com/rails/rails-html-sanitizer/releases/tag/v1.7.2
github.com/rubysec/ruby-advisory-db/blob/master/gems/rails-html-sanitizer/GHSA-h7wh-q2qr-458c.yml
github.com/advisories/GHSA-h7wh-q2qr-458c
github.com/rails/rails-html-sanitizer