Fix memory-safety and correctness bugs surfaced by Coverity audit (part 2) - #22267
Merged
Conversation
Coverity CID 501623 (CHECKED_RETURN): `send_curl_request()` read `public.pem` into a fixed buffer without reserving space for a trailing NUL, then passed it through the JSON string path as a C string. Read at most `sizeof(public_key) - 1` bytes, keep the byte count, and terminate the buffer explicitly before use.
Coverity CID 501624 (FORWARD_NULL): guard the 422 errorMsgKey comparisons in send_curl_request() when the claim server omits or mis-types errorMsgKey. Fall back to the existing generic 422 failure message instead of dereferencing a NULL string.
The claim flow buffered the full HTTP response body with no upper bound, which allowed a hostile endpoint to force unbounded growth during the curl transfer. Cap the response at 10 MiB in the write callback and configure libcurl to reject oversized responses early when the size is advertised.
Coverity CID 501625 (CHECKED_RETURN): stop ignoring curl_easy_setopt() errors when preparing claim requests. Abort the request setup with a clear failure reason instead of continuing with partially applied curl options such as a rejected proxy configuration.
curl_slist_append() can return NULL on allocation failure. Keep the original list pointer, assign the new list to a temporary, and only commit it once the append succeeded. Fail the request cleanly with can_retry=false if the header cannot be appended, so the claim request never proceeds without its Content-Type header.
`size * nmemb` can theoretically overflow size_t. Treat overflow as a too-large response (same as the existing size-limit path): flag it on the response buffer and return 0 so libcurl aborts the transfer.
Coverity CID 410065 (MISSING_LOCK): claim_id_get_uuid() copied the shared claim UUID through a function-local static and returned it after dropping claim.spinlock. Use a stack-local ND_UUID so concurrent readers do not race on the helper's scratch storage.
stelfrag
marked this pull request as ready for review
April 24, 2026 16:39
stelfrag
marked this pull request as draft
April 24, 2026 16:39
Contributor
There was a problem hiding this comment.
No issues found across 2 files
Confidence score: 5/5
- Automated review surfaced no issues in the provided summaries.
- No files require special attention.
Architecture diagram
sequenceDiagram
participant Node as Netdata Node
participant Claim as Claiming Service
participant FS as Local Filesystem
participant CURL as libcurl
participant Cloud as Cloud API (PUT /claim)
Note over Claim, Cloud: Node Claiming Flow with Hardened Safety
Node->>Claim: Initiate Claim
Claim->>Claim: CHANGED: claim_id_get_uuid()<br/>(Now uses stack-local UUID to avoid races)
Claim->>FS: Open public.pem
FS-->>Claim: Key data
Claim->>Claim: CHANGED: Read max sizeof-1 and NUL-terminate
Claim->>CURL: NEW: Initialize request with strict checks
alt Header or Option Setup Fails
Claim->>Claim: NEW: cleanup_curl_request_failure()<br/>(Set can_retry = false)
else Success
Claim->>CURL: Set CURL_SETOPT (URL, Auth, Headers)
Claim->>CURL: NEW: Set CURLOPT_MAXFILESIZE_LARGE (10 MiB)
end
Claim->>Cloud: PUT claim request
loop While Data Received
Cloud-->>CURL: Data chunk
CURL->>Claim: response_write_callback()
alt NEW: Size > 10 MiB OR integer overflow
Claim-->>CURL: Return 0 (Abort)
Note right of Claim: response->too_large = true
else Within limits
Claim->>Claim: buffer_memcat()
Claim-->>CURL: Return real_size
end
end
alt Transfer Success (2xx)
CURL-->>Claim: CURLE_OK
Claim->>Node: Claim Successful
else Transfer Failure or Overflow
CURL-->>Claim: CURLE_FILESIZE_EXCEEDED or other error
alt NEW: Response too large
Claim->>Claim: Set can_retry = false
else Transient Network Error
Claim->>Claim: Set can_retry = true
end
Claim->>Node: Failure (with detailed reason)
end
opt HTTP 422 Unprocessable Entity
Claim->>Claim: CHANGED: Parse JSON errorMsgKey
Note right of Claim: Fallback to HTTP status if key missing
end
Contributor
There was a problem hiding this comment.
Pull request overview
Hardens the Netdata Cloud claiming path by addressing memory-safety and correctness issues in the claim HTTP flow and claim UUID retrieval.
Changes:
- Make
claim_id_get_uuid()return a stack-local UUID copy (avoids shared static state). - Add bounded response buffering (10 MiB cap) with overflow protection in the libcurl write callback.
- Fail fast on libcurl request setup errors (setopt/slist) and improve handling of missing
errorMsgKeyin HTTP 422 responses; safely NUL-terminatepublic.pemreads.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
src/claim/claim_id.c |
Removes a function-local static UUID temporary to avoid shared state and keep the getter purely stack-local. |
src/claim/claim-with-api.c |
Adds response-size limits/overflow guards, checks curl setup failures, safely terminates public key reads, and hardens 422 error parsing. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
stelfrag
marked this pull request as ready for review
April 24, 2026 16:59
thiagoftsm
approved these changes
Apr 24, 2026
thiagoftsm
left a comment
Contributor
There was a problem hiding this comment.
No issue found during runtime (Coredump or communication with Cloud). LGTM!
This was referenced Apr 27, 2026
Merged
Ferroin
pushed a commit
that referenced
this pull request
Jul 15, 2026
…rt 2) (#22267) * claim: terminate public key read buffer Coverity CID 501623 (CHECKED_RETURN): `send_curl_request()` read `public.pem` into a fixed buffer without reserving space for a trailing NUL, then passed it through the JSON string path as a C string. Read at most `sizeof(public_key) - 1` bytes, keep the byte count, and terminate the buffer explicitly before use. * claim: guard missing 422 errorMsgKey Coverity CID 501624 (FORWARD_NULL): guard the 422 errorMsgKey comparisons in send_curl_request() when the claim server omits or mis-types errorMsgKey. Fall back to the existing generic 422 failure message instead of dereferencing a NULL string. * claim: cap claim response body size The claim flow buffered the full HTTP response body with no upper bound, which allowed a hostile endpoint to force unbounded growth during the curl transfer. Cap the response at 10 MiB in the write callback and configure libcurl to reject oversized responses early when the size is advertised. * claim: handle curl option setup failures Coverity CID 501625 (CHECKED_RETURN): stop ignoring curl_easy_setopt() errors when preparing claim requests. Abort the request setup with a clear failure reason instead of continuing with partially applied curl options such as a rejected proxy configuration. * claim: check curl_slist_append return value curl_slist_append() can return NULL on allocation failure. Keep the original list pointer, assign the new list to a temporary, and only commit it once the append succeeded. Fail the request cleanly with can_retry=false if the header cannot be appended, so the claim request never proceeds without its Content-Type header. * claim: guard size * nmemb overflow in response write callback `size * nmemb` can theoretically overflow size_t. Treat overflow as a too-large response (same as the existing size-limit path): flag it on the response buffer and return 0 so libcurl aborts the transfer. * claim: remove shared uuid scratch from getter Coverity CID 410065 (MISSING_LOCK): claim_id_get_uuid() copied the shared claim UUID through a function-local static and returned it after dropping claim.spinlock. Use a stack-local ND_UUID so concurrent readers do not race on the helper's scratch storage. --------- Co-authored-by: Costa Tsaousis <costa@netdata.cloud> (cherry picked from commit 8b118b6)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Summary
Summary by cubic
Hardened the claim HTTP flow and UUID getter by fixing memory-safety, overflow, and error-handling issues from a Coverity audit. This prevents oversized responses, avoids NULL/overflow bugs, and improves retry behavior.
curl_easy_setopt()errors and oncurl_slist_append()allocation failure; clean up and set can_retry=false.public.pemsafely: read at most sizeof-1, track bytes read, and NUL-terminate.errorMsgKeyis missing; fall back to a generic message using the HTTP status.claim_id_get_uuid()to avoid races; use a stack-local UUID.Written for commit 9d5f13f. Summary will update on new commits.