| tiêu đề | Dianping (Meituan) CAT (Central Application Tracking), module `cat-home` (report web UI) 3.0.0 (released tag, same code path) and the 4.0-RC1 development line; reviewed at commit e815e74d4c2dd74edac831241f1253fcc7d25381 Cross-site scripting |
|---|
| Mô tả | Unauthenticated reflected XSS through the domain parameter of every CAT report page
Vendor: Dianping (Meituan)
Affected versions: 3.0.0 (released tag, same code path) and the 4.0-RC1 development line; reviewed at commit e815e74d4c2dd74edac831241f1253fcc7d25381
Vulnerability class: Cross-site scripting, reflected (CWE-79)
Preconditions: none — anyone who can reach the deployment gets the page served anonymously under the shipped configuration. `PermissionFilter` (`system/page/permission/PermissionFilter.java:81-95`) bypasses authentication when `resourceConfigManager.getRole(requestURI, op)` returns `ResourceConfigManager.DEFAULT_RESOURCE_ROLE` (`ResourceConfigManager.java:44`, returned at `:87`); the shipped policy in `cat-home/src/main/resources/config/resource-config.xml` is only `<resource path="/r" op="view" role="2"/>`, whose key is the literal `/r` — a real request URI (`/cat/r/transaction`) never matches it, so the request is served as role 1 (anonymous). Confirmed at runtime with a cookie-less client.
Unauthenticated reflected XSS through the domain parameter of every CAT report page
Data flow: HTTP parameter `domain` → `AbstractReportPayload.java:54-55` → report handler/`Model.getDomain()` → `${model.domain}` unescaped in `WEB-INF/tags/hourlyReport.tag:104,116` / `historyReport.tag:103,116,120-129` (and page-level JSP duplicates)
### Affected interfaces
| Interface |
|---|
| GET /cat/r/transaction?op=view&domain=<payload> — and every other report page (transaction, event, problem, heartbeat, cross, business, state, …) |
| GET /cat/r/transaction?op=history&domain=<payload> — history mode of the same pages |
Primary route detail:
```
GET /cat/r/<page>?op=view&domain=<payload>
```
Anonymous. The `domain` request parameter is the report-selection parameter of every CAT report page, meant to name a monitored project. It is bound verbatim and rendered by the shared report JSP tags with unescaped JSP EL inside HTML attributes, so a fully anonymous caller gets arbitrary HTML/JavaScript reflected 82 times in a `200 text/html` response and executed in the CAT origin (`value="…"><script>…` attribute breakout in `hourlyReport.tag:104`).
### Root cause
1. **Source** — `cat-core/src/main/java/com/dianping/cat/mvc/AbstractReportPayload.java:54-55`: `@FieldMeta("domain") private String m_domain = Constants.CAT;` binds the HTTP parameter verbatim (`setDomain`, `:188-192`, accepts every non-empty string).
2. **Flow** — `cat-home/src/main/java/com/dianping/cat/report/page/transaction/Handler.java:187-196` (`getHourlyReport`: `String domain = payload.getDomain();` at `:188`, wrapped into `new ModelRequest(domain, payload.getDate())` at `:194`) and attached to the page model (`Handler.java:238-242`, `:280`, `:286-293`, `:324`); the same pattern exists in the sibling report handlers. `report/page/transaction/Model.java:116-120` exposes the caller string again as `getDomain()`.
3. **Sink** — the shared report tags render the value unescaped inside HTML attributes:
- `cat-home/src/main/webapp/WEB-INF/tags/hourlyReport.tag:104` — `<input id="search" type="text" value="${model.domain}" …>` (attribute breakout → script execution)
- `hourlyReport.tag:116` — `<a class="switch" href="${model.baseUri}?op=history&domain=${model.domain}&ip=${model.ipAddress}">`
- `historyReport.tag:103`, `:116`, `:120-129` (same value in `value=` / `href=`)
- `hourlyStorageReport.tag:105`, `:117` and `historyStorageReport.tag:104`
- page-level duplicates such as `jsp/report/transaction/transaction.jsp:11-12` (`title=...?domain=${model.domain}` / `navUrlPrefix="...domain=${model.domain}"`), `jsp/report/problem/problemHistoryReport.jsp:20-24`, `jsp/report/home/index.jsp:18-22`, `jsp/report/system.jsp:91`, `:149`.
4. **Missing guard** — no output escaping (`<c:out>`/JSTL/`fn:escapeXml`) on any of the above sinks, and no validation that `domain` is a valid domain name before it enters `ModelRequest`; additionally, the permission filter's literal `/r` policy key means the documented role policy never applies to real report URIs, leaving the reflection reachable anonymously.
Baseline: commit `e815e74d4c2dd74edac831241f1253fcc7d25381`, `cat-home.war` built from source with Maven (sha256 `2152e10cdcdc1c2fafb2dd617755b0388e3e9bcc71306c9c9738bbc027e89107`), self-hosted instance on the reporter's own host on Tomcat 9.0.121 at `127.0.0.1:18808`, with a MySQL 8.4.11 instance. Harmless canary marker: `cv3cat9f31` / `CV3-CAT-XSS-9f31` (no payload that modifies server state).
**1. Anonymous reflected XSS (view mode)**
```sh
$ curl -s -i -G --data-urlencode 'domain=cv3cat9f31"><script>alert("CV3-CAT-XSS-9f31")</script>' \
'http://127.0.0.1:18808/cat/r/transaction?op=view'
HTTP/1.1 200
Set-Cookie: JSESSIONID=DA537DAC3DB0404923753D07FB1167BB; Path=/cat; HttpOnly
Content-Type: text/html;charset=utf-8
raw payload occurrences in body: 82
value="cv3cat9f31"><script>alert("CV3-CAT-XSS-9f31")</script>"
value="cv3cat9f31"><script>alert("CV3-CAT-XSS-9f31")</script>" class="search-
```
The rendered sink is the search box of the hourly report tag (`WEB-INF/tags/hourlyReport.tag:104`); the request sends no cookie, token or `Authorization` header (fresh `curl`, no session jar) — the response hands out a brand-new `JSESSIONID`, i.e. the reflection happens for an anonymous caller.
**2. History-mode variant** — the same request with `op=history` reflects the payload 82 times through `WEB-INF/tags/historyReport.tag:103`.
**3. Negative control** — the identical request with `domain=cat` returns the same page with **0** occurrences of `CV3-CAT-XSS-9f31`.
- **Vendor contact**: GitHub Private Vulnerability Reporting - dianping/cat
- **Status**: vendor notified 2026-10-06 through GitHub Private Vulnerability Reporting; private report <<GHSA_LINK>>; not publicly disclosed; no CVE assigned
- **Duplicate check**: public advisories (NVD/OSV/GitHub) and the project issue tracker were searched before reporting; please tell us if this duplicates something already tracked internally. |
|---|
| Nguồn | ⚠️ https://github.com/dianping/cat |
|---|
| Người dùng | lucasg2g (UID 84737) |
|---|
| Đệ trình | 15/10/2026 07:30 (cách đây 24 ngày) |
|---|
| Kiểm duyệt | 08/11/2026 11:50 (24 days later) |
|---|
| Trạng thái | được chấp nhận |
|---|
| Mục VulDB | 432810 [Dianping CAT 3.0.0/3.1.0/4.0-RC1 Report hourlyReport.tag Model.getDomain domain Tập lệnh chéo trang] |
|---|
| điểm | 19 |
|---|