Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hide Authorization header value #1127

Merged
merged 10 commits into from
Nov 28, 2023
Merged
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Changed
- Server errors are no longer serialized back to the client since this might leak sensitive
information through the error message. ([#1126])
- When `show`ing `HTTP.Request` and `HTTP.Response` the values for the headers
`Authorization`, `Proxy-Authorization`, `Cookie`, and `Set-Cookie` are masked with `*`s
since they might include sensitive information. ([#1127])
### Fixed
- Restrict `HTTP.isredirect` to arguments of integer types. ([#1117])
- Fix `HTTP.getcookies` error when key doesn't exist. ([#1119])
Expand Down
11 changes: 10 additions & 1 deletion src/Messages.jl
Original file line number Diff line number Diff line change
Expand Up @@ -609,7 +609,16 @@ function Base.show(io::IO, m::Message)
end
println(io, typeof(m), ":")
println(io, "\"\"\"")
writeheaders(io, m)

# Mask the following (potentially) sensitive headers with "******":
# - Authorization
# - Proxy-Authorization
# - Cookie
# - Set-Cookie
header_str = sprint(writeheaders, m)
header_str = replace(header_str, r"(*CRLF)^((?>(?>Proxy-)?Authorization|(?>Set-)?Cookie): ).+$"mi => s"\1******")
write(io, header_str)

summary = bodysummary(m.body)
validsummary = isvalidstr(summary)
validsummary && write(io, summary)
Expand Down
14 changes: 14 additions & 0 deletions test/messages.jl
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,20 @@ using JSON
# https://github.com/JuliaWeb/HTTP.jl/issues/828
# don't include empty headers in request when writing
@test repr(Request("GET", "/", ["Accept" => ""])) == "Request:\n\"\"\"\nGET / HTTP/1.1\r\n\r\n\"\"\""

# Test that sensitive header values are masked when `show`ing HTTP.Request and HTTP.Response
for H in ["Authorization", "Proxy-Authorization", "Cookie", "Set-Cookie"], h in (lowercase(H), H)
req = HTTP.Request("GET", "https://xyz.com", [h => "secret", "User-Agent" => "HTTP.jl"])
req_str = sprint(show, req)
@test !occursin("secret", req_str)
@test occursin("$h: ******", req_str)
@test occursin("HTTP.jl", req_str)
resp = HTTP.Response(200, [h => "secret", "Server" => "HTTP.jl"])
resp_str = sprint(show, resp)
@test !occursin("secret", resp_str)
@test occursin("$h: ******", req_str)
@test occursin("HTTP.jl", resp_str)
end
end

@testset "queryparams" begin
Expand Down
Loading