Skip to content

feat(xmldsig): add signature template builders#74

Merged
polaz merged 9 commits into
mainfrom
feat/#73-signature-builders
Jul 6, 2026
Merged

feat(xmldsig): add signature template builders#74
polaz merged 9 commits into
mainfrom
feat/#73-signature-builders

Conversation

@polaz

@polaz polaz commented Jul 3, 2026

Copy link
Copy Markdown
Member

Summary

  • add deterministic SignatureBuilder and ReferenceBuilder APIs for XMLDSig templates
  • preserve reference/transform order and serialize namespace-correct XML with quick-xml
  • reject missing references, invalid namespace prefixes and IDs, and verify-only SHA-1 signing algorithms
  • harden XML NCName validation against markup injection while accepting valid Unicode names
  • update compatible Rust dependencies (quick-xml 0.38, time 0.3.53, num-bigint 0.4.7 resolution)

Testing

  • cargo fmt --all -- --check
  • cargo check --all-features
  • cargo clippy --all-features --all-targets -- -D warnings
  • cargo nextest run --all-features (511 passed)
  • cargo test --doc --all-features (3 passed)

Closes #73

polaz added 2 commits July 3, 2026 14:38
- Add quick-xml 0.38 for deterministic XML output
- Raise the time dev-dependency floor to 0.3.53
- Resolve num-bigint 0.4.7 through the updated dependency graph
- Add deterministic SignatureBuilder and ReferenceBuilder APIs
- Validate signing algorithms, namespace prefixes, and required references
- Cover XML structure, escaping, transform order, and error paths

Closes #73
@coderabbitai

coderabbitai Bot commented Jul 3, 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: 69884957-22c0-4f73-894f-80a7dea792d0

📥 Commits

Reviewing files that changed from the base of the PR and between dab84be and 83894ec.

📒 Files selected for processing (1)
  • tests/signature_builder.rs

📝 Walkthrough

Summary by CodeRabbit

  • New Features

    • Added XMLDSig signature template generation with configurable SignedInfo algorithms, one or more references (preserving insertion order), transforms (including XPath and canonicalization), optional namespace prefixing, and optional empty KeyInfo, producing deterministic output.
  • Bug Fixes

    • Improved pre-generation validation for required references and XML identifier safety (namespace prefix, Signature/Reference IDs), plus clearer errors for unsupported or unsafe signing/digest algorithm usage.
  • Documentation

    • Refreshed the README toolchain description to accurately reflect current XML parsing/writing and cryptography components.
  • Chores

    • Updated XML-related and timing dependencies.

Walkthrough

This PR adds a new xmldsig::builder module for constructing deterministic XMLDSig <Signature> templates, exposes the new builder types through the public API, updates dependencies and README guidance, and adds integration tests for serialization and validation behavior.

Changes

XMLDSig signature builder

Layer / File(s) Summary
Dependency updates
Cargo.toml, README.md
Adds quick-xml as a runtime dependency, updates time to 0.3.53 for dev builds, and revises the README implementation stack description.
Constants, error type and ReferenceBuilder
src/xmldsig/builder.rs
Adds module constants, SignatureBuilderError, and ReferenceBuilder with optional reference metadata plus ordered transform support.
SignatureBuilder core and validation
src/xmldsig/builder.rs
Implements SignatureBuilder state, validation, and full template assembly for namespaces, SignedInfo, SignatureValue, optional KeyInfo, and references.
Reference and transform serialization
src/xmldsig/builder.rs
Serializes Reference and Transform elements and adds XML writing helpers plus NCName and namespace-prefix validation helpers.
Public API exports
src/xmldsig/mod.rs
Exposes the new builder module and re-exports ReferenceBuilder, SignatureBuilder, and SignatureBuilderError.
Template serialization tests
tests/signature_builder.rs
Adds tests for namespace handling, element ordering, reference ordering, transform serialization, XPath content, InclusiveNamespaces output, and Unicode namespace prefixes.
Validation tests
tests/signature_builder.rs
Adds tests for missing references, invalid namespace prefixes, SHA-1 rejection, and NCName validation for Signature and Reference Id values.

Estimated code review effort: 4 (Complex) | ~45 minutes

