Skip to content

fix(web): type-safe peer_color blocks css inject#399

Merged
intendednull merged 1 commit into
mainfrom
claude/issue-191-peer-color
Apr 27, 2026
Merged

fix(web): type-safe peer_color blocks css inject#399
intendednull merged 1 commit into
mainfrom
claude/issue-191-peer-color

Conversation

@intendednull
Copy link
Copy Markdown
Owner

Why

peer_color(&str) build inline style="color: hsl(...)". Output today only made of digits + hsl(),% so safe — but signature take any string. Future bad caller pass attacker text → CSS injection (data exfil, layout break, position:absolute overlay). Type signature lie about what input safe.

Fix

Pick Option C: change peer_color(&EndpointId) -> String. Bad string can't even reach func — compiler block it. Hash still over base32 form so colors stable for valid peer ids.

Two old caller hold String (member_list, profile_card). For them add thin wrapper peer_color_from_str(&str) -> String — parse to EndpointId, fall back to neutral grey hsl(0, 0%, 70%) on garbage. Wrapper small + isolated; if those String upstreams ever get retyped to EndpointId, drop the wrapper.

Runner-up rejected: Option B (CSS custom property --peer-hue). Need CSS edits across the styles, bigger diff, no extra type guarantee — just smaller injection slot. Option C kill the surface at the type, smaller blast radius.

Test

  • Added charset test for peer_color output (only digits + hsl(),% ).
  • Added determinism test (same id → same color).
  • Added wrapper-equiv test (valid id.to_string() → same color as typed).
  • Added garbage-string fallback test.
  • Existing render tests still pass.

Verify

  • cargo test -p willow-web --lib peer_color — 4 new tests pass.
  • cargo clippy --workspace --all-targets -- -D warnings — clean.
  • cargo fmt --check — clean.
  • just check-wasm — clean.
  • Full cargo test --workspace clean except willow-actor::ask_dead_actor_returns_closed, a pre-existing flake unrelated to web/CSS — passes in isolation.

Closes #191


Generated by Claude Code

`peer_color` took `&str` so future caller could pass attacker
string into inline `style=`. Now takes `&EndpointId`. Add
`peer_color_from_str` for legacy String call sites; falls back
to neutral grey on parse fail. Add charset test locking output
to digits + `hsl(),% `.

Closes #191
@intendednull intendednull merged commit 8c9a61b into main Apr 27, 2026
7 checks passed
@intendednull intendednull deleted the claude/issue-191-peer-color branch April 27, 2026 08:54
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] CSS injection surface via peer_color inline style attribute

2 participants