Skip to content

fix(security): close SVG/i18n security-context gaps vs @angular/compiler v21.2.7 - #334

Open
Brooooooklyn wants to merge 5 commits into
mainfrom
fix/issue-315-security-contexts
Open

fix(security): close SVG/i18n security-context gaps vs @angular/compiler v21.2.7#334
Brooooooklyn wants to merge 5 commits into
mainfrom
fix/issue-315-security-contexts

Conversation

@Brooooooklyn

@Brooooooklyn Brooooooklyn commented Jun 2, 2026

Copy link
Copy Markdown
Member

Summary

Closes #315.

Bumps the vendored @angular/compiler submodule to v21.2.7 and ports the security-context fixes from issue #315, keeping oxc_angular_compiler a faithful 1:1 reimplementation of the pinned upstream.

Issue #315 sub-gaps

  • Host-binding security context is now computed (multi-selector union/merge + case-sensitive :not(element) exclusions over allKnownElementNames).
  • AOT i18n rejects trusted-types sink attributes (e.g. iframe|src) for translation; the guard uses the resolved element tag.
  • Template preparser strips :svg:script (in addition to script), matching v21.2.7 SCRIPT_ELEMENTS.

Faithfulness fixes surfaced during review

  • Namespaced security lookup: :svg: / :math: elements resolve by local name; the host-unknown scan skips the full phantom set of SECURITY_SCHEMA element segments that exist only namespaced (:svg:animate, :math:*) or are absent from the element schema, so it matches upstream allKnownElementNames reachability — no over-validation, no under-sanitization (verified: phantom set == {sec segments} − {bare known} exactly).
  • SVG/MathML namespace inheritance for implicit + selectorless children; namespaced raw-text and namespaced void-local close-tag handling.
  • Explicit parser is_component marker (uppercase element vs bare component) threaded through security, i18n, and AST construction.
  • Namespaced attribute codegen (mergeNsAndName) for template attr bindings; host bindings left unsplit, matching upstream.
  • ShadowCss: closed-comment-only handling, ECMAScript \s semantics, unanchored sourceURL detection, single-pass restore, and a scoping-leak fix.

Validation

  • cargo fmt --all -- --check: clean · cargo check: 0 errors
  • cargo test -p oxc_angular_compiler: all binaries pass (0 failed, 1 pre-existing ignored)
  • cargo run -p oxc_angular_conformance: 1259/1259 (100%), idempotent
  • Reviewed across 22 adversarial-review iterations (Codex), ending in an approved verdict with no material findings.

🤖 Generated with Claude Code


Note

High Risk
Touches authentication-adjacent security context, i18n XSS guards, and core HTML/R3 parsing paths; incorrect namespace or sink handling could change sanitization or template output.

Overview
Aligns oxc_angular_compiler with @angular/compiler v21.2.7 for issue #315 and related parser/i18n faithfulness gaps.

Security & sanitization: Host bindings on components/directives now get real security_context via host_binding_security_context instead of None. ATTRIBUTE_NO_BINDING bindings map to ɵɵvalidateAttribute in resolve_sanitizers. i18n extraction/merge blocks trusted-types sink attributes without stripping namespace prefixes (e.g. :svg:iframe|src stays allowed).

HTML lexer/parser: Adds @default never; exhaustive switch (BlockType::DefaultNever), digit-named entities, and IncompleteBlockOpen handling. Namespace inheritance and component open/close matching use resolved full names; HtmlElement gains is_component. Raw-text scanning is unified (local vs component close boundaries); default mode treats <_foo> as text while selectorless mode differs for top-level vs mid-text <_.

R3 / i18n: R3SwitchExhaustiveCheck drops optional expression; conformance humanizer trims @let span semicolons for v21.2.7. Selectorless components use fullName/void host tags in i18n placeholders. Binding specialization uses shared split_ns_name from the HTML tags module.

Conformance: Fixture JSON updates (entities, switch blocks, R3 spans for data-* bindings, ShadowCss comments) and snapshot totals 1273 tests at 100% pass.

Reviewed by Cursor Bugbot for commit 626d83b. Bugbot is set up for automated code reviews on this repo. Configure here.

