Every CVE Search/ Get API key

CVE-2026-53727

css_parser: SSRF and Local File Disclosure in `CssParser::Parser#read_remote_file`

8.9 HighFix available

css_parser is a Ruby CSS parser. From 2.2.0 until 3.0.0, CssParser::Parser#read_remote_file in lib/css_parser/parser.rb, and therefore load_uri! and the @import-following branch of add_block!, issued HTTP and HTTPS requests against any host, port, and URI without a scheme allowlist, host or IP filtering, or protection against link-local, loopback, or RFC-1918 addresses. Location: redirects were followed recursively back into the same function, which also serviced file:// URIs, so a single attacker-controlled HTTP redirect could upgrade the bug from SSRF to arbitrary local file disclosure. Any consumer of css_parser that hands it attacker-influenced CSS together with a base_uri: option is exposed. This issue is fixed in version 3.0.0.

Attack profile

How easy it is to exploit

Attack vector
Network
Complexity
Low
Privileges needed
None
User interaction
None

What an attacker can affect

Confidentiality
High
Integrity
None
Availability
None

Exploit likelihood

0.51%Unchanged since Jul 18, 2026
90%50%10%1%

What each source reports

CVE List Score used 8.9

css_parser: SSRF and Local File Disclosure in `CssParser::Parser#read_remote_file`

css_parser is a Ruby CSS parser. From 2.2.0 until 3.0.0, CssParser::Parser#read_remote_file in lib/css_parser/parser.rb, and therefore load_uri! and the @import-following branch of add_block!, issued HTTP and HTTPS requests against any host, port, and URI without a scheme allowlist, host or IP filtering, or protection against link-local, loopback, or RFC-1918 addresses. Location: redirects were followed recursively back into the same function, which also serviced file:// URIs, so a single attacker-controlled HTTP redirect could upgrade the bug from SSRF to arbitrary local file disclosure. Any consumer of css_parser that hands it attacker-influenced CSS together with a base_uri: option is exposed. This issue is fixed in version 3.0.0.

Record
CVE-2026-53727
CVSS 4.0
8.9 HighCVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:N/VA:N/SC:H/SI:N/SA:N
Weakness
CWE-918
Updated
2026-11-02
EUVDEUVD-2026-45324 8.9

css_parser is a Ruby CSS parser. From 2.2.0 until 3.0.0, CssParser::Parser#read_remote_file in lib/css_parser/parser.rb, and therefore load_uri! and the @import-following branch of add_block!, issued HTTP and HTTPS requests against any host, port, and URI without a scheme allowlist, host or IP filtering, or protection against link-local, loopback, or RFC-1918 addresses. Location: redirects were followed recursively back into the same function, which also serviced file:// URIs, so a single attacker-controlled HTTP redirect could upgrade the bug from SSRF to arbitrary local file disclosure. Any consumer of css_parser that hands it attacker-influenced CSS together with a base_uri: option is exposed. This issue is fixed in version 3.0.0.

Record
EUVD-2026-45324
CVSS 4.0
8.9 HighCVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:N/VA:N/SC:H/SI:N/SA:N
Updated
2026-11-02
GitHub AdvisoriesGHSA-9pmc-p236-855h 8.9

Ruby CSS Parser: SSRF and Local File Disclosure in `CssParser::Parser#read_remote_file`

Summary

CssParser::Parser#read_remote_file (and therefore load_uri!, and the @import-following branch of add_block!) issues HTTP/HTTPS requests against any host, port and URI it is handed, with no scheme allowlist, no host / IP filtering, and no protection against link-local, loopback or RFC‑1918 addresses. Location: redirects are followed recursively back into the same function, which also services file:// URIs, so a single attacker-controlled HTTP redirect upgrades the bug from SSRF to arbitrary local file disclosure.

In practice, any consumer of css_parser that hands it attacker‑influenced CSS together with a base_uri: option — Premailer being the canonical example — is exposed. The attacker only needs the ability to land one @import url(...) in the CSS that the host application parses.

Vulnerable code

lib/css_parser/parser.rb#L613-L687:

