Add animation HTML wrapper safety#88
Conversation
There was a problem hiding this comment.
Claude Code Review
This repository is configured for manual code reviews. Comment @claude review to trigger a review and subscribe this PR to future pushes, or @claude review once for a one-time review.
Tip: disable this comment in your organization's Code Review settings.
|
@coderabbitai review Please review the generated animation HTML wrapper safety slice. Focus areas:
Claude review is intentionally skipped per maintainer instruction. |
|
Caution Review failedPull request was closed or merged during review No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (3)
🚧 Files skipped from review as they are similar to previous changes (2)
📝 WalkthroughWalkthroughThis PR hardens the animation HTML wrapper generation by adding comprehensive escaping for embedded collection libraries, token data, and dependency scripts, while neutralizing script-closing sequences. The implementation includes new smart contract escaping helpers, a detailed wrapper boundary test validating the escaping protections, and updates to project documentation and operational tracking. ChangesAnimation HTML Wrapper Escaping & Safety
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
🧩 Analysis chain🏁 Script executed: #!/bin/bash
# Find and read main changed files
echo "=== Finding relevant Solidity files ==="
fd -e sol | head -30
echo ""
echo "=== Finding test files ==="
fd -e sol -p test | head -20
echo ""
echo "=== Finding docs/ADR files ==="
fd -e md | head -40
echo ""
echo "=== StreamCore.sol ==="
cat smart-contracts/StreamCore.sol 2>/dev/null || fd -e sol -n StreamCore.sol --exec cat {}
echo ""
echo "=== StreamMetadataEscaping test ==="
fd -e sol -n "StreamMetadataEscaping*" --exec cat {}Length of output: 68375 🏁 Script executed: #!/bin/bash
echo "=== PR diff overview ==="
gh pr diff 88 --repo 6529-Collections/6529Stream 2>/dev/null | head -2000Length of output: 44991
HTML Attribute Escaping —
|
| Focus Area | Assessment |
|---|---|
collectionLibrary HTML attribute escaping |
✅ Correct; minor: null/control chars in URL not escaped (low severity, admin-controlled) |
JS string escaping for tokenData / dependency |
✅ Correct; < → \x3c breaks any </script inside the literal |
tokenDataRaw + JSON.parse wrapper |
✅ Correct; hostile injection contained; runtime throw for non-JSON tokenData is expected and documented |
Case-insensitive </script neutralization |
✅ Correct bounds check, correct case folding, no double-processing side effects |
| Tests/docs scope framing | ✅ Accurately captures wrapper-boundary hardening vs. artist-script sandboxing |
The implementation is sound for its declared scope. The one actionable item worth tracking is null/control-character handling in _escapeHtmlAttribute for the URL attribute, which can be addressed in the URI-policy work already listed as remaining.
✅ 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.
There was a problem hiding this comment.
🧹 Nitpick comments (1)
smart-contracts/StreamCore.sol (1)
822-863: Downgrade the U+2028/U+2029 concern: escaping is compatibility hardening, not a modern syntax break.The “unescaped U+2028/U+2029 breaks wrapper string literals” issue applies to older ECMAScript engines; in ES2019+ (used by modern browsers), U+2028 (LINE SEPARATOR) and U+2029 (PARAGRAPH SEPARATOR) are allowed inside single- and double-quoted JavaScript string literals and do not invalidate/terminate the literal. Consider escaping them in
_escapeJavaScriptSingleQuotedStringonly if the generated wrapper script must run on legacy JS runtimes (defense-in-depth).🤖 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 `@smart-contracts/StreamCore.sol` around lines 822 - 863, The comment says escaping U+2028/U+2029 is unnecessary for modern JS runtimes; make the escaping of LINE SEPARATOR (U+2028) and PARAGRAPH SEPARATOR (U+2029) conditional rather than always applied in _escapeJavaScriptSingleQuotedString. Add an optional boolean parameter (e.g., escapeLineSeparators) to _escapeJavaScriptSingleQuotedString and propagate it from callers; when true, detect and escape the U+2028/U+2029 codepoints (they are encoded as the UTF‑8 sequences 0xE2 0x80 0xA8 and 0xE2 0x80 0xA9) and append their escaped form (\u2028 / \u2029) using _appendBytes/_hexNibble as appropriate; when false, leave those codepoints unescaped. Ensure callers that generate wrapper scripts default to false unless legacy JS runtime compatibility is required.
🤖 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.
Nitpick comments:
In `@smart-contracts/StreamCore.sol`:
- Around line 822-863: The comment says escaping U+2028/U+2029 is unnecessary
for modern JS runtimes; make the escaping of LINE SEPARATOR (U+2028) and
PARAGRAPH SEPARATOR (U+2029) conditional rather than always applied in
_escapeJavaScriptSingleQuotedString. Add an optional boolean parameter (e.g.,
escapeLineSeparators) to _escapeJavaScriptSingleQuotedString and propagate it
from callers; when true, detect and escape the U+2028/U+2029 codepoints (they
are encoded as the UTF‑8 sequences 0xE2 0x80 0xA8 and 0xE2 0x80 0xA9) and append
their escaped form (\u2028 / \u2029) using _appendBytes/_hexNibble as
appropriate; when false, leave those codepoints unescaped. Ensure callers that
generate wrapper scripts default to false unless legacy JS runtime compatibility
is required.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 0abaef06-2bc3-4e9e-9f37-ad429010ff3f
📒 Files selected for processing (12)
docs/adr/0006-metadata-freeze.mddocs/known-blockers.mddocs/metadata.mddocs/status.mdops/AUTONOMOUS_RUN.mdops/ROADMAP.mdsmart-contracts/StreamCore.soltest/README.mdtest/StreamInitialization.t.soltest/StreamMetadataEscaping.t.soltest/fixtures/metadata/onchain-final-schema-v1-token-uri.txttest/helpers/TestHashingUtils.sol
|
Autonomous merge note:
|
Refs #51.
Summary
collectionLibrarybefore placing it into the generated animation HTML<script src>attribute, including C0 control characters and DEL as numeric entities.tokenDataand dependency script content through escaped JavaScript string literals instead of raw wrapper source.tokenDataviaJSON.parse("[" + tokenDataRaw + "]"), preventing hostile token data from executing before parsing.</scriptsequences inside the generated wrapper script body.animation_urlHTML assertions for hostile library, tokenData, dependency, and collection-script inputs, including embedded null/newline bytes in the library URL.Scope Notes
forge build --sizesstill reports the known release blocker thatStreamCoreexceeds EIP-170 at 35,696 runtime bytes with a -11,120 byte runtime margin. The canonical local check remains green for this slice.Local Validation
forge test --match-contract StreamMetadataEscapingTest -vvvforge test --match-path 'test/StreamMetadata*.t.sol' -vvvmake checkpowershell -ExecutionPolicy Bypass -File scripts\check.ps1forge fmt --check smart-contracts\StreamCore.sol test\StreamMetadataEscaping.t.sol test\StreamInitialization.t.sol test\helpers\TestHashingUtils.solgit diff --checkslither . --config-file slither.config.json --foundry-compile-all --json <temp>: unchanged baseline, 718 total findings; High 4 / Medium 19 / Low 93 / Informational 591 / Optimization 11Size Check
forge build --sizesexits nonzero becauseStreamCoreis above EIP-170. This is a known deployment/release blocker, not introduced as a new canonical gate in this PR.Summary by CodeRabbit
Bug Fixes
Tests
Documentation