Skip to content

Stop dereferencing a null Errors list on unexpected response bodies - #69

Open
Pichatorn-A4K wants to merge 1 commit into
Keyfactor:mainfrom
Pichatorn-A4K:fix/error-parsing-nre
Open

Stop dereferencing a null Errors list on unexpected response bodies#69
Pichatorn-A4K wants to merge 1 commit into
Keyfactor:mainfrom
Pichatorn-A4K:fix/error-parsing-nre

Conversation

@Pichatorn-A4K

Copy link
Copy Markdown

Every caller in CertCentralClient did

Errors errors = JsonConvert.DeserializeObject<Errors>(response.Response);
x.Errors = errors.errors;

which produces a null Errors list, or throws, in three cases that are all
reachable against the live API:

  • an empty body - DeserializeObject("") returns null outright, so
    the assignment itself NREs;
  • a JSON body that is not the {"errors":[...]} envelope - .errors is null.
    GET /services/v2/account/metadata answers literally {} on an account with
    no custom fields;
  • a non-JSON body - a proxy or WAF error page raises JsonReaderException from
    outside Request()'s try/catch, so it does not surface as a CA error at
    all. DigiCert's responses are fronted by a CDN, so an HTML body is a real
    shape on the wire.

Downstream there are eleven Errors[0] / .First() / .Count sites, so any of
those cases became a NullReferenceException instead of a diagnosable message.

ParseErrors() never returns null and never throws, and labels which of the
three cases occurred. CertCentralResponse also carries the HTTP status now,
so the message can name it - previously 4xx and 5xx were indistinguishable
to every caller.

Found during a pre-engagement audit of the shipped 2.4.1 net8.0 assembly; verified by building and running the change against a fake client offline. Companion PRs from the same audit: #65, #66, #67.

🤖 Generated with Claude Code

Every caller in CertCentralClient did

    Errors errors = JsonConvert.DeserializeObject<Errors>(response.Response);
    x.Errors = errors.errors;

which produces a null Errors list, or throws, in three cases that are all
reachable against the live API:

* an empty body - DeserializeObject<Errors>("") returns null outright, so
  the assignment itself NREs;
* a JSON body that is not the {"errors":[...]} envelope - .errors is null.
  GET /services/v2/account/metadata answers literally {} on an account with
  no custom fields;
* a non-JSON body - a proxy or WAF error page raises JsonReaderException from
  *outside* Request()'s try/catch, so it does not surface as a CA error at
  all. DigiCert's responses are fronted by a CDN, so an HTML body is a real
  shape on the wire.

Downstream there are eleven Errors[0] / .First() / .Count sites, so any of
those cases became a NullReferenceException instead of a diagnosable message.

ParseErrors() never returns null and never throws, and labels which of the
three cases occurred. CertCentralResponse also carries the HTTP status now,
so the message can name it - previously 4xx and 5xx were indistinguishable
to every caller.
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.

1 participant