def read_remote_file(uri) # :nodoc:
  ...
  begin
    uri = Addressable::URI.parse(uri.to_s)

    if uri.scheme == 'file'
      # local file
      path = uri.path
      path.gsub!(%r{^/}, '') if Gem.win_platform?
      src = File.read(path, mode: 'rb')        # <-- arbitrary local read
    else
      # remote file
      if uri.scheme == 'https'
        uri.port = 443 unless uri.port
        http = Net::HTTP.new(uri.host, uri.port)
        http.use_ssl = true
      else
        http = Net::HTTP.new(uri.host, uri.port)  # <-- arbitrary host:port
      end

      res = http.get(uri.request_uri, ...)
      ...
      elsif res.code.to_i >= 300 and res.code.to_i < 400
        unless res['Location'].nil?
          return read_remote_file Addressable::URI.parse(...)  # <-- cross-scheme redirect
        end
      end
    ...

There is no validation of uri.host, uri.scheme, or the resolved IP address — neither before the HTTP request, nor before the recursive call on the Location header.

The user-facing entry points that reach this sink are:

  • Parser#load_uri! — directly calls read_remote_file (line 513).
  • Parser#add_block! — when invoked with base_uri: and the default import: true, scans the CSS for @import url(...) rules and resolves each one through load_uri! (line 150).

Threat model and scope

| Capability | Reachable? | Notes | |---|---|---| | Arbitrary outbound http:// / https:// GET to any host:port reachable from the server | ✅ | No host, IP, port or scheme allowlist. Works against loopback, RFC‑1918, link‑local (169.254/16, AWS / GCP / Azure IMDS), and Docker / k8s service IPs. | | Recovering the response body | ✅ (conditional) | The body is fed back into add_block!. Any bytes that form selector { decl } round‑trip out via Parser#each_selector / to_s. A consumer that emits the parsed CSS (e.g. Premailer inlining into HTML) leaks the body to the original attacker. | | Local file read via cross-scheme redirect (Location: file://...) | ⚠️ partial | Redirect is followed without checking the new scheme; the recursive call services file:// with File.read. The read itself executes against any path the Ruby process can open. Content recovery via the parser API is constrained by CSS grammar — see "File-disclosure scope" below. | | File-existence oracle | ✅ | With default io_exceptions: true, missing paths raise CssParser::RemoteFileError and existing paths return silently. An attacker can iterate file:// targets to enumerate filesystem layout, usernames, installed software, etc. | | Side-effecting GETs against unprotected internal admin endpoints | ✅ | Even with a non‑CSS response, the request…

Record
GHSA-9pmc-p236-855h
CVSS 4.0
8.9 HighCVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:N/VA:N/SC:H/SI:N/SA:N
Weakness
CWE-918
Updated
2026-11-02
NVD 8.9

css_parser is a Ruby CSS parser. From 2.2.0 until 3.0.0, CssParser::Parser#read_remote_file in lib/css_parser/parser.rb, and therefore load_uri! and the @import-following branch of add_block!, issued HTTP and HTTPS requests against any host, port, and URI without a scheme allowlist, host or IP filtering, or protection against link-local, loopback, or RFC-1918 addresses. Location: redirects were followed recursively back into the same function, which also serviced file:// URIs, so a single attacker-controlled HTTP redirect could upgrade the bug from SSRF to arbitrary local file disclosure. Any consumer of css_parser that hands it attacker-influenced CSS together with a base_uri: option is exposed. This issue is fixed in version 3.0.0.

Record
CVE-2026-53727
CVSS 4.0
8.9 HighCVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:N/VA:N/SC:H/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X
CVSS 3.1
8.6 HighCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:N/A:N
Weakness
CWE-918
Updated
2026-11-02
OSV 8.9

css_parser: SSRF and Local File Disclosure in `CssParser::Parser#read_remote_file`

css_parser is a Ruby CSS parser. From 2.2.0 until 3.0.0, CssParser::Parser#read_remote_file in lib/css_parser/parser.rb, and therefore load_uri! and the @import-following branch of add_block!, issued HTTP and HTTPS requests against any host, port, and URI without a scheme allowlist, host or IP filtering, or protection against link-local, loopback, or RFC-1918 addresses. Location: redirects were followed recursively back into the same function, which also serviced file:// URIs, so a single attacker-controlled HTTP redirect could upgrade the bug from SSRF to arbitrary local file disclosure. Any consumer of css_parser that hands it attacker-influenced CSS together with a base_uri: option is exposed. This issue is fixed in version 3.0.0.

