Skip to content

feat(xmldsig): build x509 certificate chains#61

Open
polaz wants to merge 5 commits into
mainfrom
feat/#60-x509-chain-building
Open

feat(xmldsig): build x509 certificate chains#61
polaz wants to merge 5 commits into
mainfrom
feat/#60-x509-chain-building

Conversation

@polaz

@polaz polaz commented Jun 22, 2026

Copy link
Copy Markdown
Member

Summary

  • Implement P2-004 certificate chain building for parsed X509Data certificates.
  • Add certificate serial metadata and ordered chain indexes starting at the selected signing certificate.
  • Select signing certificate via X509SubjectName, X509IssuerSerial, or X509SKI hints, with deterministic ambiguity errors.
  • Checked dependency updates in this PR scope: cargo update produced no tracked diff because Cargo.lock is untracked, but the workspace was verified against the resolved updated graph.

Testing

  • cargo fmt -- --check
  • cargo check --workspace
  • cargo clippy --workspace --all-targets -- -D warnings
  • cargo nextest run --workspace
  • cargo test --doc --workspace
  • cargo build --workspace

Closes #60

- Order embedded X509Data certificates from signing cert to issuer chain
- Select signing cert by SubjectName, IssuerSerial, or SKI hints when present
- Preserve serial metadata for later chain verification
- Add regression coverage for unordered chains and ambiguity

Dependency update check: cargo update produced no tracked diff because Cargo.lock is untracked; workspace verified against the resolved updated graph.

Closes #60
@coderabbitai

coderabbitai Bot commented Jun 22, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@polaz, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 38 minutes and 26 seconds. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits.

🚦 How do rate limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: a46877b0-a67e-4ef7-bf40-f35fea713f45

📥 Commits

Reviewing files that changed from the base of the PR and between 5ca0875 and 60abb57.

📒 Files selected for processing (1)
  • src/xmldsig/parse.rs
📝 Walkthrough

Walkthrough

The change adds ordered X.509 certificate chain construction to src/xmldsig/parse.rs. X509DataInfo gains certificate_chain: Vec<usize> and ParsedX509Certificate gains serial_number: Vec<u8> plus serial_number_hex: String. New helpers select a signing certificate, build the chain, and update tests and fixtures.

Changes

X.509 Certificate Chain Building

Layer / File(s) Summary
Data shape: new fields on X509DataInfo and ParsedX509Certificate
src/xmldsig/parse.rs
Introduces MAX_X509_CHAIN_DEPTH, adds certificate_chain: Vec<usize> to X509DataInfo, and adds serial_number: Vec<u8> plus serial_number_hex: String to ParsedX509Certificate.
Chain building and signing cert selection
src/xmldsig/parse.rs
Updates parse_x509_data_dispatch to populate certificate_chain using build_x509_certificate_chain and select_x509_signing_certificate, with depth limiting, cycle detection, and ambiguity rejection.
Tests and fixture infrastructure
src/xmldsig/parse.rs
Reworks PEM fixture loading via fixture_cert_base64; updates X509Data assertions; adds tests for chain ordering, issuer-serial selection, decimal serial conversion, ambiguity rejection, depth-exceeded rejection, and canonical serial hex formatting.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 47.62% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title succinctly matches the main change: building X.509 certificate chains.
Description check ✅ Passed The description matches the implemented chain-building, hint selection, metadata, and testing work.
Linked Issues check ✅ Passed The changes address #60 with ordered chains, subject/issuer/SKI selection, bounded depth, and deterministic ambiguity handling plus tests.
Out of Scope Changes check ✅ Passed The diff stays focused on X.509 parsing/chain logic and test fixtures; no unrelated code areas are introduced.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/#60-x509-chain-building

Comment @coderabbitai help to get the list of available commands.

@greptile-apps

greptile-apps Bot commented Jun 22, 2026

Copy link
Copy Markdown

Greptile Summary

This PR adds X.509 certificate chain building for XMLDSig X509Data. The main changes are:

  • Builds an ordered certificate chain starting at the selected signing certificate.
  • Adds parsed certificate serial metadata in raw bytes and canonical hex form.
  • Selects the signing certificate from SubjectName, IssuerSerial, or SKI hints.
  • Returns deterministic errors for ambiguous, malformed, or unmatched lookup identifiers.

Confidence Score: 5/5

The changed XMLDSig certificate-chain parsing logic appears merge-safe.

The implementation is narrowly scoped to X.509 metadata extraction, signing-certificate selection, deterministic ambiguity handling, and chain ordering, with repository checks reported across formatting, build, lint, documentation tests, and test suites.

T-Rex T-Rex Logs

What T-Rex did

  • The base revision was probed and it failed to compile because X509DataInfo did not expose a public certificate_chain field.
  • The head revision was probed and produced a parse result with certificates_len=3 and certificate_chain=[2, 1, 0], with the assertion passing (per the after-state evidence).

View all artifacts

T-Rex Ran code and verified through T-Rex