Possibly related PRs

  • structured-world/xml-sec#14: Overlaps on XMLDSig SignatureBuilder template generation and <Transforms> / InclusiveNamespaces serialization.
  • structured-world/xml-sec#20: Shares the same XMLDSig signing and transform semantics, including XPath-based transform handling and algorithm validation.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main change: adding XMLDSig signature template builders.
Description check ✅ Passed The description is directly related to the changeset and accurately describes the new builders, tests, and dependency updates.
Linked Issues check ✅ Passed The PR matches #73 by adding deterministic XMLDSig builders, preserving order, enforcing validation, adding tests, and updating dependencies.
Out of Scope Changes check ✅ Passed No clearly unrelated changes are present; the README and dependency updates are consistent with the linked issue scope.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ 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 feat/#73-signature-builders

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.

Describe the current RustCrypto stack and quick-xml writer instead of the removed ring dependency.
@greptile-apps

greptile-apps Bot commented Jul 3, 2026

Copy link
Copy Markdown

Greptile Summary

This PR adds XMLDSig template builders. The main changes are:

  • New SignatureBuilder and ReferenceBuilder APIs.
  • Deterministic XML serialization with quick-xml.
  • Validation for references, IDs, namespace prefixes, and signing algorithms.
  • Tests for ordering, XPath transforms, Unicode prefixes, and invalid IDs.

Confidence Score: 5/5

This looks safe to merge.

No blocking issues found in the changed code.

T-Rex T-Rex Logs

What T-Rex did

  • The before-state showed the builder-api test initially failing due to unresolved imports for ReferenceBuilder and SignatureBuilder.
  • The after-state shows the builder-api test passing, with signature_builder_contract ... ok, namespace-prefixed XML, and ALL_ASSERTIONS_PASSED.
  • The validation path was exercised through public Rust API calls to SignatureBuilder::build_template(), covering namespace prefix validation, Signature/Reference Id NCName checks, missing references, and disabled signing algorithms.
  • The dependency-compat update is evidenced by the head SHA and new dependencies like quick-xml v0.38.4 and time v0.3.53, alongside a successful cargo check --all-features.

View all artifacts

T-Rex Ran code and verified through T-Rex

Important Files Changed

Filename Overview
src/xmldsig/builder.rs Adds XMLDSig signature and reference builders with validation and transform serialization.
src/xmldsig/mod.rs Exports the new builder module and public builder types.
tests/signature_builder.rs Adds tests for generated signature templates and builder validation.
Cargo.toml Adds quick-xml and updates the time dev dependency.

Reviews (4): Last reviewed commit: "test(xmldsig): document NCName bypass pa..." | Re-trigger Greptile

