Repository navigation
fix(azure): never crash on a null field in an Azure DevOps reply - #1288
Conversation
Part of #1283. Provider tests use these to send their evidence code a realistic reply once per field with that field made null, or a list emptied, and to name the outcome: ok, error or panic, plus which evidence fields came back changed or missing.
Every pointer the SDK hands back can be nil when Azure DevOps sends a field as null or leaves it out, and the evidence code dereferenced them unchecked: 51 of the 188 null variants in the new test panicked, through both `assert pullrequest azure` (V1) and attest (V2). One generic helper, value, now reads every reply pointer and gives the zero value when it is missing; unixTime does the same for timestamps. azureApprovers no longer dereferences Vote, so azureReviews loses its separate nil guard. SDK lists hold structs, so a null item decodes to an empty one. A pull request with no pullRequestId, a commit with no commitId, or a null query result is now an error instead of a panic or a silent drop. A null reviewer is skipped, as a reviewer with no vote always was. The test feeds each reply with each value nulled and asserts the rule rather than a golden file. Part of #1283 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Claude finished @AlexKantor87's task in 1m 46s —— View job Follow-up review — commits
|
# Conflicts: # internal/testHelpers/oddReplies.go # internal/testHelpers/oddReplies_test.go
Follow-up review — commits
|
Snyk fails every branch on CVE-2026-111943, a high-severity flaw in Go's crypto/x509 fixed in 1.26.10; go.mod declared 1.26.7. The Dockerfile built from golang:1.26-alpine3.23, so each build could pull a different toolchain. It now names golang:1.26.10-alpine3.23 by digest. Dependabot can't update a FROM built from ARGs, so the line is literal, and a docker ecosystem entry (golang only) keeps the digest current.
A reviewer who voted but has neither displayName nor uniqueName was counted as " ()". For an approval that records evidence attributed to nobody, which fails open. A change-request vote with no identity is the same unreadable entry, so any counted vote errors, naming the reviewer's index. The check sits where reviewers are fetched, so V1 and V2 share it. Also name a pull request with a nil id the same way in both GetPullRequestCommits errors. Part of #1283. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Dependabot bumps the pinned golang image on its own, and none of the gomod updates touch go.mod's go directive. Snyk reads go.mod, so an image-only bump would leave the next Go stdlib CVE flagged even though the image is fixed. The test makes that bump red until go.mod moves too.
…ring The last commit made a vote from a reviewer with no displayName or uniqueName an error. Deleted accounts come back with no identity, so any PR once approved by someone who has since left would fail attestation for good, with no workaround. Such a reviewer is now left out of the approvers, so it never counts as an approval, and kept in reviews with an empty name, so the record still shows an unknown account reviewed. Part of #1283. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
This branch now includes #1291's branch, so the Go 1.26.10 change clears the Snyk check here. That's why no search: answers no review finding; it brings in #1291's reviewed files unchanged ( |
…283-azure # Conflicts: # .github/dependabot.yml
Follow-up review — commits
|
…uest The last commit kept a reviewer with no identity in reviews with its state, approvals included. Review on the GitLab PR pointed out that policies read reviews, so one counting approvals there would count an approval by nobody. A nameless approval is now left out of reviews as well as approvers; a nameless change request is still kept, since dropping it would read as none given. Part of #1283. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
The SDK decodes a null reviewer as an empty one, so a reply like
[null, {vote: 10}] skipped the null entry with no error. Skipping it could
hide a change request, which is why the other providers fail on an entry
they can't read. A missing id is the only sign of a null reviewer, the same
check we use for pullRequestId and commitId, so it now returns an error.
Part of #1283
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A pull request with no createdBy was recorded with the author " ()", and a commit with no author as " <>". A reviewer with no identity already gave "". One helper, azureIdentity, now formats all three and gives "" when both parts are missing. Part of #1283 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Thanks @mbevc1, both fixed. 1. Null reviewer. Fixed in 9c837a6. A reviewer with no 2. Author as I checked the other PRs for both. A missing commit author was also search: grep -nE 'has no id|azureIdentity(' internal/azure/azure.go verified: sed -n '296,299p;307,312p' internal/azure/azure.go mutation: drop the reviewer id check -> TestPREvidenceOddReplies and TestPREvidenceReviewerWithNoIDFails red (5 cases) |
Part of #1283.
kosli attest pullrequest azureandkosli assert pullrequest azurecrashed when Azure DevOps sent a field as null where the code expected a value. The Azure SDK gives every field as a pointer, and the code read most of them without checking. For now we treat every field as optional (#1284 will decide which fields are required).What changed
valuereturns what a pointer holds, or an empty value when it's nil. It replaces every unchecked read in the V1 path (assert) and the V2 path (attest), including the reviewer vote.unixTimedoes the same for timestamps.pullRequestIdorcommitIdis the only sign. Either now returns an error rather than being recorded as empty.idreturns an error. The SDK turns a null reviewer into an empty one, and skipping it could hide a change request.()or<>.main. Azure may send that for a commit with none, and failing would break attestations that work today.reviewswe keep one only if it requests changes, because dropping it would read as no objection. This is the same rule Bitbucket has onmain.Tests
odd_replies_test.goruns a fake Azure DevOps server that the real SDK talks to. It sends replies through V1 and V2 once per field, with that field made null. It checks there's never a crash, and never an error except a missingpullRequestId,commitIdor reviewerid. Againstmain, 51 cases crash.Not changed
A reviewer with only one of display name and unique name gives text like
Ada (). That's for #1284.Full CLI suite against a local server: 3,849 tests passed.
🤖 Generated with Claude Code