VNX-598: Credential or secret sent in a GET query string
Reports URLs that carry an interpolated password, API key, client secret or token as a query parameter (including ?key= given a variable named for an API key), request helpers given such a key in their params object, and HTML forms that submit a password field by GET.
| Field | Value |
|---|---|
| Rule ID | VNX-598 |
| Severity | Medium |
| SARIF level | warning |
| Kind | sast |
| Languages | Go, Java, JavaScript / TypeScript, PHP, Python, HTML |
| CWE | CWE-598 |
| CAPEC | CAPEC-66 |
| ATT&CK | T1190 |
| CWSS vector | CWSS:1.0/TI:M/AP:A/AL:A/IC:N/FC:LT/RP:N/RL:A/AV:I/AS:N/IN:A/SC:A/BI:M/DI:H/EX:M/EC:N/P:C |
| Tags | sensitive-data-in-url credentials logging cwe-598 |
| Source | internal/sast/rules/vnx-598.rego |
Overview
VNX-598 maps to CWE-598: Use of GET Request Method With Sensitive Query Strings. A query string is written to web server and proxy access logs, kept in browser history and sent onward in the Referer header.
The rule reports:
- a URL built in code whose query (the line opens one with
?name=) carries a parameter namedpassword,passwd,pwd,pass,passphrase,secret,client_secret,api_key,apikey,api-key,access_token,auth_token,token,session_id,sessionidorssn, whose value is interpolated (concatenation, f-string or template-literal placeholder,%s/%v, PHP$variable); - a GET helper (
requests.get,axios.get,http.get) given such a key in itsparamsobject; - an HTML or template
<form>that submits a password input by GET:method="get", or no method at all (GET is the default) in.html,.htm,.php,.jsp,.ejs,.hbs,.twig,.jinjaand.erbfiles.
It does not report form-encoded POST bodies (grant_type=password&password=...), credentials in headers or POST data, constant example URLs (?api_key=YOUR_API_KEY), lookalike parameters (pageToken, next_token, show_password_field), otpauth:// provisioning URIs, forms submitted by POST or by a script handler (onsubmit, ngSubmit, Angular bindings, @submit), or comments.
What Gets Flagged
url = f"{base}/login?user={username}&password={password}" # FLAGGED
requests.get("https://api.example.com/v1/items?api_key=" + api_key) # FLAGGED
requests.get(url, params={"q": q, "access_token": token}) # FLAGGED
# NOT FLAGGED
requests.get(url, headers={"X-Api-Key": api_key})
requests.post(base + "/token", data="grant_type=password&password=" + password)
<form action="/session" method="get"> <!-- FLAGGED: has a password input -->
<input type="password" name="pw">
</form>
Remediation
- Send credentials in a POST body or an
Authorizationheader, never in the URL. - Give every login form
method="post". - Where an API only accepts a key in the query string, keep the URL out of logs and rotate the key.
References
- CWE-598: Use of GET Request Method With Sensitive Query Strings
- OWASP: Information exposure through query strings in URL
Suppressing this rule
Put a nosec comment on the line, or on line 1 to cover the whole file. Use the comment marker of the file’s language (#, //, -- or ;):
# nosec vnx-598
// nosec vnx-598
Or record an ignore rule: vulnetix ignore add --rule vnx-598 --reason "...". See Suppressing findings.