Comment thread src/xmldsig/builder.rs Outdated
Comment thread src/xmldsig/builder.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.

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/builder.rs`:
- Line 16: The XPath transform in the XML signature builder uses the ds prefix
without guaranteeing it is bound in scope. Update the XPath emission in the
builder around XPATH_EXCLUDE_ALL_SIGNATURES so the generated <XPath> element
includes a local xmlns:ds binding, or uses the same configured prefix emitted by
ns_prefix("ds"), so not(ancestor-or-self::ds:Signature) always resolves
correctly.

In `@tests/signature_builder.rs`:
- Around line 16-29: Reject non-NCName values for both
SignatureBuilder::signature_id and ReferenceBuilder::id before build_template()
emits XML. Add the same NCName validation already used for ns_prefix into
SignatureBuilder::validate() (or the build path it calls) and ensure the check
covers Signature/@Id and each Reference/@Id so values like sig&1 are rejected
early with a clear error.
🪄 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: 9159d5d0-6ccc-4c1b-ac0a-3a6b651d496e

📥 Commits

Reviewing files that changed from the base of the PR and between 965d549 and 4122fe4.

📒 Files selected for processing (5)
  • Cargo.toml
  • README.md
  • src/xmldsig/builder.rs
  • src/xmldsig/mod.rs
  • tests/signature_builder.rs

Comment thread src/xmldsig/builder.rs Outdated
Comment thread tests/signature_builder.rs
polaz added 2 commits July 3, 2026 22:08
- Reproduce XPath transform parser incompatibility
- Cover Unicode NCName prefixes
- Require NCName validation for Signature and Reference IDs
- Bind the parser-compatible dsig prefix for XPath transforms
- Accept Unicode XML namespace prefixes
- Reject schema-invalid Signature and Reference IDs

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

192-233: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Tighten is_ncname to reject non-round-tripping inputs. Document::parse("<{value}/>") accepts strings that only parse because they introduce comment/PI markup before the root, so malformed Signature/@Id and Reference/@Id values can pass validation. Since quick-xml writes attribute values verbatim, those inputs produce invalid XML.

🤖 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/builder.rs` around lines 192 - 233, The `validate` method in
`SignatureBuilder` only checks `Signature/@Id` and `Reference/@Id` with
`is_ncname`, which lets through values that parse in `Document::parse` but do
not round-trip safely when serialized by quick-xml. Update the ID validation
used in `validate` so it rejects inputs that would not serialize back as a valid
XML attribute value, and apply the stricter check consistently to both
`signature_id` and each `reference.id` by using the existing
`SignatureBuilderError::InvalidId` paths.
🤖 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/builder.rs`:
- Around line 192-233: The `validate` method in `SignatureBuilder` only checks
`Signature/@Id` and `Reference/@Id` with `is_ncname`, which lets through values
that parse in `Document::parse` but do not round-trip safely when serialized by
quick-xml. Update the ID validation used in `validate` so it rejects inputs that
would not serialize back as a valid XML attribute value, and apply the stricter
check consistently to both `signature_id` and each `reference.id` by using the
existing `SignatureBuilderError::InvalidId` paths.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 8c96f6c4-a1ee-45fc-abd4-4a32cedfc5d5

📥 Commits

Reviewing files that changed from the base of the PR and between 4122fe4 and 8797e7a.

📒 Files selected for processing (2)
  • src/xmldsig/builder.rs
  • tests/signature_builder.rs

polaz added 3 commits July 4, 2026 02:39
Reproduce parser-based validation accepting comment and processing-instruction markup for Signature and Reference IDs.
Require parser-based XML names to round-trip exactly, preventing comment or processing-instruction markup from passing Signature and Reference ID validation.
@polaz

polaz commented Jul 3, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai Re: NCName round-trip validation outside-diff finding — fixed in ee25df4. The parsed root local name must now equal the original input exactly, preventing comment/PI markup injection for both Signature/@id and Reference/@id. Regression coverage reproduces both bypass forms; full suite passes 511/511.

@coderabbitai

coderabbitai Bot commented Jul 3, 2026

Copy link
Copy Markdown

Tip

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

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
cd /tmp && rm -rf repo && git clone --quiet https://github.com/structured-world/xml-sec.git repo && cd repo
git log --oneline -1 ee25df4 2>/dev/null || echo "commit not found"
git show ee25df4 --stat
echo "---diff---"
git show ee25df4 -- src/xmldsig/builder.rs

Length of output: 1980


@polaz Confirmed — commit ee25df4 addresses this correctly. The updated is_ncname now checks that document.root_element().tag_name().name() == value, so any parser-based construct like foo/><!--x or foo?><?pi? that would otherwise parse successfully but produce a mismatched root local name is now rejected. This closes the comment/PI injection bypass for both Signature/@Id and Reference/@Id validation. Nice fix, and thanks for the regression coverage.

@polaz

polaz commented Jul 4, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 4, 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: 1

🤖 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 `@tests/signature_builder.rs`:
- Around line 199-213: The current invalid ID payloads in SignatureBuilder tests
fail the initial NCName character check instead of exercising the parser
round-trip path. Update the cases in
SignatureBuilder::new(...).signature_id(...) and
ReferenceBuilder::new(...).id(...) to use payloads that start as valid NCNames
but cross the boundary later, so the validation in build_template() covers the
intended injection scenario.
🪄 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: 7dc78bf3-e133-4604-bf13-4a7a41215485

📥 Commits

Reviewing files that changed from the base of the PR and between 8797e7a and dab84be.

📒 Files selected for processing (2)
  • src/xmldsig/builder.rs
  • tests/signature_builder.rs

Comment thread tests/signature_builder.rs
Explain why the comment and processing-instruction payloads reached parser success before exact-name validation.
@polaz polaz merged commit d9e5e88 into main Jul 6, 2026
10 checks passed
@polaz polaz deleted the feat/#73-signature-builders branch July 6, 2026 06:53
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: add XMLDSig signature builders

1 participant