Record
CVE-2026-53727
CVSS 4.0
8.9 HighCVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:N/VA:N/SC:H/SI:N/SA:N
Weakness
CWE-918
Updated
2026-11-02
OSVDEBIAN-CVE-2026-53727 8.6

css_parser is a Ruby CSS parser. From 2.2.0 until 3.0.0, CssParser::Parser#read_remote_file in lib/css_parser/parser.rb, and therefore load_uri! and the @import-following branch of add_block!, issued HTTP and HTTPS requests against any host, port, and URI without a scheme allowlist, host or IP filtering, or protection against link-local, loopback, or RFC-1918 addresses. Location: redirects were followed recursively back into the same function, which also serviced file:// URIs, so a single attacker-controlled HTTP redirect could upgrade the bug from SSRF to arbitrary local file disclosure. Any consumer of css_parser that hands it attacker-influenced CSS together with a base_uri: option is exposed. This issue is fixed in version 3.0.0.

Record
DEBIAN-CVE-2026-53727
CVSS 3.1
8.6 HighCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:N/A:N
Updated
2026-11-02
OSVGHSA-9pmc-p236-855h 8.9

Ruby CSS Parser: SSRF and Local File Disclosure in `CssParser::Parser#read_remote_file`

Summary

CssParser::Parser#read_remote_file (and therefore load_uri!, and the @import-following branch of add_block!) issues HTTP/HTTPS requests against any host, port and URI it is handed, with no scheme allowlist, no host / IP filtering, and no protection against link-local, loopback or RFC‑1918 addresses. Location: redirects are followed recursively back into the same function, which also services file:// URIs, so a single attacker-controlled HTTP redirect upgrades the bug from SSRF to arbitrary local file disclosure.

In practice, any consumer of css_parser that hands it attacker‑influenced CSS together with a base_uri: option — Premailer being the canonical example — is exposed. The attacker only needs the ability to land one @import url(...) in the CSS that the host application parses.

Vulnerable code

lib/css_parser/parser.rb#L613-L687:

def read_remote_file(uri) # :nodoc:
  ...
  begin
    uri = Addressable::URI.parse(uri.to_s)

    if uri.scheme == 'file'
      # local file
      path = uri.path
      path.gsub!(%r{^/}, '') if Gem.win_platform?
      src = File.read(path, mode: 'rb')        # <-- arbitrary local read
    else
      # remote file
      if uri.scheme == 'https'
        uri.port = 443 unless uri.port
        http = Net::HTTP.new(uri.host, uri.port)
        http.use_ssl = true
      else
        http = Net::HTTP.new(uri.host, uri.port)  # <-- arbitrary host:port
      end

      res = http.get(uri.request_uri, ...)
      ...
      elsif res.code.to_i >= 300 and res.code.to_i < 400
        unless res['Location'].nil?
          return read_remote_file Addressable::URI.parse(...)  # <-- cross-scheme redirect
        end
      end
    ...

There is no validation of uri.host, uri.scheme, or the resolved IP address — neither before the HTTP request, nor before the recursive call on the Location header.

The user-facing entry points that reach this sink are:

  • Parser#load_uri! — directly calls read_remote_file (line 513).
  • Parser#add_block! — when invoked with base_uri: and the default import: true, scans the CSS for @import url(...) rules and resolves each one through load_uri! (line 150).

Threat model and scope

| Capability | Reachable? | Notes | |---|---|---| | Arbitrary outbound http:// / https:// GET to any host:port reachable from the server | ✅ | No host, IP, port or scheme allowlist. Works against loopback, RFC‑1918, link‑local (169.254/16, AWS / GCP / Azure IMDS), and Docker / k8s service IPs. | | Recovering the response body | ✅ (conditional) | The body is fed back into add_block!. Any bytes that form selector { decl } round‑trip out via Parser#each_selector / to_s. A consumer that emits the parsed CSS (e.g. Premailer inlining into HTML) leaks the body to the original attacker. | | Local file read via cross-scheme redirect (Location: file://...) | ⚠️ partial | Redirect is followed without checking the new scheme; the recursive call services file:// with File.read. The read itself executes against any path the Ruby process can open. Content recovery via the parser API is constrained by CSS grammar — see "File-disclosure scope" below. | | File-existence oracle | ✅ | With default io_exceptions: true, missing paths raise CssParser::RemoteFileError and existing paths return silently. An attacker can iterate file:// targets to enumerate filesystem layout, usernames, installed software, etc. | | Side-effecting GETs against unprotected internal admin endpoints | ✅ | Even with a non‑CSS response, the request…

