Conversation
| if len(options.reqHeaders) > 0 && len(options.reqHeaders[0]) != 0 { | ||
| for _, header := range options.headers { | ||
| fmt.Printf("%s \t\t%s\n", "Headers:", header) | ||
| fmt.Printf("%s \t\t%s: %s\n", "Headers:", header.key, header.value) |
Check failure
Code scanning / CodeQL
Clear-text logging of sensitive information High
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI about 1 month ago
To fix the problem, the code should avoid printing potentially sensitive header values in clear text. The general approaches are: (a) omit sensitive headers entirely from logs, (b) mask/obfuscate their values (e.g., keep only prefix, replace rest with ***), or (c) only log header names. The safest and simplest fix that preserves functionality is to keep visibility of which headers are being used while redacting their values when printing configuration.
Concretely, we can change showInfo in cmd/requester.go so that it does not print header.value directly. A good balance is to log header names and a masked version of their values, and to treat well-known sensitive headers (e.g., Authorization, Cookie, Set-Cookie, X-Api-Key, X-API-KEY, Proxy-Authorization) as always fully redacted. For all headers, we can implement a small helper like maskHeaderValue that returns "***" or a partially masked string. This helper will be added in cmd/requester.go just above showInfo, and showInfo’s loop will be updated to call it instead of printing the raw header.value. No behavior outside logging output is changed, and no new external dependencies are needed.
Specifically:
- In
cmd/requester.go, define a helper function such as:
func maskHeaderValue(name, value string) string {
// normalize name
lower := strings.ToLower(strings.TrimSpace(name))
switch lower {
case "authorization", "proxy-authorization", "cookie", "set-cookie", "x-api-key", "x-api-key", "x-auth-token":
return "***"
}
if len(value) <= 4 {
return "***"
}
return value[:2] + "..." + "***"
}(adjusted to the project’s style).
- Modify the loop in
showInfofrom printing%s: %swithheader.valueto usingmaskHeaderValue(header.key, header.value).
This ensures that even if request files contain sensitive headers, they will not be logged in clear text.
| @@ -136,6 +136,23 @@ | ||
| fmt.Printf("%s \t%20s %s\n", code, color.BlueString(resultContentLength), result.line) | ||
| } | ||
|
|
||
| // maskHeaderValue obfuscates potentially sensitive header values before logging. | ||
| // It fully redacts well-known sensitive headers and partially masks others. | ||
| func maskHeaderValue(name, value string) string { | ||
| headerName := strings.ToLower(strings.TrimSpace(name)) | ||
| switch headerName { | ||
| case "authorization", "proxy-authorization", "cookie", "set-cookie", "x-api-key", "x-api-key", "x-auth-token": | ||
| return "***" | ||
| } | ||
| // For non-explicitly sensitive headers, avoid logging the full value. | ||
| trimmed := strings.TrimSpace(value) | ||
| if len(trimmed) <= 4 { | ||
| return "***" | ||
| } | ||
| // Show only a small prefix and mask the rest. | ||
| return trimmed[:2] + "...***" | ||
| } | ||
|
|
||
| // showInfo prints the configuration options used for the scan. | ||
| func showInfo(options RequestOptions) { | ||
| var statusCodeStrings []string | ||
| @@ -148,7 +165,8 @@ | ||
| fmt.Printf("%s \t\t%s\n", "Target:", options.uri) | ||
| if len(options.reqHeaders) > 0 && len(options.reqHeaders[0]) != 0 { | ||
| for _, header := range options.headers { | ||
| fmt.Printf("%s \t\t%s: %s\n", "Headers:", header.key, header.value) | ||
| maskedValue := maskHeaderValue(header.key, header.value) | ||
| fmt.Printf("%s \t\t%s: %s\n", "Headers:", header.key, maskedValue) | ||
| } | ||
| } else { | ||
| fmt.Printf("%s \t\t%s\n", "Headers:", "false") |
| headers = append(headers, header{headerSplit[0], strings.Join(headerSplit[1:], "")}) | ||
| headerSplit := strings.SplitN(_header, ":", 2) | ||
| if len(headerSplit) < 2 { | ||
| log.Printf("Invalid header format: %s\n", _header) |
Check failure
Code scanning / CodeQL
Clear-text logging of sensitive information High
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI about 1 month ago
In general, to fix clear-text logging of sensitive information in this context, avoid logging full header lines (which include both names and values) when they originate from untrusted sources. Instead, log only non-sensitive metadata, such as whether parsing failed and, at most, the header name (without value), or use a redacted version.
In this specific case, the problematic logging is:
if len(headerSplit) < 2 {
log.Printf("Invalid header format: %s\n", _header)
continue
}_header can contain the entire header including its value. To keep functionality unchanged while avoiding leakage:
- Parse out what looks like a header name anyway (best-effort split on
:), but ignore the value completely for logging. - If a plausible name can be extracted, log only that name; otherwise, log a generic message without including user-controlled content.
- Keep the
continueso that malformed headers are still skipped.
Concretely, within setupRequestOptions in cmd/requester.go, replace the log line to avoid printing _header, and optionally attempt to log only the trimmed header name if present. No new imports or types are required.
| @@ -879,7 +879,13 @@ | ||
| for _, _header := range reqHeaders { | ||
| headerSplit := strings.SplitN(_header, ":", 2) | ||
| if len(headerSplit) < 2 { | ||
| log.Printf("Invalid header format: %s\n", _header) | ||
| // Avoid logging potentially sensitive header values; log only the header name when possible. | ||
| headerName := strings.TrimSpace(headerSplit[0]) | ||
| if headerName != "" { | ||
| log.Printf("Invalid header format for header name: %s\n", headerName) | ||
| } else { | ||
| log.Printf("Invalid header format encountered; header name is empty\n") | ||
| } | ||
| continue | ||
| } | ||
| headers = append(headers, header{strings.TrimSpace(headerSplit[0]), strings.TrimSpace(headerSplit[1])}) |
Changes
Testing