Brooooooklyn and others added 2 commits June 2, 2026 12:33
Regenerate the conformance fixtures and angular.snap.md against the
vendored Angular v21.2.7 submodule so `cargo run -p oxc_angular_conformance`
is idempotent (git diff --exit-code clean).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ler v21.2.7 (#315)

Bump the vendored @angular/compiler submodule to v21.2.7 and port the
security-context fixes from issue #315, keeping oxc_angular_compiler a
faithful 1:1 reimplementation of the pinned upstream.

Issue #315 sub-gaps:
- Host bindings now compute the security context (multi-selector union/merge
  plus case-sensitive :not(element) exclusions over allKnownElementNames).
- AOT i18n: trusted-types sink attributes (e.g. iframe|src) are rejected for
  translation; the guard uses the resolved element tag.
- Template preparser strips :svg:script (in addition to script), matching
  v21.2.7 SCRIPT_ELEMENTS.

Faithfulness fixes surfaced during 22 adversarial-review iterations:
- Namespaced security lookup: :svg:/:math: elements resolve by local name;
  the host-unknown scan skips the full phantom set of SECURITY_SCHEMA element
  segments that exist only namespaced (:svg:animate, :math:*) or are absent
  from the element schema, so it matches upstream allKnownElementNames
  reachability (no over-validation, no under-sanitization).
- SVG/MathML namespace inheritance for implicit and selectorless children;
  namespaced raw-text and namespaced void-local close-tag handling.
- Explicit parser is_component marker (uppercase element vs bare component)
  threaded through security, i18n, and AST construction.
- Namespaced attribute codegen (mergeNsAndName) for template attr bindings;
  host bindings left unsplit, matching upstream.
- ShadowCss: closed-comment-only handling, ECMAScript \s semantics, unanchored
  sourceURL detection, single-pass comment restore, and a scoping-leak fix.

Validation: cargo fmt/check clean; full Rust test suite passes (0 failed,
1 pre-existing ignored); conformance 1259/1259 (100%, idempotent). The final
adversarial review returned an approved verdict with no material findings.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

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

ℹ️ 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 crates/oxc_angular_compiler/src/transform/html_to_r3.rs Outdated
brandonroberts and others added 2 commits June 3, 2026 09:36
Signed-off-by: Brandon Roberts <robertsbt@gmail.com>
Merge origin/main into fix/issue-315-security-contexts and address Codex
review on html_to_r3 visit_element:

- Read element.is_component before special script/style/link handling
- Skip preparser Element-only filtering for selectorless components
  (matches upstream visitComponent, which never calls preparseElement)
- Keep UNSUPPORTED_SELECTORLESS_TAGS check on resolved host tag
- Add unit tests for bare <Script>/<Style>/<Link/> components vs real
  lowercase <script>/<style> elements

Merge notes:
- Keep PR angular submodule pin at v21.2.7
- Prefer PR security-context / is_component / namespaced semantics
- Prefer main relative fixture paths; oxfmt fixtures after merge
- Fix Vec::new_in(&allocator) API after oxc 0.140 merge
@cursor

cursor Bot commented Aug 11, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_759d00f2-30f8-4a36-a6bf-f592d036fdac)

Merge from main pulled v22 semantics that break the v21.2.7 pin for #315:
- restore case-insensitive data- attribute name normalization for bindings
- strip trailing semicolon from @let humanized source spans (v21 fixtures)
- fix shadow_css comment fixtures that mixed {} input with {c} expected

Conformance: 1273/1273 (100%).
@cursor

cursor Bot commented Aug 11, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_346b568d-16dc-4542-b4d4-c30da0af2790)

@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: 626d83bc9f

ℹ️ 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".

/// prefix is no longer stripped, so `data-on-x` is not an event binding.
/// Matches TypeScript v21.2.7: `/^data-/i.test(attrName) ? attrName.substring(5) : attrName`.
fn normalize_attribute_name<'b>(&self, name: &'b str) -> &'b str {
if name.len() > 5 && name[..5].eq_ignore_ascii_case("data-") { &name[5..] } else { name }

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Avoid slicing Unicode attribute names by byte offset

When an attribute name contains multibyte characters and byte offset 5 is not a UTF-8 boundary, this indexing panics before the prefix comparison; for example, the permissive HTML lexer accepts <div ééé="x"></div>, but ééé has six bytes and name[..5] splits the final character, crashing the compiler during the R3 transform. Check the ASCII data- prefix through a boundary-safe operation such as name.get(..5) before slicing.

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.

security: missing security-context entries for SVG animation, iframe i18n, and namespaced SVG script elements

2 participants