Harden CSDL attribute round trips - #26
Merged
Merged
Conversation
`emit_csdl_xml` applied `xml_escape` to only 4 of roughly 30
interpolation sites. Names, types, namespaces, DefaultValue,
navigation-binding Path/Target, action/function references and
annotation terms were all written into attributes verbatim. Those values
are agent- and user-influenced, so a `"` in an identifier closed the
attribute and let the remainder of the value inject arbitrary markup —
the same defect class as ARN-172. A property named
Name"/><Property Name="Smuggled
produced a second, unintended property element, and a smuggled
`HasStream="true"` altered the typed model on re-parse.
Every interpolated string value now passes through `xml_escape`. The
remaining unescaped interpolations are numeric (`i64`, `u32`, `f64`,
`bool`) and cannot produce a metacharacter.
`xml_escape` additionally escapes tab, newline and carriage return as
character references. XML attribute-value normalisation replaces literal
occurrences with spaces, so without this a multi-line DefaultValue or
Description came back altered even when the quoting was correct. The
function is also now a single pass rather than five chained `replace`
calls.
Tests cover both properties: `adversarial_identifiers_do_not_inject_markup`
asserts that no live markup is emitted and that the typed model survives
a round trip unchanged, across entity types, keys, properties,
annotations, containers, entity sets, navigation bindings and
action/function imports; `whitespace_in_attribute_values_round_trips`
pins the normalisation behaviour.
This is the emitter half of ARN-237. The strict-parsing half — rejecting
truncated schemas, mandatory attributes, unknown-element rejection — is
deliberately deferred: it increases the set of persisted schemas that
fail to load, which interacts directly with ARN-190, where one corrupt
tenant CSDL aborts the entire registry restore.
Refs ARN-237.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
nikstern
marked this pull request as ready for review
August 23, 2026 21:52
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Implements #23 by porting the CSDL hardening behavior from nerdsane#409 onto this fork.
Deliberate semantic difference from upstream nerdsane#409
Malformed entity syntax now fails parsing, including in optional attributes, instead of silently turning a present value into an absent value. This is stricter and may reject previously tolerated malformed CSDL, but it prevents invalid typed metadata from silently falling back to defaults.
Validation
cargo test -p temper-spec— 284 unit tests plus integration and fixture suites passedcargo clippy -p temper-spec --all-targets -- -D warningscargo test -p temper-codegen --test generated_sdk_compilecargo test -p temper-verifycargo test --workspace— passed, including HTTP metadata E2E and verification cascade coverageCloses #23