CWE-598
AllowedUse of HTTP Request With Sensitive Query String
Abstraction: Variant · Status: Draft
The web application uses an HTTP method to process a request, but the request includes sensitive information in the query string.
139 vulnerabilities reference this CWE, most recent first.
GHSA-J6R2-9GJ9-JMVP
Vulnerability from github – Published: 2024-11-01 18:31 – Updated: 2024-11-01 18:31IBM TXSeries for Multiplatforms 10.1 could allow an attacker to obtain sensitive information from the query string of an HTTP GET method to process a request which could be obtained using man in the middle techniques.
{
"affected": [],
"aliases": [
"CVE-2024-41738"
],
"database_specific": {
"cwe_ids": [
"CWE-598"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2024-11-01T17:15:16Z",
"severity": "MODERATE"
},
"details": "IBM TXSeries for Multiplatforms 10.1 could allow an attacker to obtain sensitive information from the query string of an HTTP GET method to process a request which could be obtained using man in the middle techniques.",
"id": "GHSA-j6r2-9gj9-jmvp",
"modified": "2024-11-01T18:31:33Z",
"published": "2024-11-01T18:31:33Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2024-41738"
},
{
"type": "WEB",
"url": "https://www.ibm.com/support/pages/node/7174572"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:N/A:N",
"type": "CVSS_V3"
}
]
}
GHSA-JC6H-3P5P-HP65
Vulnerability from github – Published: 2026-03-25 21:30 – Updated: 2026-03-25 21:30IBM InfoSphere Information Server 11.7.0.0 through 11.7.1.6 could allow an attacker to obtain sensitive information from the query string of an HTTP GET method to process a request which could be obtained using man in the middle techniques.
{
"affected": [],
"aliases": [
"CVE-2025-14808"
],
"database_specific": {
"cwe_ids": [
"CWE-598"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2026-03-25T21:16:23Z",
"severity": "LOW"
},
"details": "IBM InfoSphere Information Server 11.7.0.0 through 11.7.1.6 could allow an attacker to obtain sensitive information from the query string of an HTTP GET method to process a request which could be obtained using man in the middle techniques.",
"id": "GHSA-jc6h-3p5p-hp65",
"modified": "2026-03-25T21:30:35Z",
"published": "2026-03-25T21:30:35Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2025-14808"
},
{
"type": "WEB",
"url": "https://www.ibm.com/support/pages/node/7266695"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:L/I:N/A:N",
"type": "CVSS_V3"
}
]
}
GHSA-JVP4-Q659-95MJ
Vulnerability from github – Published: 2026-05-14 16:33 – Updated: 2026-06-09 10:25Summary
Portainer's authentication middleware accepts JWT bearer tokens passed as the ?token=<JWT> URL query parameter on any authenticated API endpoint, in addition to the standard Authorization: Bearer header. URLs are recorded in reverse-proxy access logs, browser history, and HTTP Referer headers on outbound navigation, so any JWT passed this way can be harvested by anyone with access to those logs or by an external site the user subsequently visits. A leaked token grants the full privileges of the user it was issued to, until the token expires (default 8 hours, configurable).
The ?token= parameter was used by Portainer's browser-based container attach, exec, and pod shell features, so any user with exec or attach rights on a container was exposed — not only administrators.
Severity
High
Attack complexity is High because exploitation depends on the attacker obtaining a leaked token from a log, referer, or shared URL. Once obtained, a leaked token grants the privileges of the user it was issued to; for administrator tokens this compromises confidentiality, integrity, and availability of Portainer itself and of every Docker/Kubernetes environment it manages — container exec and stack deployment make host-level compromise reachable, so subsequent-system impact is also High.
Affected Versions
Query-parameter token acceptance has existed since JWT authentication was introduced in Portainer.
Fixes are included in the following releases:
| Branch | First vulnerable | Fixed in |
|---|---|---|
| 2.33.x (LTS) | 2.33.0 | 2.33.8 |
| 2.39.x (LTS) | 2.39.0 | 2.39.2 |
| 2.40.x (STS) | all prior | 2.41.0 |
Portainer releases prior to 2.33.0 are end-of-life and will not receive a fix. Users on EOL versions should upgrade to a supported LTS branch.
Workarounds
Administrators who cannot immediately upgrade can reduce exposure by:
- Stripping
?token=at the reverse proxy. A rewrite rule in nginx, Traefik, or equivalent that removes thetokenquery parameter before the request reaches Portainer blocks the query-parameter auth path entirely. Container exec and interactive shells rely on the query-parameter token for WebSocket upgrade and will stop working until the patched release is deployed. - Auditing existing logs. Search reverse-proxy access logs and application logs for
?token=or&token=occurrences and treat any captured JWT as compromised. Resetting the affected user's password invalidates their sessions; reducing the JWT session timeout in Portainer settings shortens the exposure window for tokens already issued. - Administrator hygiene. Do not share Portainer URLs that contain
?token=in chat, email, or tickets, and avoid navigating to external sites from within the Portainer UI on unpatched instances — theRefererheader will carry the token.
None of these replace the fix.
Affected Code
Pre-fix, extractBearerToken in api/http/security/bouncer.go read the JWT from the token query parameter before falling back to the Authorization header. The query.Del("token") call scrubs the parameter from r.URL.RawQuery on the way through Portainer, but by that point the original URL has already been recorded by any upstream reverse proxy, access logger, or browser.
func extractBearerToken(r *http.Request) (string, bool) {
query := r.URL.Query()
token := query.Get("token")
if token != "" {
query.Del("token")
r.URL.RawQuery = query.Encode()
return token, true
}
tokens, ok := r.Header[jwtTokenHeader]
if !ok || len(tokens) == 0 {
return "", false
}
// ...
}
The fix removes the query-parameter path entirely. Authenticated requests now carry the JWT via the Authorization header for API clients, or via the portainer_api_key HttpOnly cookie for the browser UI — cookies are sent automatically on same-origin WebSocket upgrade requests, so the browser-based container attach, exec, and pod shell features continue to work without exposing the token in the URL. The WebSocket handlers that previously documented ?token= as a required query parameter have been updated to match.
Impact
- Token leakage to infrastructure. Intermediate systems that observe the request URL — reverse proxies, load balancers, access logs, WAFs, and corporate network monitoring — capture the full JWT in plaintext.
- Token leakage via the browser. URLs containing
?token=are recorded in browser history and forwarded in theRefererheader on any outbound navigation from the Portainer UI. - Account takeover. Anyone with access to a leaked JWT acts as the authenticated user for the remainder of the token's validity, without needing the password. If the leaked token belongs to an administrator, the attacker gains full API access including user management, container exec, and stack deployment.
- Reach beyond Portainer. Container exec with an administrator JWT reaches the host filesystem of managed environments and can be used to execute commands on those hosts.
Timeline
- 2026-03-06: Reported via GitHub Security Advisory by scanpwn.
- 2026-04-14: Fix merged to
develop. - 2026-04-29: 2.41.0 released.
- 2026-05-07: 2.39.2-LTS and 2.33.8-LTS released.
Credit
- scanpwn — identified and reported the query-parameter JWT acceptance and the resulting token-leakage vectors.
{
"affected": [
{
"package": {
"ecosystem": "Go",
"name": "github.com/portainer/portainer"
},
"ranges": [
{
"events": [
{
"introduced": "2.33.0"
},
{
"fixed": "2.33.8"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "Go",
"name": "github.com/portainer/portainer"
},
"ranges": [
{
"events": [
{
"introduced": "2.39.0"
},
{
"fixed": "2.39.2"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "Go",
"name": "github.com/portainer/portainer"
},
"ranges": [
{
"events": [
{
"introduced": "2.40.0"
},
{
"fixed": "2.41.0"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-44883"
],
"database_specific": {
"cwe_ids": [
"CWE-598"
],
"github_reviewed": true,
"github_reviewed_at": "2026-05-14T16:33:48Z",
"nvd_published_at": "2026-05-28T22:16:59Z",
"severity": "HIGH"
},
"details": "## Summary\nPortainer\u0027s authentication middleware accepts JWT bearer tokens passed as the `?token=\u003cJWT\u003e` URL query parameter on any authenticated API endpoint, in addition to the standard `Authorization: Bearer` header. URLs are recorded in reverse-proxy access logs, browser history, and HTTP `Referer` headers on outbound navigation, so any JWT passed this way can be harvested by anyone with access to those logs or by an external site the user subsequently visits. A leaked token grants the full privileges of the user it was issued to, until the token expires (default 8 hours, configurable).\n\nThe `?token=` parameter was used by Portainer\u0027s browser-based container attach, exec, and pod shell features, so any user with exec or attach rights on a container was exposed \u2014 not only administrators.\n\n## Severity\n**High**\n\nAttack complexity is High because exploitation depends on the attacker obtaining a leaked token from a log, referer, or shared URL. Once obtained, a leaked token grants the privileges of the user it was issued to; for administrator tokens this compromises confidentiality, integrity, and availability of Portainer itself and of every Docker/Kubernetes environment it manages \u2014 container exec and stack deployment make host-level compromise reachable, so subsequent-system impact is also High.\n\n## Affected Versions\nQuery-parameter token acceptance has existed since JWT authentication was introduced in Portainer.\n\nFixes are included in the following releases:\n\n| Branch | First vulnerable | Fixed in |\n|---------------------|------------------|------------|\n| 2.33.x (LTS) | 2.33.0 | **2.33.8** |\n| 2.39.x (LTS) | 2.39.0 | **2.39.2** |\n| 2.40.x (STS) | all prior | **2.41.0** |\n\nPortainer releases prior to 2.33.0 are end-of-life and will not receive a fix. Users on EOL versions should upgrade to a supported LTS branch.\n\n## Workarounds\nAdministrators who cannot immediately upgrade can reduce exposure by:\n\n- **Stripping `?token=` at the reverse proxy.** A rewrite rule in nginx, Traefik, or equivalent that removes the `token` query parameter before the request reaches Portainer blocks the query-parameter auth path entirely. Container exec and interactive shells rely on the query-parameter token for WebSocket upgrade and will stop working until the patched release is deployed.\n- **Auditing existing logs.** Search reverse-proxy access logs and application logs for `?token=` or `\u0026token=` occurrences and treat any captured JWT as compromised. Resetting the affected user\u0027s password invalidates their sessions; reducing the JWT session timeout in Portainer settings shortens the exposure window for tokens already issued.\n- **Administrator hygiene.** Do not share Portainer URLs that contain `?token=` in chat, email, or tickets, and avoid navigating to external sites from within the Portainer UI on unpatched instances \u2014 the `Referer` header will carry the token.\n\nNone of these replace the fix.\n\n## Affected Code\nPre-fix, `extractBearerToken` in `api/http/security/bouncer.go` read the JWT from the `token` query parameter before falling back to the `Authorization` header. The `query.Del(\"token\")` call scrubs the parameter from `r.URL.RawQuery` on the way through Portainer, but by that point the original URL has already been recorded by any upstream reverse proxy, access logger, or browser.\n\n```go\nfunc extractBearerToken(r *http.Request) (string, bool) {\n query := r.URL.Query()\n token := query.Get(\"token\")\n if token != \"\" {\n query.Del(\"token\")\n r.URL.RawQuery = query.Encode()\n return token, true\n }\n\n tokens, ok := r.Header[jwtTokenHeader]\n if !ok || len(tokens) == 0 {\n return \"\", false\n }\n // ...\n}\n```\n\nThe fix removes the query-parameter path entirely. Authenticated requests now carry the JWT via the `Authorization` header for API clients, or via the `portainer_api_key` HttpOnly cookie for the browser UI \u2014 cookies are sent automatically on same-origin WebSocket upgrade requests, so the browser-based container attach, exec, and pod shell features continue to work without exposing the token in the URL. The WebSocket handlers that previously documented `?token=` as a required query parameter have been updated to match.\n\n## Impact\n- **Token leakage to infrastructure.** Intermediate systems that observe the request URL \u2014 reverse proxies, load balancers, access logs, WAFs, and corporate network monitoring \u2014 capture the full JWT in plaintext.\n- **Token leakage via the browser.** URLs containing `?token=` are recorded in browser history and forwarded in the `Referer` header on any outbound navigation from the Portainer UI.\n- **Account takeover.** Anyone with access to a leaked JWT acts as the authenticated user for the remainder of the token\u0027s validity, without needing the password. If the leaked token belongs to an administrator, the attacker gains full API access including user management, container exec, and stack deployment.\n- **Reach beyond Portainer.** Container exec with an administrator JWT reaches the host filesystem of managed environments and can be used to execute commands on those hosts.\n\n## Timeline\n- 2026-03-06: Reported via GitHub Security Advisory by **scanpwn**.\n- 2026-04-14: Fix merged to `develop`.\n- 2026-04-29: 2.41.0 released.\n- 2026-05-07: 2.39.2-LTS and 2.33.8-LTS released.\n\n## Credit\n- **scanpwn** \u2014 identified and reported the query-parameter JWT acceptance and the resulting token-leakage vectors.",
"id": "GHSA-jvp4-q659-95mj",
"modified": "2026-06-09T10:25:32Z",
"published": "2026-05-14T16:33:48Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/portainer/portainer/security/advisories/GHSA-jvp4-q659-95mj"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-44883"
},
{
"type": "PACKAGE",
"url": "https://github.com/portainer/portainer"
},
{
"type": "WEB",
"url": "https://github.com/portainer/portainer/releases/tag/2.33.8"
},
{
"type": "WEB",
"url": "https://github.com/portainer/portainer/releases/tag/2.39.2"
},
{
"type": "WEB",
"url": "https://github.com/portainer/portainer/releases/tag/2.41.0"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:H",
"type": "CVSS_V3"
},
{
"score": "CVSS:4.0/AV:N/AC:H/AT:N/PR:N/UI:P/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N",
"type": "CVSS_V4"
}
],
"summary": "Portainer: JWT accepted in URL query leaks tokens to logs and referers"
}
GHSA-JW5Q-RCM6-45RP
Vulnerability from github – Published: 2025-11-19 21:31 – Updated: 2025-11-19 21:31IBM i 7.2, 7.3, 7.4, 7.5, and 7.6 are impacted by obtaining an information vulnerability in the database plan cache implementation. A user with access to the database plan cache could see information they do not have authority to view.
{
"affected": [],
"aliases": [
"CVE-2025-36371"
],
"database_specific": {
"cwe_ids": [
"CWE-598"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2025-11-19T20:15:52Z",
"severity": "MODERATE"
},
"details": "IBM i 7.2, 7.3, 7.4, 7.5, and 7.6 are impacted by obtaining an information vulnerability in the database plan cache implementation.\u00a0 A user with access to the database plan cache could see information they do not have authority to view.",
"id": "GHSA-jw5q-rcm6-45rp",
"modified": "2025-11-19T21:31:23Z",
"published": "2025-11-19T21:31:23Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2025-36371"
},
{
"type": "WEB",
"url": "https://www.ibm.com/support/pages/node/7251699"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N",
"type": "CVSS_V3"
}
]
}
GHSA-M2H3-RP3M-P73R
Vulnerability from github – Published: 2026-03-13 21:31 – Updated: 2026-03-13 21:31IBM Sterling Partner Engagement Manager 6.2.3.0 through 6.2.3.5 and 6.2.4.0 through 6.2.4.2 could allow an attacker to obtain sensitive information from the query string of an HTTP GET method to process a request which could be obtained using man in the middle techniques.
{
"affected": [],
"aliases": [
"CVE-2025-14811"
],
"database_specific": {
"cwe_ids": [
"CWE-598"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2026-03-13T19:53:50Z",
"severity": "LOW"
},
"details": "IBM Sterling Partner Engagement Manager 6.2.3.0 through 6.2.3.5 and 6.2.4.0 through 6.2.4.2 could allow an attacker to obtain sensitive information from the query string of an HTTP GET method to process a request which could be obtained using man in the middle techniques.",
"id": "GHSA-m2h3-rp3m-p73r",
"modified": "2026-03-13T21:31:45Z",
"published": "2026-03-13T21:31:45Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2025-14811"
},
{
"type": "WEB",
"url": "https://www.ibm.com/support/pages/node/7263391"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:L/I:N/A:N",
"type": "CVSS_V3"
}
]
}
GHSA-M67M-3P5G-CW9J
Vulnerability from github – Published: 2025-04-15 14:20 – Updated: 2025-04-15 21:42Summary
When creating a new component from an existing component that has a source code repository URL specified in settings, this URL is included in the client's URL parameters during the creation process. If, for example, the source code repository URL contains GitHub credentials, the confidential PAT and username are shown in plaintext and get saved into browser history. Moreover, if the request URL is logged, the credentials are written to the logs in plaintext.
The problematic URL in question is of this form:
https://<HOST>/create/component/vcs/?repo=https%3A%2F%2F<GITHUB USERNAME>%3A<GITHUB PAT>%40github.com%2F<REPOSITORY OWNER>%2F<REPOSITORY NAME>.git&project=1&category=&name=<REDACTED>&slug=<REDACTED>&is_glossary=False&vcs=github&source_language=228&license=&source_component=1#existing
If using Weblate official Docker image, nginx logs the URL and the token in plaintext:
nginx stdout | 127.0.0.1 - - [04/Apr/2025:10:46:54 +0000] "GET /create/component/vcs/?repo=https%3A%2F%2F<GITHUB USERNAME>%3A<GITHUB PAT>%40github.com%2F<REPOSITORY OWNER>%2F<REPOSITORY NAME>.git&project=1&category=&name=<REDACTED>&slug=<REDACTED>&is_glossary=False&vcs=github&source_language=228&license=&source_component=1 HTTP/1.1" 200 17625 "<REDACTED>" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:136.0) Gecko/20100101 Firefox/136.0"
Reproduction
- In a project, create a component which has the Repository push URL setting configured with, for example, a GitHub repository URL including a username and a PAT.
- In the same project, create another component using the From existing component option and selecting the previous component as the source. Click Continue.
- Observe that the URL parameter
repoincludes the secret PAT configured in the original components settings. The URL with the token is potentially saved as plaintext in browser history and server logs. - Select a translation file to import and click Continue.
- Observe again the same
repoparameter in the URL.
Impact
- If server logs are compromised, the attacker may be able to gain access to private repositories potentially containing sensitive source code.
- Under common browser settings, the URL containing VCS credentials is saved into browser history. Browser extensions, for example, are often able to read the history and thus offer a realistic attack vector to gain access to the credentials.
{
"affected": [
{
"package": {
"ecosystem": "PyPI",
"name": "weblate"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "5.11"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2025-32021"
],
"database_specific": {
"cwe_ids": [
"CWE-598"
],
"github_reviewed": true,
"github_reviewed_at": "2025-04-15T14:20:38Z",
"nvd_published_at": "2025-04-15T21:16:04Z",
"severity": "LOW"
},
"details": "### Summary\n\nWhen creating a new component from an existing component that has a source code repository URL specified in settings, this URL is included in the client\u0027s URL parameters during the creation process. If, for example, the source code repository URL contains GitHub credentials, the confidential PAT and username are shown in plaintext and get saved into browser history. Moreover, if the request URL is logged, the credentials are written to the logs in plaintext.\n\nThe problematic URL in question is of this form:\n\n```\nhttps://\u003cHOST\u003e/create/component/vcs/?repo=https%3A%2F%2F\u003cGITHUB USERNAME\u003e%3A\u003cGITHUB PAT\u003e%40github.com%2F\u003cREPOSITORY OWNER\u003e%2F\u003cREPOSITORY NAME\u003e.git\u0026project=1\u0026category=\u0026name=\u003cREDACTED\u003e\u0026slug=\u003cREDACTED\u003e\u0026is_glossary=False\u0026vcs=github\u0026source_language=228\u0026license=\u0026source_component=1#existing\n```\n\nIf using Weblate official Docker image, nginx logs the URL and the token in plaintext:\n\n```\nnginx stdout | 127.0.0.1 - - [04/Apr/2025:10:46:54 +0000] \"GET /create/component/vcs/?repo=https%3A%2F%2F\u003cGITHUB USERNAME\u003e%3A\u003cGITHUB PAT\u003e%40github.com%2F\u003cREPOSITORY OWNER\u003e%2F\u003cREPOSITORY NAME\u003e.git\u0026project=1\u0026category=\u0026name=\u003cREDACTED\u003e\u0026slug=\u003cREDACTED\u003e\u0026is_glossary=False\u0026vcs=github\u0026source_language=228\u0026license=\u0026source_component=1 HTTP/1.1\" 200 17625 \"\u003cREDACTED\u003e\" \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:136.0) Gecko/20100101 Firefox/136.0\"\n```\n\n### Reproduction\n\n1. In a project, create a component which has the _Repository push URL_ setting configured with, for example, a GitHub repository URL including a username and a PAT.\n2. In the same project, create another component using the _From existing component_ option and selecting the previous component as the source. Click _Continue_.\n3. Observe that the URL parameter `repo` includes the secret PAT configured in the original components settings. The URL with the token is potentially saved as plaintext in browser history and server logs.\n4. Select a translation file to import and click _Continue_.\n5. Observe again the same `repo` parameter in the URL.\n\n### Impact\n\n- If server logs are compromised, the attacker may be able to gain access to private repositories potentially containing sensitive source code.\n- Under common browser settings, the URL containing VCS credentials is saved into browser history. Browser extensions, for example, are often able to read the history and thus offer a realistic attack vector to gain access to the credentials.",
"id": "GHSA-m67m-3p5g-cw9j",
"modified": "2025-04-15T21:42:20Z",
"published": "2025-04-15T14:20:38Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/WeblateOrg/weblate/security/advisories/GHSA-m67m-3p5g-cw9j"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2025-32021"
},
{
"type": "PACKAGE",
"url": "https://github.com/WeblateOrg/weblate"
},
{
"type": "WEB",
"url": "https://github.com/WeblateOrg/weblate/releases/tag/weblate-5.11"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:H/PR:H/UI:N/S:U/C:L/I:N/A:N",
"type": "CVSS_V3"
}
],
"summary": "VCS credentials included in URL parameters are potentially logged and saved into browser history as plaintext"
}
GHSA-MRQC-3276-74F8
Vulnerability from github – Published: 2026-03-24 19:33 – Updated: 2026-03-27 21:18Summary
PinchTab v0.7.8 through v0.8.3 accepted the API token from a token URL query parameter in addition to the Authorization header. When a valid API credential is sent in the URL, it can be exposed through request URIs recorded by intermediaries or client-side tooling, such as reverse proxy access logs, browser history, shell history, clipboard history, and tracing systems that capture full URLs.
This issue is an unsafe credential transport pattern rather than a direct authentication bypass. It only affects deployments where a token is configured and a client actually uses the query-parameter form. PinchTab's security guidance already recommended Authorization: Bearer <token>, but v0.8.3 still accepted ?token= and included first-party flows that generated and consumed URLs containing the token.
This was addressed in v0.8.4 by removing query-string token authentication and requiring safer header- or session-based authentication flows.
Details
Issue 1 — Query-string token accepted in v0.7.8 through v0.8.3 (internal/handlers/middleware.go):
The v0.8.3 authentication middleware accepted credentials from the URL query string:
// internal/handlers/middleware.go — v0.8.3
auth := r.Header.Get("Authorization")
qToken := r.URL.Query().Get("token")
if auth == "" && qToken == "" {
web.ErrorCode(w, 401, "missing_token", "unauthorized", false, nil)
return
}
provided := strings.TrimPrefix(auth, "Bearer ")
if provided == auth {
if qToken != "" {
provided = qToken
} else {
provided = auth
}
}
if subtle.ConstantTimeCompare([]byte(provided), []byte(cfg.Token)) != 1 {
web.ErrorCode(w, 401, "bad_token", "unauthorized", false, nil)
return
}
This means any client sending GET /health?token=<secret> in v0.8.3 would authenticate successfully without using the Authorization header. I verified the same query-token auth pattern is present in the historical tag range starting at v0.7.8, and it is removed in v0.8.4.
Issue 2 — First-party setup and dashboard flows in v0.8.3 generated and consumed ?token= URLs:
The v0.8.3 setup flow generated dashboard URLs containing the token in the query string:
// cmd/pinchtab/cmd_wizard.go — v0.8.3
func dashboardURL(cfg *config.FileConfig, path string) string {
host := orDefault(cfg.Server.Bind, "127.0.0.1")
port := orDefault(cfg.Server.Port, "9867")
url := fmt.Sprintf("http://%s:%s%s", host, port, path)
if cfg.Server.Token != "" {
url += "?token=" + cfg.Server.Token
}
return url
}
The v0.8.3 dashboard frontend also supported one-click login from that same query-string token:
// dashboard/src/App.tsx — v0.8.3
const params = new URLSearchParams(window.location.search);
const urlToken = params.get("token");
if (urlToken) {
setStoredAuthToken(urlToken);
clean.searchParams.delete("token");
window.history.replaceState({}, "", clean.pathname + clean.hash);
window.location.reload();
}
That combination materially increased the chance that users would open, copy, paste, bookmark, or log URLs containing live credentials before the token was scrubbed from the visible address bar.
Issue 3 — Exposure depends on surrounding systems recording the URL:
PinchTab's own request logger records r.URL.Path, not the full raw query string, so the leak is not primarily through PinchTab's structured application log. The risk comes from surrounding systems or client tooling that record the full request URI, such as:
- reverse proxies and load balancers
- browser history or bookmarks
- shell history containing full
curlcommands - clipboard or terminal history when the wizard prints and copies a tokenized URL
- tracing or monitoring systems that capture full request URLs
PoC
Step 1 — Confirm auth is required
curl -i http://localhost:9867/health
Expected in token-protected affected deployments:
HTTP/1.1 401 Unauthorized
Step 2 — Authenticate using the vulnerable query-parameter pattern
curl -i "http://localhost:9867/health?token=supersecrettoken"
Expected:
HTTP/1.1 200 OK
This demonstrates that the token is accepted from the URL.
Step 3 — Observe the exposure vector If the request traverses a system that records the full URI, the token may appear in logs or local history, for example:
GET /health?token=supersecrettoken HTTP/1.1
In v0.8.3, a first-party reproduction path also exists without any external proxy: run the setup wizard, copy the printed dashboard URL containing ?token=..., and note that the live credential is now present in clipboard history and any place that URL is pasted.
Impact
- Exposure of a valid API token through unsafe URL-based transport when a client uses the
?token=authentication form. - Lower barrier for credential compromise where reverse proxies, browser history, shell history, clipboard history, or tracing systems retain full request URIs.
- The
v0.8.3wizard/dashboard flow increased the practical likelihood of this exposure by generating and consuming tokenized URLs as a first-party login pattern. - Practical risk depends on actual use of the query-token pattern; deployments that use only
Authorization: Bearer <token>are not affected by this issue in practice. - This is not a direct authentication bypass. An attacker still needs access to a secondary source that captured the URL containing the token.
Suggested Remediation
- Reject query-string token authentication and accept credentials only through the
Authorizationheader or controlled session mechanisms. - Avoid generating user-facing URLs that contain live credentials.
- Document header-based auth as the only supported non-browser API authentication pattern.
- Recommend token rotation for users who may previously have used query-parameter authentication.
Screenshot Capture
{
"affected": [
{
"package": {
"ecosystem": "Go",
"name": "github.com/pinchtab/pinchtab"
},
"ranges": [
{
"events": [
{
"introduced": "0.7.8"
},
{
"fixed": "0.8.4"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-33620"
],
"database_specific": {
"cwe_ids": [
"CWE-598"
],
"github_reviewed": true,
"github_reviewed_at": "2026-03-24T19:33:23Z",
"nvd_published_at": "2026-03-26T21:17:06Z",
"severity": "MODERATE"
},
"details": "### Summary\nPinchTab `v0.7.8` through `v0.8.3` accepted the API token from a `token` URL query parameter in addition to the `Authorization` header. When a valid API credential is sent in the URL, it can be exposed through request URIs recorded by intermediaries or client-side tooling, such as reverse proxy access logs, browser history, shell history, clipboard history, and tracing systems that capture full URLs.\n\nThis issue is an unsafe credential transport pattern rather than a direct authentication bypass. It only affects deployments where a token is configured and a client actually uses the query-parameter form. PinchTab\u0027s security guidance already recommended `Authorization: Bearer \u003ctoken\u003e`, but `v0.8.3` still accepted `?token=` and included first-party flows that generated and consumed URLs containing the token.\n\nThis was addressed in v0.8.4 by removing query-string token authentication and requiring safer header- or session-based authentication flows.\n\n### Details\n**Issue 1 \u2014 Query-string token accepted in `v0.7.8` through `v0.8.3` (`internal/handlers/middleware.go`):**\nThe `v0.8.3` authentication middleware accepted credentials from the URL query string:\n\n```\n// internal/handlers/middleware.go \u2014 v0.8.3\nauth := r.Header.Get(\"Authorization\")\nqToken := r.URL.Query().Get(\"token\")\n\nif auth == \"\" \u0026\u0026 qToken == \"\" {\n web.ErrorCode(w, 401, \"missing_token\", \"unauthorized\", false, nil)\n return\n}\n\nprovided := strings.TrimPrefix(auth, \"Bearer \")\nif provided == auth {\n if qToken != \"\" {\n provided = qToken\n } else {\n provided = auth\n }\n}\n\nif subtle.ConstantTimeCompare([]byte(provided), []byte(cfg.Token)) != 1 {\n web.ErrorCode(w, 401, \"bad_token\", \"unauthorized\", false, nil)\n return\n}\n```\n\nThis means any client sending `GET /health?token=\u003csecret\u003e` in `v0.8.3` would authenticate successfully without using the `Authorization` header. I verified the same query-token auth pattern is present in the historical tag range starting at `v0.7.8`, and it is removed in `v0.8.4`.\n\n**Issue 2 \u2014 First-party setup and dashboard flows in `v0.8.3` generated and consumed `?token=` URLs:**\nThe `v0.8.3` setup flow generated dashboard URLs containing the token in the query string:\n\n```\n// cmd/pinchtab/cmd_wizard.go \u2014 v0.8.3\nfunc dashboardURL(cfg *config.FileConfig, path string) string {\n host := orDefault(cfg.Server.Bind, \"127.0.0.1\")\n port := orDefault(cfg.Server.Port, \"9867\")\n url := fmt.Sprintf(\"http://%s:%s%s\", host, port, path)\n if cfg.Server.Token != \"\" {\n url += \"?token=\" + cfg.Server.Token\n }\n return url\n}\n```\n\nThe `v0.8.3` dashboard frontend also supported one-click login from that same query-string token:\n\n```\n// dashboard/src/App.tsx \u2014 v0.8.3\nconst params = new URLSearchParams(window.location.search);\nconst urlToken = params.get(\"token\");\nif (urlToken) {\n setStoredAuthToken(urlToken);\n clean.searchParams.delete(\"token\");\n window.history.replaceState({}, \"\", clean.pathname + clean.hash);\n window.location.reload();\n}\n```\n\nThat combination materially increased the chance that users would open, copy, paste, bookmark, or log URLs containing live credentials before the token was scrubbed from the visible address bar.\n\n**Issue 3 \u2014 Exposure depends on surrounding systems recording the URL:**\nPinchTab\u0027s own request logger records `r.URL.Path`, not the full raw query string, so the leak is not primarily through PinchTab\u0027s structured application log. The risk comes from surrounding systems or client tooling that record the full request URI, such as:\n\n1. reverse proxies and load balancers\n2. browser history or bookmarks\n3. shell history containing full `curl` commands\n4. clipboard or terminal history when the wizard prints and copies a tokenized URL\n5. tracing or monitoring systems that capture full request URLs\n\n### PoC\n**Step 1 \u2014 Confirm auth is required**\n\n```bash\ncurl -i http://localhost:9867/health\n```\n\nExpected in token-protected affected deployments:\n\n```http\nHTTP/1.1 401 Unauthorized\n```\n\n**Step 2 \u2014 Authenticate using the vulnerable query-parameter pattern**\n\n```bash\ncurl -i \"http://localhost:9867/health?token=supersecrettoken\"\n```\n\nExpected:\n\n```http\nHTTP/1.1 200 OK\n```\n\nThis demonstrates that the token is accepted from the URL.\n\n**Step 3 \u2014 Observe the exposure vector**\nIf the request traverses a system that records the full URI, the token may appear in logs or local history, for example:\n\n```text\nGET /health?token=supersecrettoken HTTP/1.1\n```\n\nIn `v0.8.3`, a first-party reproduction path also exists without any external proxy: run the setup wizard, copy the printed dashboard URL containing `?token=...`, and note that the live credential is now present in clipboard history and any place that URL is pasted.\n\n### Impact\n1. Exposure of a valid API token through unsafe URL-based transport when a client uses the `?token=` authentication form.\n2. Lower barrier for credential compromise where reverse proxies, browser history, shell history, clipboard history, or tracing systems retain full request URIs.\n3. The `v0.8.3` wizard/dashboard flow increased the practical likelihood of this exposure by generating and consuming tokenized URLs as a first-party login pattern.\n4. Practical risk depends on actual use of the query-token pattern; deployments that use only `Authorization: Bearer \u003ctoken\u003e` are not affected by this issue in practice.\n5. This is not a direct authentication bypass. An attacker still needs access to a secondary source that captured the URL containing the token.\n\n### Suggested Remediation\n1. Reject query-string token authentication and accept credentials only through the `Authorization` header or controlled session mechanisms.\n2. Avoid generating user-facing URLs that contain live credentials.\n3. Document header-based auth as the only supported non-browser API authentication pattern.\n4. Recommend token rotation for users who may previously have used query-parameter authentication.\n\n**Screenshot Capture**\n\u003cimg width=\"1162\" height=\"164\" alt=\"\u0e20\u0e32\u0e1e\u0e16\u0e48\u0e32\u0e22\u0e2b\u0e19\u0e49\u0e32\u0e08\u0e2d 2569-03-18 \u0e40\u0e27\u0e25\u0e32 12 46 08\" src=\"https://github.com/user-attachments/assets/e68b4469-dafd-400d-a6e1-f74d368cc8ac\" /\u003e",
"id": "GHSA-mrqc-3276-74f8",
"modified": "2026-03-27T21:18:50Z",
"published": "2026-03-24T19:33:23Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/pinchtab/pinchtab/security/advisories/GHSA-mrqc-3276-74f8"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-33620"
},
{
"type": "PACKAGE",
"url": "https://github.com/pinchtab/pinchtab"
},
{
"type": "WEB",
"url": "https://github.com/pinchtab/pinchtab/releases/tag/v0.8.4"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:L/I:N/A:N",
"type": "CVSS_V3"
}
],
"summary": "PinchTab: API Bearer Token Exposed in URL Query Parameter via Server Logs and Intermediary Systems"
}
GHSA-MXW5-PQ7X-P39X
Vulnerability from github – Published: 2025-02-14 00:30 – Updated: 2025-02-14 00:30The Mojave Inverter uses the GET method for sensitive information.
{
"affected": [],
"aliases": [
"CVE-2025-26473"
],
"database_specific": {
"cwe_ids": [
"CWE-598"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2025-02-13T22:15:13Z",
"severity": "HIGH"
},
"details": "The Mojave Inverter uses the GET method for sensitive information.",
"id": "GHSA-mxw5-pq7x-p39x",
"modified": "2025-02-14T00:30:44Z",
"published": "2025-02-14T00:30:44Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2025-26473"
},
{
"type": "WEB",
"url": "https://old.outbackpower.com/about-outback/contact/contact-us"
},
{
"type": "WEB",
"url": "https://www.cisa.gov/news-events/ics-advisories/icsa-25-044-17"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N",
"type": "CVSS_V3"
},
{
"score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/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",
"type": "CVSS_V4"
}
]
}
GHSA-P626-9V99-XC4X
Vulnerability from github – Published: 2025-01-04 03:33 – Updated: 2025-01-06 18:31An issue was discovered in Optimizely Configured Commerce before 5.2.2408. A medium-severity issue exists in requests for resources where the session token is submitted as a URL parameter. This exposes information about the authenticated session, which can be leveraged for session hijacking.
{
"affected": [],
"aliases": [
"CVE-2025-22387"
],
"database_specific": {
"cwe_ids": [
"CWE-598"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2025-01-04T02:15:07Z",
"severity": "HIGH"
},
"details": "An issue was discovered in Optimizely Configured Commerce before 5.2.2408. A medium-severity issue exists in requests for resources where the session token is submitted as a URL parameter. This exposes information about the authenticated session, which can be leveraged for session hijacking.",
"id": "GHSA-p626-9v99-xc4x",
"modified": "2025-01-06T18:31:02Z",
"published": "2025-01-04T03:33:08Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2025-22387"
},
{
"type": "WEB",
"url": "https://support.optimizely.com/hc/en-us/articles/32695551034893-Configured-Commerce-Security-Advisory-COM-2024-06"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N",
"type": "CVSS_V3"
}
]
}
GHSA-PF27-23G4-7WJJ
Vulnerability from github – Published: 2025-03-04 21:30 – Updated: 2025-03-21 18:31Maharashtra State Electricity Distribution Company Limited Mahavitran IOS Application 16.1 application till version 16.1 communicates using the GET method to process requests that contain sensitive information such as user account name and password, which can expose that information through the browser's history, referrers, web logs, and other sources.
{
"affected": [],
"aliases": [
"CVE-2021-41719"
],
"database_specific": {
"cwe_ids": [
"CWE-598"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2025-03-04T21:15:11Z",
"severity": "HIGH"
},
"details": "Maharashtra State Electricity Distribution Company Limited Mahavitran IOS Application 16.1 application till version 16.1 communicates using the GET method to process requests that contain sensitive information such as user account name and password, which can expose that information through the browser\u0027s history, referrers, web logs, and other sources.",
"id": "GHSA-pf27-23g4-7wjj",
"modified": "2025-03-21T18:31:34Z",
"published": "2025-03-04T21:30:57Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2021-41719"
},
{
"type": "WEB",
"url": "https://cvewalkthrough.com/cve-2021-41719-mseb-ios-application-sensitive-information-exposure"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N",
"type": "CVSS_V3"
}
]
}
Mitigation
When sending sensitive information, only include it in the request body or request headers instead of the query string. This may require avoiding use of GET requests.
No CAPEC attack patterns related to this CWE.