Skip to content

[agent][clientCertAuth] Fix nil pointer dereference on HTTP response in TryDownload#632

Open
rustiqly wants to merge 2 commits intosonic-net:masterfrom
rustiqly:fix/cert-auth-nil-resp
Open

[agent][clientCertAuth] Fix nil pointer dereference on HTTP response in TryDownload#632
rustiqly wants to merge 2 commits intosonic-net:masterfrom
rustiqly:fix/cert-auth-nil-resp

Conversation

@rustiqly
Copy link
Copy Markdown
Contributor

What I did

Fix panic in TryDownload() when http.Get() returns (nil, err).

How I did it

Restructured error handling to check err != nil first and return early before accessing resp. Then defer resp.Body.Close() and check resp.StatusCode separately.

Before: resp.StatusCode accessed in combined check with err, panics when resp is nil.
After: Error checked first, resp only accessed after confirming non-nil.

How to verify it

Call TryDownload() with an unreachable URL — should return false instead of panic.

Which release branch to backport

master

Description for the changelog

Fix nil pointer panic in gNMI CRL download when HTTP request fails.

Fixes: #630

http.Get() can return (nil, err). The previous code checked
resp != nil only for the defer but then accessed resp.StatusCode
in a combined err check, causing a panic when resp is nil.

Restructure: check err first and return early, then defer
resp.Body.Close() and check StatusCode separately.

Fixes: sonic-net#630

Signed-off-by: Rustiqly <rustiqly@users.noreply.github.com>
@mssonicbld
Copy link
Copy Markdown
Contributor

/azp run

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 1 pipeline(s).

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes a panic in the gNMI server’s client certificate CRL download path (TryDownload) by restructuring HTTP error handling to avoid dereferencing a nil *http.Response when http.Get fails.

Changes:

  • Return early on http.Get error before accessing resp.
  • Always defer resp.Body.Close() only after confirming the request succeeded.
  • Improve logging for non-200 HTTP status responses.


if resp != nil {
defer resp.Body.Close()
if err != nil {
Copy link

Copilot AI Mar 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the err != nil early-return path, resp (and resp.Body) may still be non-nil for some net/http failure modes (e.g., redirect-related errors). Returning without closing resp.Body can leak resources. Consider closing the body when resp != nil before returning (guarding resp.Body != nil).

Suggested change
if err != nil {
if err != nil {
if resp != nil && resp.Body != nil {
resp.Body.Close()
}

Copilot uses AI. Check for mistakes.
Comment on lines 160 to +165
glog.Infof("Download CRL start: %s", url)
resp, err := http.Get(url)

if resp != nil {
defer resp.Body.Close()
if err != nil {
glog.Infof("Download CRL: %s failed: %v", url, err)
return false
Copy link

Copilot AI Mar 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

http.Get uses the default client without a timeout; a slow/non-responsive CRL endpoint can block the auth path indefinitely (potential DoS when CRL checking is enabled). Consider using an http.Client with a reasonable timeout or a context with deadline for the request.

Copilot uses AI. Check for mistakes.
http.Get may return a non-nil resp with a non-nil Body even
when err is non-nil (e.g., redirect-related errors). Close
the body before returning to prevent resource leaks.

Signed-off-by: Rustiqly <rustiqly@users.noreply.github.com>
@mssonicbld
Copy link
Copy Markdown
Contributor

/azp run

@rustiqly
Copy link
Copy Markdown
Contributor Author

rustiqly commented Apr 4, 2026

Addressed Copilot review feedback:

  1. resp.Body leak on error path — Fixed in f7e1a93. Now closes resp.Body when resp != nil before returning on the error path. http.Get can return a non-nil response even on error (e.g., redirect failures).

  2. http.Get without timeout — Valid concern, but this is pre-existing behavior outside the scope of this nil-pointer fix. The default client timeout issue affects the entire TryDownload function and should be addressed in a separate PR. Filed as a note for future improvement.

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 1 pipeline(s).

@rustiqly rustiqly requested review from StormLiangMS and yxieca April 6, 2026 16:17
glog.Infof("Download CRL: %s failed: %v", url, err)
return false
}
defer resp.Body.Close()
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. There is no nil check here for resp or resp.Body
  2. If we move this line above line 163, can line163 body be a clean return?

@yxieca
Copy link
Copy Markdown

yxieca commented Apr 10, 2026

@rustiqly please consider adding unit tests.

@rustiqly
Copy link
Copy Markdown
Contributor Author

@yxieca acknowledged, I will work on adding unit tests for this in the next iteration.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[clientCertAuth] Nil pointer dereference on HTTP response when http.Get() fails

4 participants