Reviews (5): Last reviewed commit: "fix(xmldsig): validate x509 lookup hints" | Re-trigger Greptile

Comment thread src/xmldsig/parse.rs Outdated
Comment thread src/xmldsig/parse.rs
Comment thread src/xmldsig/parse.rs Outdated
@polaz

polaz commented Jun 24, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 24, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/xmldsig/parse.rs`:
- Around line 681-684: The issuer-serial matching in the certificate scan is
repeatedly calling x509_serial_decimal_to_hex inside the any() predicate, which
is unnecessary work. Refactor the logic around the issuer_serials check in
parse.rs so the decimal-to-hex normalization is computed once per issuer-serial
entry before comparing against cert.serial_number_hex, then reuse that
precomputed value in the closure. Keep the existing matching behavior in the
certificate × issuer-serial scan, but move the conversion out of the inner
comparison to avoid repeated conversions.
- Around line 696-705: The X509Data candidate selection in parse_certificates
should not fall through when lookup hints are present but produce no matches; in
the match on candidates.as_slice(), treat the empty case as an invalid lookup
instead of continuing to the leaf heuristic or default index. Update the logic
around the candidate resolution in parse.rs so subject/issuer-serial/SKI hints
either resolve to a single certificate or return a ParseError::InvalidStructure
when they match nothing or multiple certificates.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: ad198800-cb79-4b82-9c5c-867943115e59

📥 Commits

Reviewing files that changed from the base of the PR and between 4fb8503 and 199a7c1.

📒 Files selected for processing (1)
  • src/xmldsig/parse.rs

Comment thread src/xmldsig/parse.rs Outdated
Comment thread src/xmldsig/parse.rs
@polaz

polaz commented Jun 24, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 24, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/xmldsig/parse.rs (1)

675-710: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Do not let one matching X.509 hint mask another unmatched hint.

filter_map drops issuer-serials that fail decimal normalization, and the candidate scan accepts the cert if any subject/issuer-serial/SKI hint matches. That means a matching X509SubjectName can still allow a malformed or non-matching X509IssuerSerial/X509SKI to be ignored, despite the PR objective to reject unmatched lookup hints deterministically. Track whether each provided lookup hint matched an embedded certificate, and return InvalidStructure if any provided hint is malformed or unmatched.

Also applies to: 1757-1774

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/xmldsig/parse.rs` around lines 675 - 710, The X509Data lookup logic is
currently treating subject names, issuer serials, and SKIs as one combined OR
match, so a single successful hint can hide a malformed or unmatched one. Update
the lookup flow around the candidate scan in parse.rs to track match status per
hint type in the relevant X509Data parsing function(s), including the
issuer_serial_hints normalization path, and require every provided lookup hint
to either match an embedded certificate or be rejected. If any issuer-serial
fails decimal normalization or any provided SubjectName, IssuerSerial, or SKI
does not match, return InvalidStructure instead of allowing another hint to
satisfy the lookup.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@src/xmldsig/parse.rs`:
- Around line 675-710: The X509Data lookup logic is currently treating subject
names, issuer serials, and SKIs as one combined OR match, so a single successful
hint can hide a malformed or unmatched one. Update the lookup flow around the
candidate scan in parse.rs to track match status per hint type in the relevant
X509Data parsing function(s), including the issuer_serial_hints normalization
path, and require every provided lookup hint to either match an embedded
certificate or be rejected. If any issuer-serial fails decimal normalization or
any provided SubjectName, IssuerSerial, or SKI does not match, return
InvalidStructure instead of allowing another hint to satisfy the lookup.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 4a113b83-cdc0-4e98-b837-0d4187bba171

📥 Commits

Reviewing files that changed from the base of the PR and between 199a7c1 and 5ca0875.

📒 Files selected for processing (1)
  • src/xmldsig/parse.rs

@polaz

polaz commented Jun 24, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai Re: outside-diff X509 lookup hints - fixed in 60abb57. Each provided SubjectName, IssuerSerial, and SKI hint is now validated independently; malformed/unmatched hints return InvalidStructure, and hints that resolve to different certs remain ambiguous. Added regression coverage for malformed issuer serial and unmatched SKI masked by a matching subject.

@coderabbitai

coderabbitai Bot commented Jun 24, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

@polaz Thanks for the detailed update! The fix in 60abb57 looks well-reasoned:

  • Independent per-hint validation is the right approach — each hint type (SubjectName, IssuerSerial, SKI) now fails independently on mismatch/malformation rather than any one masking another.
  • Returning InvalidStructure for malformed or unmatched hints gives callers a clear, deterministic signal rather than silently falling through.
  • The ambiguity case (hints resolving to different certs) being preserved as an error is correct — that's a genuinely contradictory input.
  • The regression tests for unmatched SKI masked by a matching subject and malformed issuer serial are exactly the edge cases that could otherwise be silently swallowed. Good call on adding those explicitly.

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.

feat: build X.509 certificate chains

1 participant