Bug 2479230 (CVE-2026-91147) - CVE-2026-91147 cockpit: Cockpit: Denial of Service in `cockpit-ws` due to URL-root handling without a trailing slash
Summary: CVE-2026-91147 cockpit: Cockpit: Denial of Service in `cockpit-ws` due to URL...
Keywords:
Status: NEW
Alias: CVE-2026-91147
Product: Security Response
Classification: Other
Component: vulnerability
Version: unspecified
Hardware: All
OS: Linux
medium
medium
Target Milestone: ---
Assignee: Product Security DevOps Team
QA Contact:
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2026-05-18 03:59 UTC by OSIDB Bzimport
Modified: 2026-09-18 16:33 UTC (History)
4 users (show)

Fixed In Version:
Clone Of:
Environment:
Last Closed:
Embargoed:


Attachments (Terms of Use)

Description OSIDB Bzimport 2026-05-18 03:59:35 UTC
AI_ONLY_REPORT
package: cockpit-356-1.el10
------
Summary: Reachable Assertion DoS in `cockpit-ws` when `WebService.UrlRoot`  
is set and requested without trailing slash: an unauthenticated request to  
the exact configured URL-root prefix can yield an empty internal path and  
trigger a reachable `g_assert()`, aborting `cockpit-ws`.
Requirements to exploit: The target must run `cockpit-356-1.el10` with a  
non-empty `[WebService] UrlRoot`, and the attacker must be able to send an  
exact-prefix request without a trailing slash through a route that does not  
normalize or redirect it first. No authentication or user interaction is  
required. The availability impact depends on a build where `g_assert()` is  
active.
Component affected: `cockpit-356-1.el10`, specifically  
`src/ws/cockpitwebserver.c` in `path_has_prefix()`,  
`cockpit_web_request_process()`, and  
`cockpit_web_server_default_handle_stream()`.
Version affected: `cockpit-356-1.el10` when `[WebService] UrlRoot` is  
configured to a non-empty prefix
Patch available: no released package fix established; proposed patch  
included below
Version fixed: unknown
Upstream coordination: Notified via this report.
CVSS: CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:H - 5.9 (MEDIUM)
AV:N - The issue is triggered by a network request to the Cockpit web  
service.
AC:H - Exploitation requires a non-default but documented `UrlRoot`  
deployment, the exact configured prefix to be requested without a trailing  
slash, and a request path that is not normalized away before `cockpit-ws`  
processes it. The trigger also depends on an assertion-enabled build.
PR:N - No authentication is required.
UI:N - No user interaction is required.
S:U - The impact is confined to the Cockpit web service process.
C:N - No confidentiality impact is established.
I:N - No integrity impact is established.
A:H - A successful trigger reaches a `g_assert()` and aborts  
`cockpit-ws`, interrupting service availability.
Impact: Moderate. Assuming the shipped build retains `g_assert()`, this is  
a remote unauthenticated availability issue. Under Red Hat's guidance,  
remote DoS would normally lean Important, but this case depends on a  
non-default yet documented `UrlRoot` deployment and on the exact prefix  
request reaching `cockpit-ws` without front-end normalization or redirect,  
which makes it less easily exploitable and a better fit for Moderate.
Embargo: no
Reason: This is an availability-only issue in a configuration-dependent  
deployment, and there are straightforward operational mitigations such as  
redirecting or normalizing the exact `UrlRoot` request before it reaches  
`cockpit-ws`.
Acknowledgement: Aisle Research
Vulnerability Details: Non-empty `url_root` handling accepts an exact  
prefix match because `path_has_prefix()` treats either `'\0'` or `'/'`  
after the prefix as valid. `cockpit_web_request_process()` then strips  
`url_root` by pointer arithmetic, so a request such as `/cockpit` becomes  
an empty string rather than `/`:
```c
static gboolean
path_has_prefix (const gchar *path,
GString *prefix)
{
return prefix->len > 0 &&
strncmp (path, prefix->str, prefix->len) == 0 &&
(path[prefix->len] == '\0' || path[prefix->len] == '/');
}
```
```c
if (self->web_server->url_root->len &&
!path_has_prefix (path, self->web_server->url_root))
{
self->delayed_reply = 404;
}
...
self->original_path = path_copy;
self->path = path_copy + self->web_server->url_root->len;
```
The default stream handler assumes the resulting path always begins with  
`/` and aborts otherwise:
```c
g_assert (request->path[0] == '/');
gsize component_end = 1 + strcspn (request->path + 1, "/");
```
`[WebService] UrlRoot` is wired into `url-root` in `src/ws/main.c`, and the  
registered `handle-stream` callbacks only claim their expected `/socket` or  
`/channel/` paths. As a result, an empty path can fall through to the  
default stream handler before authentication. Some front-end proxies may  
normalize or redirect the exact prefix path before `cockpit-ws` sees it, so  
reachability depends on the deployed request path rather than being  
universal across all installations.
Steps to reproduce:
1. Configure Cockpit with a non-empty URL root:
```ini
[WebService]
UrlRoot=/cockpit
```
2. Restart `cockpit-ws` or the service stack that launches it.
3. Send a request to the exact configured prefix without a trailing slash  
using a route that reaches `cockpit-ws` without rewriting the request  
first. For example, in a deployment where the request reaches the service  
directly:
```bash
curl -i http://<host>:9090/cockpit
```
Raw request equivalent:
```http
GET /cockpit HTTP/1.1
Host: <host>:9090
```
If the deployment redirects plain HTTP to HTTPS before `cockpit-ws` handles  
the request, issue the same exact-path request through the front-end HTTPS  
endpoint instead.
4. Observe a process abort at `g_assert (request->path[0] == '/')`.  
Deployments whose front-end normalizes `/cockpit` to `/cockpit/` before  
forwarding may not reproduce through that route.
Mitigation: Until a code fix is available, either avoid deploying a  
non-empty `[WebService] UrlRoot` where feasible, or ensure the front-end  
proxy or TLS terminator rewrites or redirects the exact configured prefix,  
for example `/cockpit`, to the trailing-slash form before forwarding to  
`cockpit-ws`.
Proposed Fix: Normalizing an empty post-prefix path to `/` avoids the  
reachable assertion for exact-root requests, including query-bearing  
variants, while keeping handler behavior otherwise stable.
```diff
diff --git a/src/ws/cockpitwebserver.c b/src/ws/cockpitwebserver.c
@@ -780,6 +780,10 @@ cockpit_web_request_process (CockpitWebRequest *self,
self->path = path_copy + self->web_server->url_root->len;
self->headers = headers;
self->host = host;
@@ -791,6 +795,10 @@ cockpit_web_request_process (CockpitWebRequest *self,
else
self->query = "";
+
+  /* Exact UrlRoot request (e.g. "/cockpit") yields empty suffix;  
normalize */
+  if (self->path[0] == '\0')
+    self->path = "/";
```
Optional follow-up hardening: add a regression test covering `GET /path`  
when `url-root=/path`.
------
This report was generated using AI technology. Always review AI-generated  
content prior to use


Note You need to log in before you can comment on or make changes to this bug.