Skip to content

feat(xmldsig): complete transform coverage - #103

Open
polaz wants to merge 78 commits into
mainfrom
test/#100-phaos-negative-vectors
Open

feat(xmldsig): complete transform coverage#103
polaz wants to merge 78 commits into
mainfrom
test/#100-phaos-negative-vectors

Conversation

@polaz

@polaz polaz commented Jul 22, 2026

Copy link
Copy Markdown
Member

Summary

  • classify the imported Phaos negative XMLDSig artifacts at their actual digest, structure, weak-key, and certificate-validity boundaries
  • implement the XMLDSig Base64 transform for binary and exact node-set text input across parsing, building, signing, verification, and policy enforcement
  • implement safe-Rust XPath 1.0 and XPath Filter 2.0 with exact tree, attribute, and namespace nodes, input-scoped contexts, bounded expression complexity, namespace storage, and cumulative evaluation work, standard functions, and ordered subtree set operations
  • implement standards-default <XPath> semantics for here() plus explicit libxmlsec1 <Transform> compatibility in signing and verification
  • fail closed on ambiguous XPath id() values, invalid reserved XML namespace bindings, and namespaced ID mismatches while preserving the implicit XPath xml context and C14N 1.1 xml:id non-inheritance
  • bound exact node-set materialization through every public and internal constructor, and exclude subtrees without materializing attacker-controlled removal sets
  • adapt UTF-8 and BOM-marked UTF-16 XML octet streams to comment-preserving node sets for subsequent XPath, Filter 2.0, and canonicalization transforms
  • make template builders reject transform chains and XPath parameters that parsing or execution cannot accept
  • extend subset canonicalization to preserve exact node visibility, contiguous omitted-ancestor xml:base fixup, document-level separators, and all 28 Merlin canonical outputs byte-for-byte
  • add end-to-end signing, negative-path, tampering, donor-vector, and reciprocal xmlsec1 1.3.12 interoperability coverage

Validation

  • cargo check --all-targets --all-features
  • cargo check --no-default-features --features c14n
  • cargo check --no-default-features --features xmldsig
  • cargo clippy --all-targets --all-features -- -D warnings
  • cargo nextest run --all-features --no-fail-fast (714 passed)
  • cargo test --doc --all-features (4 passed)
  • cargo fmt --all -- --check
  • cargo package --allow-dirty
  • cargo update --dry-run (aes 0.9.2 and cc 1.4.0 available; library lockfile is not tracked)

Closes #100
Closes #101
Closes #102

- classify Phaos negative signature and certificate vectors
- implement Base64 reference transforms end to end
- add exact XPath 1.0 and XPath Filter 2.0 node sets
- validate Merlin canonical subsets and reciprocal xmlsec1 interop

Closes #100
Closes #101
Closes #102
@coderabbitai

coderabbitai Bot commented Jul 22, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: e7c161fe-f37b-49d3-8301-27be3a5f62d6

📥 Commits

Reviewing files that changed from the base of the PR and between 0a0921e and 814d30e.

📒 Files selected for processing (3)
  • src/xmldsig/sign.rs
  • src/xmldsig/xpath.rs
  • tests/signing_digest.rs

📝 Walkthrough

Summary by CodeRabbit

  • New Features

    • Added support for Base64, XPath 1.0, and XPath Filter 2.0 transforms in XML signatures.
    • Added configurable XPath here() semantics for signing and verification.
    • Expanded XMLDSig transform and validation APIs.
  • Bug Fixes

    • Improved canonicalization of XML subsets, namespace handling, and inherited attributes.
    • Corrected xml:id behavior in Canonical XML 1.1 subsets.
  • Security

    • Added bounds for references, transforms, XPath expressions, and node-set processing.
    • Added stricter validation for malformed or unsafe signature inputs.

Walkthrough

The change adds Base64, XPath 1.0, and XPath Filter 2.0 XMLDSig transforms, exact node-set tracking, visibility-aware canonicalization, configurable here() semantics, and expanded integration, golden-vector, interoperability, and negative-vector tests.

Changes

XMLDSig transform and canonicalization flow

