๐ก๏ธ Sentinel: [MEDIUM] HTML BiDi ํ ์คํธ ์กฐ์ ์ฐํ ๋ฐฉ์ง - #682
seonghobae wants to merge 10 commits into
Conversation
|
๐ Jules, reporting for duty! I'm here to lend a hand with this pull request. When you start a review, I'll add a ๐ emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down. I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job! For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with New to Jules? Learn more at jules.google/docs. For security, I will only act on instructions from the user who triggered this task. |
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews:
auto_review:
drafts: trueThanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Noema LLM review
The BiDi mitigation can be bypassed because escapeHtml() does not encode Unicode directional isolates U+2068/U+2069. A filename containing a literal U+2069 prematurely closes the FSI wrap, exposing surrounding text to malicious directionality and allowing UI spoofing. The fix needs to sanitize or reject directional isolates before approval.
Reviewed changed lines
.jules/sentinel.md:102 (RIGHT): Documentation entry describes FSI/PDI mitigation; no code impact..jules/sentinel.md:103 (RIGHT): Documentation entry describes FSI/PDI mitigation; no code impact..jules/sentinel.md:104 (RIGHT): Documentation entry describes FSI/PDI mitigation; no code impact..jules/sentinel.md:105 (RIGHT): Documentation entry describes FSI/PDI mitigation; no code impact..jules/sentinel.md:106 (RIGHT): Documentation entry describes FSI/PDI mitigation; no code impact.src/main/kotlin/html4tree/main.kt:424 (RIGHT): FSI/PDI wraps escaped directory name in title; wrapping can be broken by literal U+2068/U+2069 because escapeHtml leaves them unencoded.src/main/kotlin/html4tree/main.kt:429 (RIGHT): dir="auto" on h1 handles normal LTR names correctly.src/main/kotlin/html4tree/main.kt:460 (RIGHT): ariaLabel retains escapeHtml before FSI/PDI; still affected by literal directional-isolate bypass.src/main/kotlin/html4tree/main.kt:463 (RIGHT): Title attribute uses same FSI/PDI wrapping and has same bypass risk for literal U+2068/U+2069.src/test/kotlin/html4tree/MainTest.kt:342 (RIGHT): Updated assertion matches current output; does not cover malicious directional isolates.src/test/kotlin/html4tree/MainTest.kt:344 (RIGHT): Updated assertion matches current output; does not cover malicious directional isolates.src/test/kotlin/html4tree/MainTest.kt:945 (RIGHT): Assertion matches escaped title; does not cover malicious directional isolates.src/test/kotlin/html4tree/MainTest.kt:946 (RIGHT): Assertion matches h1 dir attribute; no adversarial case.
Adversarial validation
src/main/kotlin/html4tree/main.kt:424 (RIGHT)confirmed: A directory name containing a literal U+2069 will prematurely close the FSI isolate, breaking the intended BiDi separation. โ escapeHtml tests cover only &, <, >, ", ', `; U+2068/U+2069 are not among encoded characters and pass through unchanged.src/main/kotlin/html4tree/main.kt:429 (RIGHT)falsified: Adding dir="auto" to the h1 could mis-render normal LTR directory names. โ Existing rendering test at MainTest.kt line 946 asserts 'Root
' and passes; no LTR regression observed.- Residual risk: Other places that emit user-controlled text with FSI/PDI wrapping retain the same bypass until directional isolates are encoded or rejected.
Findings
- [medium] src/main/kotlin/html4tree/main.kt:424 (RIGHT): FSI/PDI isolation can be bypassed by filenames containing literal U+2068/U+2069 because escapeHtml() does not encode these characters. A literal U+2069 in the name closes the isolate early, exposing surrounding text to malicious directionality and enabling UI spoofing.
- Result: REQUEST_CHANGES
- Head SHA:
8a70f133349e0055e13291516430ff5f4e4a386d - Reviewer credential:
noema-review-github-app-refresh - Actor:
cwl-noema-review[bot]
|
@jules Fresh causal security finding on current BiDi hardening lane. I added test-first commit Please repair by ordinary descendant, preserving the exact path in URL encoding but neutralizing user-supplied bidirectional formatting controls for display/title contexts before the outer isolation is applied. Cover at least U+061C, U+200E/U+200F, U+202A..U+202E and U+2066..U+2069. Prefer rendering those controls visibly (for example |
Acknowledged. I've updated the |
Scope
BiDi display isolation for user-controlled directory/file names in generated HTML. Protected target:
master@728f0f33323e43573d6664209891099502827d5d. Current exact head:36510f48d859e8fa41a235e9130f4e6f64142087.Predecessor #672์ ์ ํจ source/test delta๋ ์ด branch๊ฐ ์ ๋ถ ์น๊ณํ์์ live patch๋ก ๋ค์ ํ์ธํ๊ณ , #672๋ verified-successor ์กฐ๊ฑด์ผ๋ก unmerged Closeํ์ต๋๋ค. ์ด PR์ด ํ์ฌ canonical implementation/security acceptance owner์ ๋๋ค.
Causal RED and repair lineage
์ด๊ธฐ ๊ตฌํ์
<title>/ linktitle์FSI + escaped filename + PDI๋ก ๊ฐ์ธ๊ณ visible name์dir="auto"๋ฅผ ์ฌ์ฉํ์ต๋๋ค. HTML escaping๋ง์ผ๋ก Unicode directional formatting control์ ์ฌ๋ผ์ง์ง ์์ต๋๋ค. ๊ณต๊ฒฉ์๊ฐ filename์U+2069 PDI๋ฅผ ๋ฃ์ผ๋ฉด outer isolate๋ฅผ filename ์ค๊ฐ์์ ๋๋ผ ์ ์๊ณ , ๋ค์ด์U+202E RLO๊ฐ์ override๊ฐ wrapper ๋ฐ์์ ์๋ํ ์ ์์ต๋๋ค.Test-first commit
3cf2442193eb7a31267c1cdace463e244703d81c๊ฐ hostile filename regression์ ์ถ๊ฐํ์ต๋๋ค. Production์ display/title context์์U+061C,U+200E/U+200F,U+202A..U+202E,U+2066..U+2069๋ฅผ visible\\uXXXXtext๋ก neutralizeํ๋ฉด์ ์ค์ filesystem name์ percent-encodedhrefgeneration์ ๊ทธ๋๋ก ๋ณด์กดํฉ๋๋ค. ์ผ๋ฐ Arabic/Hebrew/CJK/LTR ๋ฌธ์๋ rewriteํ์ง ์์ต๋๋ค.24f5b0ee799019be39d3f57086ea5445b4927f6f์์ generated.jules/sentinel.mddoctrine์ ์ ๊ฑฐํ์ต๋๋ค. CI๊ฐ ์ directional-control branches์ coverage gap์ ์ก์ ๋ค current36510f48d859e8fa41a235e9130f4e6f64142087์์ ๋ชจ๋ supported neutralized code point๋ฅผ exact visible\\uXXXX๋ก ๊ฒ์ฆํ๋ focused coverage contract๋ฅผ ์ถ๊ฐํ์ต๋๋ค. Coverage threshold๋ฅผ ๋ฎ์ถ๊ฑฐ๋ branch๋ฅผ ์ ์ธํ์ง ์์์ต๋๋ค.Unicode UAX #9๊ฐ isolate matching ๋ฐ explicit directional formatting์ normative rationale์ ๋๋ค. U+206A..U+206F๋ ๋ณ๋ deprecated format characters์ด๋ฉฐ ์ด contract์์ current directional-isolate control๋ก ์ฌ๋ถ๋ฅํ์ง ์์ต๋๋ค.
Exact-head verification
36510f48d859e8fa41a235e9130f4e6f64142087์์:34657409996: GREEN34657410033: GREEN34657410003: GREEN34657409995: FAIL โ central settlement ordering๋ฐ๋ผ์ CodeQL failure๋ฅผ leaf source finding์ผ๋ก ์ค๋ถ๋ฅํ์ง ์์ง๋ง, authoritative current-head settlement๊ฐ ์๋ฃ๋๊ธฐ ์ GREEN์ผ๋ก๋ ์ทจ๊ธํ์ง ์์ต๋๋ค. No-op retrigger, synthetic status, gate weakening์ ์ฌ์ฉํ์ง ์์ต๋๋ค.
Delivery Gate
Acceptance before Ready
BidiIsolationSecurityTest, all-code-point neutralization contract์ ๊ธฐ์กด generation/security tests๊ฐ repository 100% coverage๋ฅผ ์ ์งํ๋ฉฐ GREEN์ผ ๊ฒ.href์์ percent-encoded identity๋ก ๋ณด์กด๋๊ณ display/title์๋ contract ๋์ raw directional control์ด ์์ ๊ฒ.Draft ์ ์ง์ ๋๋ค. Browser/a11y ๋ฐ central CodeQL acceptance๊ฐ ์์ผ๋ฏ๋ก ๋ณด์ ์๋ฃ๋ release-ready๋ฅผ ์ฃผ์ฅํ์ง ์์ต๋๋ค.