Title: Apache CloudStack `ApiServlet` logs duplicate sensitive query parameter values in plaintext before authentication · Issue #13311 · apache/cloudstack · GitHub
Open Graph Title: Apache CloudStack `ApiServlet` logs duplicate sensitive query parameter values in plaintext before authentication · Issue #13311 · apache/cloudstack
X Title: Apache CloudStack `ApiServlet` logs duplicate sensitive query parameter values in plaintext before authentication · Issue #13311 · apache/cloudstack
Description: Advisory Details Title: Apache CloudStack ApiServlet logs duplicate sensitive query parameter values in plaintext before authentication Description: Summary Apache CloudStack exposes a sensitive information disclosure issue in the /clien...
Open Graph Description: Advisory Details Title: Apache CloudStack ApiServlet logs duplicate sensitive query parameter values in plaintext before authentication Description: Summary Apache CloudStack exposes a sensitive in...
X Description: Advisory Details Title: Apache CloudStack ApiServlet logs duplicate sensitive query parameter values in plaintext before authentication Description: Summary Apache CloudStack exposes a sensitive in...
Opengraph URL: https://github.com/apache/cloudstack/issues/13311
X: @github
Domain: github.com
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"Apache CloudStack `ApiServlet` logs duplicate sensitive query parameter values in plaintext before authentication","articleBody":"### Advisory Details\n\n**Title**: Apache CloudStack `ApiServlet` logs duplicate sensitive query parameter values in plaintext before authentication\n\n**Description**:\n\n### Summary\n\nApache CloudStack exposes a sensitive information disclosure issue in the `/client/api` request entrypoint. When a request contains duplicate query parameters, `com.cloud.api.ApiServlet` emits a WARN log stating that only the last value will be respected. For sensitive parameters such as `password`, the servlet formats the warning with `Arrays.toString(v)` and writes the raw values to the log before authentication, request verification, or command dispatch occurs. A remote caller can therefore cause plaintext credential material to be recorded in management logs even when the HTTP request itself fails with `401 Unauthorized`.\n\n### Details\n\nThe issue is in `server/src/main/java/com/cloud/api/ApiServlet.java`. Inside `processRequestInContext`, CloudStack reads the servlet parameter map and immediately passes it to `checkSingleQueryParameterValue(reqParams)`. That helper logs duplicate values without masking sensitive keys.\n\n```java\nprivate void checkSingleQueryParameterValue(Map\u003cString, String[]\u003e params) {\n params.forEach((k, v) -\u003e {\n if (v.length \u003e 1) {\n String message = String.format(\"Query parameter '%s' has multiple values %s. Only the last value will be respected.\" +\n \"It is advised to pass only a single parameter\", k, Arrays.toString(v));\n LOGGER.warn(message);\n }\n });\n}\n```\n\nThe vulnerable control flow is:\n\n1. External caller reaches `/client/api` through Jetty.\n2. `ApiServlet.processRequestInContext(...)` calls `req.getParameterMap()`.\n3. `checkSingleQueryParameterValue(reqParams)` executes before `verifyRequest(...)`.\n4. `LOGGER.warn(...)` writes duplicate sensitive values in plaintext.\n5. Only after that does the request continue into UTF-8 fixup, authentication, and API dispatch.\n\nThis is why the issue is reachable from an external network client without valid credentials. In the manual and automated verification environment, the request returned `401`, but the warning log still contained both password values.\n\nThe servlet is the standard API front door defined in `client/src/main/webapp/WEB-INF/web.xml`:\n\n```xml\n\u003cservlet\u003e\n \u003cservlet-name\u003eapiServlet\u003c/servlet-name\u003e\n \u003cservlet-class\u003ecom.cloud.api.ApiServlet\u003c/servlet-class\u003e\n \u003cload-on-startup\u003e5\u003c/load-on-startup\u003e\n\u003c/servlet\u003e\n\u003cservlet-mapping\u003e\n \u003cservlet-name\u003eapiServlet\u003c/servlet-name\u003e\n \u003curl-pattern\u003e/api/*\u003c/url-pattern\u003e\n\u003c/servlet-mapping\u003e\n```\n\n### PoC\n\n#### Prerequisites\n\n- A checkout of Apache CloudStack on the affected branch or release.\n- Java, Maven, and Python 3 installed locally.\n- Network access to fetch Maven dependencies.\n- The PoC uses a minimal Jetty harness because a full current-branch management-server E2E startup was not stable in this lab. The vulnerable code path itself is the real `ApiServlet` from the target project.\n\n#### Reproduction Steps\n\n1. Download the harness launcher from: [start_harness.sh](https://gist.github.com/YLChen-007/3f72b3b782f801c962f85131131c33fc)\n2. Download the minimal servlet harness from: [ApiServletHarnessServer.java](https://gist.github.com/YLChen-007/911719873d1971e07abaf1cd36e53878)\n3. Download the Log4j harness config from: [log4j2-harness.xml](https://gist.github.com/YLChen-007/983e67bf057554fc92f87fc4a59c96d8)\n4. Download the automation wrapper from: [verification_test.py](https://gist.github.com/YLChen-007/545bad01b0931a4434453e53180aaafe)\n5. Optionally download the control case from: [control-normal_behavior.py](https://gist.github.com/YLChen-007/f1a14cba0f26748d94ad818570ec4ff4)\n6. Place the files in one working directory with `ApiServletHarnessServer.java` under `src/`.\n7. Start the PoC harness:\n `bash start_harness.sh --port 18085`\n8. In another terminal, send a duplicate sensitive parameter request:\n `curl -i 'http://127.0.0.1:18085/client/api?command=listCapabilities\u0026response=json\u0026password=MANUAL_SECRET_ONE\u0026password=MANUAL_SECRET_TWO'`\n9. Observe the harness console output. The request may return `401 Unauthorized`, but the server log will contain both password values in the WARN line.\n10. For an automated check, run:\n `python3 verification_test.py`\n\n### Log of Evidence\n\nManual trigger evidence captured during verification:\n\n```text\nHTTP/1.1 401 Unauthorized\n...\n{\"error\":\"stubbed after duplicate-parameter check\"}\n\nWARN com.cloud.api.ApiServlet - Query parameter 'password' has multiple values [MANUAL_SECRET_ONE, MANUAL_SECRET_TWO]. Only the last value will be respected.It is advised to pass only a single parameter\n```\n\nAutomated verification evidence:\n\n```text\n[MODE] Integration-Test\n[OBSERVED_WARNING] WARN com.cloud.api.ApiServlet - Query parameter 'password' has multiple values [EXP_SECRET_ALPHA_8852, EXP_SECRET_BETA_8852]. Only the last value will be respected.It is advised to pass only a single parameter\n[OBSERVED_LEAK_ALPHA] True\n[OBSERVED_LEAK_BETA] True\n[CLASSIFICATION] DEFECT-CONFIRMED-WITH-LIMITATIONS\n```\n\nControl evidence:\n\n```text\n[MODE] Integration-Test Control\n[OBSERVED_WARNING] WARN com.cloud.api.ApiServlet - Query parameter 'username' has multiple values [CONTROL_USER_ALPHA_8852, CONTROL_USER_BETA_8852]. Only the last value will be respected.It is advised to pass only a single parameter\n[OBSERVED_PASSWORD_SECRET] False\n[CONTROL] SUCCESS\n```\n\n### Impact\n\nThis is an information disclosure vulnerability in the API control plane. Any actor who can send requests to `/client/api` can force plaintext sensitive values into management logs simply by repeating a sensitive parameter name. The immediate impact is credential leakage to anyone with access to local logs, centralized log collection, support bundles, or backups. Depending on the leaked parameter, this can expose administrator passwords, API secrets, session tokens, or other credentials that can later be reused against CloudStack.\n\n### Affected products\n\n- **Ecosystem**: maven\n- **Package name**: org.apache.cloudstack:cloudstack\n- **Affected versions**: \u003c= 4.22.1.0\n- **Patched versions**: \u003cNone\u003e\n\n### Severity\n\n- **Severity**: Medium\n- **Vector string**: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N\n\n### Weaknesses\n\n- **CWE**: CWE-200: Exposure of Sensitive Information to an Unauthorized Actor\n\n### Occurrences\n\n| Permalink | Description |\n| :--- | :--- |\n| [https://github.com/apache/cloudstack/blob/348ce953a99246a756b527994f7745a7be038234/server/src/main/java/com/cloud/api/ApiServlet.java#L199-L204](https://github.com/apache/cloudstack/blob/348ce953a99246a756b527994f7745a7be038234/server/src/main/java/com/cloud/api/ApiServlet.java#L199-L204) | `checkSingleQueryParameterValue` formats duplicate query parameter values with `Arrays.toString(v)` and writes them directly with `LOGGER.warn(...)` without any sensitive-key masking. |\n| [https://github.com/apache/cloudstack/blob/348ce953a99246a756b527994f7745a7be038234/server/src/main/java/com/cloud/api/ApiServlet.java#L229-L230](https://github.com/apache/cloudstack/blob/348ce953a99246a756b527994f7745a7be038234/server/src/main/java/com/cloud/api/ApiServlet.java#L229-L230) | `processRequestInContext` invokes the duplicate-parameter warning path immediately after `req.getParameterMap()`, before authentication and request verification. |\n| [https://github.com/apache/cloudstack/blob/348ce953a99246a756b527994f7745a7be038234/client/src/main/webapp/WEB-INF/web.xml#L45-L60](https://github.com/apache/cloudstack/blob/348ce953a99246a756b527994f7745a7be038234/client/src/main/webapp/WEB-INF/web.xml#L45-L60) | The standard `/client/api` servlet mapping shows this vulnerable code is on the default external HTTP API path. |","author":{"url":"https://github.com/YLChen-007","@type":"Person","name":"YLChen-007"},"datePublished":"2026-06-01T07:33:22.000Z","interactionStatistic":{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":2},"url":"https://github.com/13311/cloudstack/issues/13311"}
| route-pattern | /_view_fragments/issues/show/:user_id/:repository/:id/issue_layout(.:format) |
| route-controller | voltron_issues_fragments |
| route-action | issue_layout |
| fetch-nonce | v2:a47b2519-f82b-0492-d34b-2f0a74f00b71 |
| current-catalog-service-hash | 81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114 |
| request-id | DAEA:204C81:10D25C4:1682670:6A4D8D2E |
| html-safe-nonce | 0a524cd7bf607623f7b1a87697433004eac093eb8abf0305d899bbce3123f16f |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiJEQUVBOjIwNEM4MToxMEQyNUM0OjE2ODI2NzA6NkE0RDhEMkUiLCJ2aXNpdG9yX2lkIjoiMjc2MTgzNzExMTgzMzEwMzY2MiIsInJlZ2lvbl9lZGdlIjoiaWFkIiwicmVnaW9uX3JlbmRlciI6ImlhZCJ9 |
| visitor-hmac | a1efe1e455886e3c6dba4f1dfb81bf89318bbfc5acf2ac152aac5b1eb853c35b |
| hovercard-subject-tag | issue:4561210248 |
| github-keyboard-shortcuts | repository,issues,copilot |
| google-site-verification | Apib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I |
| octolytics-url | https://collector.github.com/github/collect |
| analytics-location | / |
| fb:app_id | 1401488693436528 |
| apple-itunes-app | app-id=1477376905, app-argument=https://github.com/_view_fragments/issues/show/apache/cloudstack/13311/issue_layout |
| twitter:image | https://opengraph.githubassets.com/89ad9ce9b4f603d51925082855768641e3223a65854f95d802315fbec0faa91c/apache/cloudstack/issues/13311 |
| twitter:card | summary_large_image |
| og:image | https://opengraph.githubassets.com/89ad9ce9b4f603d51925082855768641e3223a65854f95d802315fbec0faa91c/apache/cloudstack/issues/13311 |
| og:image:alt | Advisory Details Title: Apache CloudStack ApiServlet logs duplicate sensitive query parameter values in plaintext before authentication Description: Summary Apache CloudStack exposes a sensitive in... |
| og:image:width | 1200 |
| og:image:height | 600 |
| og:site_name | GitHub |
| og:type | object |
| og:author:username | YLChen-007 |
| hostname | github.com |
| expected-hostname | github.com |
| None | 9f8758a3953dfe943439713a6fa4f90d542a3431f10e861ca03dd7f39009f320 |
| turbo-cache-control | no-preview |
| go-import | github.com/apache/cloudstack git https://github.com/apache/cloudstack.git |
| octolytics-dimension-user_id | 47359 |
| octolytics-dimension-user_login | apache |
| octolytics-dimension-repository_id | 9759448 |
| octolytics-dimension-repository_nwo | apache/cloudstack |
| octolytics-dimension-repository_public | true |
| octolytics-dimension-repository_is_fork | false |
| octolytics-dimension-repository_network_root_id | 9759448 |
| octolytics-dimension-repository_network_root_nwo | apache/cloudstack |
| turbo-body-classes | logged-out env-production page-responsive |
| disable-turbo | false |
| browser-stats-url | https://api.github.com/_private/browser/stats |
| browser-errors-url | https://api.github.com/_private/browser/errors |
| release | bffd5484f01713a661b03469b77678f72b6574ed |
| ui-target | full |
| theme-color | #1e2327 |
| color-scheme | light dark |
Links:
Viewport: width=device-width