Record
GHSA-9pmc-p236-855h
CVSS 4.0
8.9 HighCVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:N/VA:N/SC:H/SI:N/SA:N
Weakness
CWE-918
Updated
2026-11-02
OSVUBUNTU-CVE-2026-53727 8.9

css_parser is a Ruby CSS parser. From 2.2.0 until 3.0.0, CssParser::Parser#read_remote_file in lib/css_parser/parser.rb, and therefore load_uri! and the @import-following branch of add_block!, issued HTTP and HTTPS requests against any host, port, and URI without a scheme allowlist, host or IP filtering, or protection against link-local, loopback, or RFC-1918 addresses. Location: redirects were followed recursively back into the same function, which also serviced file:// URIs, so a single attacker-controlled HTTP redirect could upgrade the bug from SSRF to arbitrary local file disclosure. Any consumer of css_parser that hands it attacker-influenced CSS together with a base_uri: option is exposed. This issue is fixed in version 3.0.0.

Record
UBUNTU-CVE-2026-53727
CVSS 4.0
8.9 HighCVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:N/VA:N/SC:H/SI:N/SA:N
CVSS 3.1
8.6 HighCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:N/A:N
Updated
2026-11-02

Affected products

Affected packages

Affected packages
PackageAffectedFixed
css_parser
RubyGems
before 3.0.0
3.0.0
ruby-css-parser
Debian:12
All versions, plus listed versions
1.16.0-11.19.0-11.21.1-11.6.0-21.6.0-2+deb12u1
Show 5 moreShow less
2.0.0-12.1.0-13.0.0-13.1.0-13.3.0-1
None known
ruby-css-parser
Debian:13
All versions, plus listed versions
1.19.0-11.19.0-1+deb13u11.21.1-12.0.0-12.1.0-13.0.0-13.1.0-13.3.0-1
None known
ruby-css-parser
Debian:14
before 3.0.0-1, plus listed versions
1.19.0-11.21.1-12.0.0-12.1.0-1
3.0.0-1
css_parser
RubyGems
before 3.0.0, plus listed versions
0.9.00.9.11.0.01.0.11.1.1
Show 45 moreShow less
1.1.21.1.31.1.41.1.51.1.61.1.71.1.81.1.91.10.01.11.01.12.01.13.01.14.01.15.01.16.01.17.01.17.11.19.01.19.11.2.11.2.21.2.31.2.41.2.51.2.61.20.01.21.01.21.11.22.01.3.01.3.11.3.21.3.31.3.41.3.51.3.61.3.71.4.01.4.11.4.101.4.21.4.31.4.41.4.51.4.6
3.0.0
ruby-css-parser
Ubuntu:16.04:LTS
All versions, plus listed versions
1.3.6-1
None known
ruby-css-parser
Ubuntu:18.04:LTS
All versions, plus listed versions
1.3.6-11.6.0-1
None known
ruby-css-parser
Ubuntu:20.04:LTS
All versions, plus listed versions
1.6.0-1
None known
ruby-css-parser
Ubuntu:22.04:LTS
All versions, plus listed versions
1.6.0-11.6.0-2
None known
ruby-css-parser
Ubuntu:24.04:LTS
All versions, plus listed versions
1.6.0-21.16.0-1
None known
ruby-css-parser
Ubuntu:26.10
All versions, plus listed versions
1.21.1-12.1.0-13.0.0-1
None known
ruby-css-parser
Ubuntu:26.04:LTS
All versions, plus listed versions
1.19.0-11.21.1-1
None known

History

History
RecordedChangedSources
first indexedCVE List, EUVD, GitHub Advisories, NVD, OSV

Dates are when Every CVE recorded each change. Upstream dates may differ.

In short

CVE-2026-53727 is a high vulnerability (CVSS 8.9) in Premailer Css Parser, published July 9, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.51%, the 43rd percentile. Fixed in css_parser 3.0.0.

References

Show 7 moreShow less
This page doesn't list everything

Left out here: 14 versions and the rest of 2 source descriptions. The JSON record has them.

MoveEnter Open