Layer / File(s) Summary
Visibility-aware canonicalization
src/c14n/*
Canonicalization now tracks element, attribute, and namespace visibility, renders orphan axis nodes, handles namespace discontinuities, and updates C14N 1.1 xml:* inheritance and xml:base behavior.
Exact node sets and XPath evaluation
src/xmldsig/types.rs, src/xmldsig/xpath.rs
NodeSet stores exact tree, attribute, and namespace keys; XPath evaluation supports here(), id(), lang(), namespace bindings, and ordered Filter 2.0 operations.
Transform parsing and execution
src/xmldsig/transforms.rs, src/xmldsig/whitespace.rs
Base64, XPath, and XPath Filter 2.0 transforms are parsed with strict validation and executed through bounded, options-aware chains with binary/node-set adaptation and canonicalization.
Public API and builder serialization
src/xmldsig/mod.rs, src/xmldsig/parse.rs, src/xmldsig/builder.rs, Cargo.toml
New transform types and URIs are exported, parse_reference is public with mixed-content validation, safe XPath dependencies are enabled, and XPath namespace bindings are validated during signature construction.
Signing and verification options
src/xmldsig/sign.rs, src/xmldsig/verify.rs
Signing and verification thread TransformOptions, expose XPath here() semantics, update transform allowlisting, and normalize signature Base64 input as bytes.
Validation and fixtures
tests/*, README.md
Tests cover transform behavior, signing and verification, tampering, C14N golden vectors, xmlsec1 interoperability, Phaos failure boundaries, fixture documentation, and corpus completeness.

Estimated code review effort: 5 (Critical) | ~120 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Reference
  participant parse_transforms
  participant execute_transforms_with_options
  participant XPathEngine
  participant NodeSet
  participant canonicalize_with_visibility
  participant VerifyContext

  Reference->>parse_transforms: parse Base64/XPath/XPathFilter2
  VerifyContext->>execute_transforms_with_options: execute with TransformOptions
  execute_transforms_with_options->>XPathEngine: evaluate XPath or Filter 2.0
  XPathEngine->>NodeSet: return selected exact nodes
  execute_transforms_with_options->>canonicalize_with_visibility: canonicalize visible node set
  canonicalize_with_visibility-->>VerifyContext: return pre-digest bytes
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed It succinctly describes the main change: expanded XMLDSig transform support.
Description check ✅ Passed The description directly matches the XMLDSig transform and interoperability changes in the PR.
Linked Issues check ✅ Passed The code and tests address Phaos classification, Base64 transforms, XPath/XPath Filter 2.0, and the required validation and interoperability checks.
Out of Scope Changes check ✅ Passed The changes appear scoped to the stated XMLDSig transform, canonicalization, and test coverage objectives.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch test/#100-phaos-negative-vectors

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@greptile-apps

greptile-apps Bot commented Jul 22, 2026

Copy link
Copy Markdown

Greptile Summary

This PR completes XMLDSig transform support across parsing, signing, verification, and canonicalization. The main changes are:

  • Adds Base64, XPath 1.0, and XPath Filter 2.0 transforms.
  • Adds exact and bounded XPath node-set processing.
  • Expands canonicalization for subset visibility, namespace state, and xml:base fixup.
  • Tightens builder, parser, ID, namespace, and transform-chain validation.
  • Adds negative-vector, golden-output, and xmlsec1 interoperability coverage.

Confidence Score: 5/5

This looks safe to merge.

No blocking issues found in the changed code.

Files Needing Attention: No files require additional attention.

T-Rex T-Rex Logs

What T-Rex did

  • Ran the integration tests for base64_transform_integration and xpath_transform_integration with cargo test, which completed with exit code 0 using Cargo/Rustc 1.96.1, and the complete stdout/stderr and per-test results are preserved in the attached log.

View all artifacts

T-Rex Ran code and verified through T-Rex

Important Files Changed

Filename Overview
src/xmldsig/xpath.rs Adds bounded XPath evaluation and exact tree, attribute, and namespace node projection.
src/xmldsig/transforms.rs Adds Base64, XPath, Filter 2.0, octet-stream adaptation, and node-set finalization.
src/xmldsig/builder.rs Aligns template construction and XPath validation with parser and executor limits.
src/c14n/serialize.rs Adds exact node visibility, subset axis processing, document separators, and XML attribute inheritance handling.
src/c14n/ns_common.rs Makes namespace collection aware of exact namespace-node visibility.
src/c14n/ns_exclusive.rs Adds visibility-aware prefix selection and namespace discontinuity tracking.
src/c14n/xml_base.rs Limits C14N 1.1 base fixup to contiguous omitted ancestors.
Cargo.toml Adds safe-Rust XPath dependencies to the XMLDSig feature.

Reviews (16): Last reviewed commit: "docs(xmldsig): clarify xpath work ceilin..." | Re-trigger Greptile

Comment thread src/c14n/serialize.rs

@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: 3

🤖 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/types.rs`:
- Around line 252-263: Restore set.with_comments to the requested with_comments
value after insert_subtree and comment filtering in collect_document, so
materializing nodes cannot override the caller’s setting. Preserve the existing
removal of comment Tree keys when comments are disabled and ensure
entire_document_without_comments() reports with_comments() == false.

In `@tests/c14n_golden.rs`:
- Around line 288-372: Update
merlin_xpath_subset_and_signed_info_match_all_28_golden_outputs so the final
signed_info_output comparison does not assert before the accumulated failures
are reported. Add any SignedInfo mismatch to the existing failures list with
consistent diagnostic context, or otherwise defer that assertion until after the
per-reference failures check, ensuring all mismatches are surfaced together.

In `@tests/xpath_transform_integration.rs`:
- Around line 1-12: Add end-to-end signing and verification cases in the
integration tests for plain Transform::XPath and XPathFilterOperation::Union,
alongside the existing XPathFilter2 Intersect/Subtract coverage. Reuse the
established fixtures, builders, and verification flow so both missing transform
cases are exercised without changing existing coverage.
🪄 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: b254107a-d800-4c2d-a4d0-e8f72b84b1da

📥 Commits

Reviewing files that changed from the base of the PR and between 93ff852 and 335a8cc.

📒 Files selected for processing (27)
  • Cargo.toml
  • README.md
  • src/c14n/mod.rs
  • src/c14n/ns_common.rs
  • src/c14n/ns_exclusive.rs
  • src/c14n/ns_inclusive.rs
  • src/c14n/serialize.rs
  • src/c14n/xml_base.rs
  • src/xmldsig/builder.rs
  • src/xmldsig/mod.rs
  • src/xmldsig/parse.rs
  • src/xmldsig/transforms.rs
  • src/xmldsig/types.rs
  • src/xmldsig/verify.rs
  • src/xmldsig/xpath.rs
  • tests/base64_transform_integration.rs
  • tests/c14n_golden.rs
  • tests/donor_negative_vectors.rs
  • tests/fixtures/xmldsig/README.md
  • tests/fixtures/xmldsig/merlin-xpath-filter2/sign-spec-subset.xml
  • tests/fixtures/xmldsig/phaos-xmldsig-three/certs/rsa-ca-cert.der
  • tests/fixtures/xmldsig/phaos-xmldsig-three/certs/rsa-cert.der
  • tests/fixtures_smoke.rs
  • tests/signature_builder.rs
  • tests/xmlsec1_interop.rs
  • tests/xpath_donor_vectors.rs
  • tests/xpath_transform_integration.rs

Comment thread src/xmldsig/types.rs
Comment thread tests/c14n_golden.rs
Comment thread tests/xpath_transform_integration.rs

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 335a8cc3b9

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/xmldsig/xpath.rs Outdated
Comment thread src/xmldsig/transforms.rs Outdated
Comment thread src/xmldsig/xpath.rs Outdated
Comment thread src/xmldsig/transforms.rs
Comment thread src/c14n/serialize.rs
polaz added 9 commits July 23, 2026 09:57
Prove that selected attributes and namespaces emit no bytes when their owner element is absent from the canonical subset.
- Default here() to the XMLDSig XPath parameter element
- Add explicit libxmlsec Transform-node compatibility to sign and verify
- Preserve comment exclusion metadata while materializing node sets

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b1315dc17b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/c14n/serialize.rs
Comment thread src/xmldsig/builder.rs
Comment thread src/xmldsig/xpath.rs Outdated
Comment thread src/xmldsig/transforms.rs Outdated

@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/transforms.rs (1)

326-349: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Reuse the shared XML-base64 normalization helper.

append_normalized_base64 duplicates the same space/tab/CR/LF-only normalization policy from src/xmldsig/whitespace.rs. Extract a shared byte-oriented helper usable from transforms.rs and verify.rs, and call it from the Base64 transform path.

🤖 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/transforms.rs` around lines 326 - 349, Move the shared
space/tab/CR/LF Base64 normalization logic from append_normalized_base64 into a
reusable byte-oriented helper in xmldsig::whitespace, preserving invalid-byte
rejection and error behavior. Update the Base64 transform path and verify.rs
callers to use that helper, then remove the duplicate local implementation from
transforms.rs.

Source: Learnings

🤖 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/transforms.rs`:
- Around line 326-349: Move the shared space/tab/CR/LF Base64 normalization
logic from append_normalized_base64 into a reusable byte-oriented helper in
xmldsig::whitespace, preserving invalid-byte rejection and error behavior.
Update the Base64 transform path and verify.rs callers to use that helper, then
remove the duplicate local implementation from transforms.rs.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: f6d7c4cf-ed65-46bf-a728-34b758bc8e13

📥 Commits

Reviewing files that changed from the base of the PR and between 335a8cc and b1315dc.

📒 Files selected for processing (10)
  • src/c14n/serialize.rs
  • src/xmldsig/mod.rs
  • src/xmldsig/sign.rs
  • src/xmldsig/transforms.rs
  • src/xmldsig/types.rs
  • src/xmldsig/verify.rs
  • src/xmldsig/xpath.rs
  • tests/base64_transform_integration.rs
  • tests/c14n_golden.rs
  • tests/xpath_transform_integration.rs

polaz added 10 commits July 23, 2026 12:17
Reproduce duplicate xml:base materialization when an omitted parent separates two included elements.
Stop C14N 1.1 xml:base materialization at the nearest included ancestor while preserving it as the URI resolution seed.
Reproduce malformed XPath elements when an expression namespace binding reuses the signature prefix for another URI.
Fail template validation when an XPath binding would move prefixed XMLDSig parameter elements into another namespace.
Reproduce the compatibility normalizer collapsing XPath word operators into function-like tokens.
Exclude XPath word operators from QName-to-function-call whitespace normalization.
Reproduce unbounded transform chains through both XML parsing and the public programmatic executor.
Reject references with more than 64 transforms at both XML parsing and public executor boundaries.
Route transform and signature verification byte streams through one XML-whitespace helper while retaining caller-specific alphabet validation.
@polaz

polaz commented Jul 23, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai Fixed in deac05f: transform and SignatureValue verification now share a byte-oriented XML base64 normalizer with caller-specific alphabet validation; existing invalid-byte offsets and error mapping are preserved, with focused unit and integration coverage.

@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 (2)
src/xmldsig/types.rs (1)

96-124: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Make the public NodeSet constructors budget-checked.

xmldsig re-exports NodeSet, but the fully public constructors remain unbounded while the budget checks only cover the pub(crate) try_* variants. External callers can bypass the quadratic materialization guard through entire_document_without_comments, entire_document_with_comments, or subtree. Move those constructors to pub(crate) with try_* behavior, or embed the budget check in the public constructors.

🤖 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/types.rs` around lines 96 - 124, Make the public NodeSet
constructors entire_document_without_comments, entire_document_with_comments,
and subtree enforce the same materialization budget as the existing try_*
variants. Either change them to crate-private try_* constructors that return the
appropriate failure result, or add the budget checks directly while preserving
their public API; ensure external callers cannot bypass the quadratic guard.
src/xmldsig/xpath.rs (1)

441-470: 🚀 Performance & Scalability | 🟠 Major | ⚡ Quick win

Bound total XPath evaluation work.

MAX_XPATH_PER_NODE_EVALUATIONS only limits how many independent filter evaluations run; each xpath.evaluate(&context, node.clone()) can still traverse the mirrored document, and sxd-xpath-no-unsafe offers no step limit/interrupt API. In filter mode, add a combined budget such as nodes_evaluated_so_far * document_size, or run the ordinary XPath transform under a wall-clock/step ceiling, rather than only checking the outer loop count.

🤖 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/xpath.rs` around lines 441 - 470, Bound total XPath work in the
wrap_as_filter branch, not just the number of per-node evaluations. Use the
mirrored document size and a cumulative budget such as evaluated_nodes
multiplied by document_size, rejecting the transform with TransformError::XPath
once the budget is exceeded; apply the check before each xpath.evaluate call
while preserving the existing selected-node behavior.
🤖 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/types.rs`:
- Around line 96-124: Make the public NodeSet constructors
entire_document_without_comments, entire_document_with_comments, and subtree
enforce the same materialization budget as the existing try_* variants. Either
change them to crate-private try_* constructors that return the appropriate
failure result, or add the budget checks directly while preserving their public
API; ensure external callers cannot bypass the quadratic guard.

In `@src/xmldsig/xpath.rs`:
- Around line 441-470: Bound total XPath work in the wrap_as_filter branch, not
just the number of per-node evaluations. Use the mirrored document size and a
cumulative budget such as evaluated_nodes multiplied by document_size, rejecting
the transform with TransformError::XPath once the budget is exceeded; apply the
check before each xpath.evaluate call while preserving the existing
selected-node behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 2bbf016d-9748-42c1-8af7-1b555d1c8109

📥 Commits

Reviewing files that changed from the base of the PR and between 74e0b2b and ebaef06.

📒 Files selected for processing (8)
  • src/xmldsig/builder.rs
  • src/xmldsig/transforms.rs
  • src/xmldsig/types.rs
  • src/xmldsig/uri.rs
  • src/xmldsig/xpath.rs
  • tests/base64_transform_integration.rs
  • tests/signature_builder.rs
  • tests/uri_integration.rs

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ebaef0678b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/xmldsig/xpath.rs Outdated
Comment thread src/xmldsig/builder.rs Outdated
Comment thread src/xmldsig/builder.rs
Comment thread src/xmldsig/xpath.rs Outdated

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 066682f47f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/xmldsig/transforms.rs
Comment thread src/xmldsig/types.rs Outdated

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: baa19f6071

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/xmldsig/xpath.rs
Comment thread src/xmldsig/xpath.rs
Comment thread src/xmldsig/xpath.rs Outdated
Comment thread src/xmldsig/xpath.rs Outdated

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 21590a5f04

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/xmldsig/builder.rs
polaz added 2 commits July 28, 2026 11:20
- Share XPath work across transforms and references
- Bound source mirrors, id scans, namespaces, and references
- Clarify the standards-required cross-document here() error
Validate each SignedInfo child before applying the aggregate Reference cardinality bound.

@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/xpath.rs (1)

617-657: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Raise the whole-document XPath work ceiling or avoid per-node document-size charges.

The filter branch charges document_size once for the all-nodes scan and again before every input-node evaluation, so N whole-document inputs cost 2·N·D. With MAX_XPATH_PER_NODE_EVALUATIONS = 4_096, a 737-node entire-document input can exhaust MAX_XPATH_CUMULATIVE_EVALUATION_WORK = 6_000_000 before id()/here() even run, while a 2,500-node input fails on the trivial true() expression. For SAML/XAdES documents, either raise this constant to allow the full per-node cap on reasonable document sizes or scale the charge by expression shape/document relation so ordinary URI="" transforms are not rejected under the 1,024-entry default per-transform limit.

🤖 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/xpath.rs` around lines 617 - 657, Adjust the work-budget
accounting in the wrap_as_filter branch so per-node XPath evaluation does not
exhaust the cumulative limit merely because each input charges the full document
size. Update the charges around all_nodes_xpath evaluation and the
xpath.evaluate loop, or raise the relevant MAX_XPATH_CUMULATIVE_EVALUATION_WORK
limit, while preserving protection against genuinely expensive expressions and
allowing ordinary whole-document URI="" transforms up to
MAX_XPATH_PER_NODE_EVALUATIONS.
🤖 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/xpath.rs`:
- Around line 617-657: Adjust the work-budget accounting in the wrap_as_filter
branch so per-node XPath evaluation does not exhaust the cumulative limit merely
because each input charges the full document size. Update the charges around
all_nodes_xpath evaluation and the xpath.evaluate loop, or raise the relevant
MAX_XPATH_CUMULATIVE_EVALUATION_WORK limit, while preserving protection against
genuinely expensive expressions and allowing ordinary whole-document URI=""
transforms up to MAX_XPATH_PER_NODE_EVALUATIONS.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 7209b988-bcef-4bdf-b39d-e6866b834f13

📥 Commits

Reviewing files that changed from the base of the PR and between 74e0b2b and 0a0921e.

📒 Files selected for processing (14)
  • src/xmldsig/builder.rs
  • src/xmldsig/parse.rs
  • src/xmldsig/sign.rs
  • src/xmldsig/transforms.rs
  • src/xmldsig/types.rs
  • src/xmldsig/uri.rs
  • src/xmldsig/verify.rs
  • src/xmldsig/xpath.rs
  • tests/base64_transform_integration.rs
  • tests/signature_builder.rs
  • tests/transforms_integration.rs
  • tests/uri_integration.rs
  • tests/xpath_donor_vectors.rs
  • tests/xpath_transform_integration.rs

Document why the context-count ceiling and signature-wide worst-case work budget are independent limits.
@polaz

polaz commented Jul 29, 2026

Copy link
Copy Markdown
Member Author

@codex review

@polaz

polaz commented Jul 29, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 29, 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.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 814d30e806

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/xmldsig/xpath.rs
// A user expression may scan the entire document on every call.
// Charge that worst-case cost before execution so a failure never
// occurs after performing work beyond the aggregate budget.
work_budget.charge(document_size)?;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Account for nested scans inside each XPath evaluation

When verifying untrusted XML with an ordinary XPath transform, this charges only one document traversal per context-node evaluation, but a short accepted expression such as //*[count(//*) > 0] can scan the document once for every element during each evaluation. Since the outer loop evaluates the expression for every input node, a roughly 1,000-node document can remain below the 6,000,000-unit meter while causing approximately cubic XPath work, enabling a CPU denial of service. The budget must account for intra-expression traversal multiplicity or use an evaluator with an interruptible step limit.

Useful? React with 👍 / 👎.

Comment thread src/xmldsig/types.rs
self.nodes.insert(XmlNodeKey::Namespace {
owner: owner.id(),
prefix: prefix.to_owned(),
uri: uri.to_owned(),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Bound namespace bytes when materializing node sets

When untrusted XML declares a long namespace URI on an ancestor with many descendants, every descendant's in-scope namespace entry clones that entire URI here. The 65,536-entry limit counts nodes but not string bytes, so a document containing one moderately large URI and thousands of small elements can amplify into hundreds of megabytes or more during ordinary URI dereferencing, causing an out-of-memory denial of service before transform execution. Charge the cloned prefix/URI bytes against a materialization budget or store shared references instead.

Useful? React with 👍 / 👎.

Comment thread src/xmldsig/types.rs
Comment on lines +184 to +187
self.nodes.retain(|key| {
document.get_node(key.owner_id()).is_none_or(|candidate| {
candidate != node && !candidate.ancestors().any(|ancestor| ancestor == node)
})

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Avoid ancestor scans for every retained node-set entry

For an enveloped signature nested near the bottom of a deeply nested untrusted document, most retained entries are ancestors or unrelated nodes, and this predicate walks each candidate's complete ancestor chain looking for the signature node. With tens of thousands of entries still permitted by the materialization cap, exclude_subtree therefore becomes quadratic and can consume hundreds of millions of ancestor steps before digesting. Remove entries using document-order subtree bounds or precompute the excluded owner IDs in one traversal.

Useful? React with 👍 / 👎.

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(xmldsig): support XPath transforms feat(xmldsig): support Base64 reference transforms test(xmldsig): classify Phaos negative vectors

1 participant