Hi everyone,
since upgrading OpenLiteSpeed from 1.9.2 to 1.9.3, our OpenLiteSpeed load balancer returns 400 Bad Request for GET requests that contain an unencoded # in the query string. With 1.9.2 the same requests are accepted and forwarded to the backends without any problem. We have rolled back to 1.9.2 for now.
Environment
Background
We operate AWEKAS, a weather station network. Thousands of weather stations upload their data via simple HTTP GET requests. Many of these devices run embedded firmware that does not URL-encode parameter values. If a user’s password contains a #, the request line looks like this (credentials changed):
GET /upload.php?ID=ExampleUser&PASSWORD=abc#123&temp=12.3 HTTP/1.1
Since 1.9.3 these requests are rejected with 400 before they reach the backend.
We understand that an unencoded # is not valid in the request-target (RFC 3986 section 3.4, RFC 9112 section 3.2), and that rejecting it is a reasonable hardening step. Unfortunately we cannot update the firmware of these devices, since they are made by various manufacturers and many are no longer supported.
Questions
Staying on 1.9.2 is only a temporary solution for us, since we don’t want to miss future security fixes.
Thanks in advance for any help!
Best regards,
Othmar Gattringer
AWEKAS GmbH
since upgrading OpenLiteSpeed from 1.9.2 to 1.9.3, our OpenLiteSpeed load balancer returns 400 Bad Request for GET requests that contain an unencoded # in the query string. With 1.9.2 the same requests are accepted and forwarded to the backends without any problem. We have rolled back to 1.9.2 for now.
Environment
- Debian 13 (trixie), amd64
- OpenLiteSpeed installed from the LiteSpeed APT repository
- Affected: 1.9.3-1+trixie, working: 1.9.2-1+trixie
- OLS is used as a load balancer in front of our application servers
Background
We operate AWEKAS, a weather station network. Thousands of weather stations upload their data via simple HTTP GET requests. Many of these devices run embedded firmware that does not URL-encode parameter values. If a user’s password contains a #, the request line looks like this (credentials changed):
GET /upload.php?ID=ExampleUser&PASSWORD=abc#123&temp=12.3 HTTP/1.1
Since 1.9.3 these requests are rejected with 400 before they reach the backend.
We understand that an unencoded # is not valid in the request-target (RFC 3986 section 3.4, RFC 9112 section 3.2), and that rejecting it is a reasonable hardening step. Unfortunately we cannot update the firmware of these devices, since they are made by various manufacturers and many are no longer supported.
Questions
- Was this change in request-line validation intentional in 1.9.3? Is it documented anywhere?
- Is there a configuration option (server, listener or virtual host level) to relax this check and restore the 1.9.2 behavior, e.g. by treating # as a literal character or passing it through to the backend?
- If not, would you consider adding such an option for legacy clients?
Staying on 1.9.2 is only a temporary solution for us, since we don’t want to miss future security fixes.
Thanks in advance for any help!
Best regards,
Othmar Gattringer
AWEKAS GmbH