Commit 7d347ec
committed
fix(desktop): bind only mention pairs this community vouches for
Visibility was the paste's whole trust boundary: a record whose label
appeared in the inserted content was registered, and registration
outlives the paste. Clipboard HTML is attacker-authored, so any copied
page could carry `<span data-mention-pubkey="<their key>"
data-mention-label="John Smith">@john Smith</span>` — plausible, plainly
visible, and accepted. The chip lit, the send carried their key in its
`p` tag, and the name stayed bound for the rest of the session. Seeing a
label only proves the user saw a name, never that the name belongs to
the key beside it; a Buzz provenance marker proves less still, since an
attacker writes the same marker.
The pair itself is now checked against state the community supplied.
Local first — the mention candidates the composer would offer and the
profile lookup the surface renders from, both already in hand — then the
relay's own profile for the pubkey. Labels are compared against
`collectProfileAliases`, the same alias set that turned a `p` tag into
the label the copy carries, so a chip rendered off a kind-0 `name` or a
NIP-05 handle verifies on the alias it was rendered from. Anything
neither source names is dropped: the words paste as readable text and
tag nobody.
That relay lookup is what keeps the headline case working. A mention of
someone who is not a member of the destination channel is exactly what
no local directory can speak to, so it is the case the fetch exists for
— and it is bounded by the record cap the parser already applies, reads
the profile entries `useUsersBatchQuery` maintains before spending a
request, and treats an entry those hooks call stale as no answer.
Verification can need that round trip, so binding lands after the
insertion. The visibility gate therefore runs a second time against what
the composer holds when the answer arrives: an in-flight check whose
paste the user has since deleted or replaced must not bind a name
nothing on screen shows. A composer with no verifier binds nothing, and
a failed lookup binds nothing — the pasted words are already in place
and simply stay plain, so there is no partial state to retry.
`selectBindableMentionIdentities` filters the verifier's answer back
down to what it asked about, so the seam cannot widen into "the verifier
decides what gets bound". `canonicalMentionLabel` moves out of
`matchChipTextToLabel` and is shared, so the copy-side chip classifier
and this check agree on what one name spelled two ways means.
Tests: eleven cases over the hook the composers actually pass, driving
the real `get_users_batch` seam — the forged pair dropped whether the
key is unknown or known under another name, each local source and the
relay vouching on their own, a mixed paste separated, and the cache
freshness rule; four over the bindable selector; and a Playwright case
pasting the visible forged shape into a DM, asserting the lookup ran,
the chip stayed dark, and the sent event carried no impostor `p` tag.
Removing the check lights the chip and fails it; ignoring only its
verdict fails it the same way. The full clipboard spec passes.
Signed-off-by: Matt Toohey <contact@matttoohey.com>1 parent fcc9f32 commit 7d347ec
13 files changed
Lines changed: 797 additions & 72 deletions
File tree
- desktop
- src
- features
- forum/ui
- messages
- lib
- ui
- profile
- tests/e2e
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
360 | 360 | | |
361 | 361 | | |
362 | 362 | | |
| 363 | + | |
| 364 | + | |
| 365 | + | |
| 366 | + | |
363 | 367 | | |
364 | 368 | | |
365 | 369 | | |
| |||
387 | 391 | | |
388 | 392 | | |
389 | 393 | | |
| 394 | + | |
390 | 395 | | |
391 | 396 | | |
392 | 397 | | |
| |||
Lines changed: 89 additions & 29 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
8 | 8 | | |
9 | 9 | | |
10 | 10 | | |
11 | | - | |
| 11 | + | |
12 | 12 | | |
13 | 13 | | |
14 | 14 | | |
| |||
288 | 288 | | |
289 | 289 | | |
290 | 290 | | |
291 | | - | |
| 291 | + | |
292 | 292 | | |
293 | | - | |
294 | | - | |
295 | | - | |
296 | | - | |
| 293 | + | |
| 294 | + | |
| 295 | + | |
| 296 | + | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
| 300 | + | |
| 301 | + | |
| 302 | + | |
297 | 303 | | |
298 | | - | |
| 304 | + | |
299 | 305 | | |
300 | | - | |
301 | | - | |
302 | | - | |
303 | | - | |
304 | | - | |
305 | | - | |
306 | | - | |
307 | | - | |
308 | | - | |
| 306 | + | |
| 307 | + | |
309 | 308 | | |
310 | 309 | | |
311 | | - | |
312 | | - | |
| 310 | + | |
313 | 311 | | |
314 | 312 | | |
315 | | - | |
316 | | - | |
317 | | - | |
318 | | - | |
319 | | - | |
320 | | - | |
321 | | - | |
322 | | - | |
323 | | - | |
324 | | - | |
| 313 | + | |
| 314 | + | |
| 315 | + | |
| 316 | + | |
| 317 | + | |
| 318 | + | |
| 319 | + | |
| 320 | + | |
| 321 | + | |
| 322 | + | |
| 323 | + | |
| 324 | + | |
| 325 | + | |
325 | 326 | | |
326 | | - | |
| 327 | + | |
| 328 | + | |
| 329 | + | |
| 330 | + | |
| 331 | + | |
| 332 | + | |
| 333 | + | |
| 334 | + | |
| 335 | + | |
| 336 | + | |
| 337 | + | |
| 338 | + | |
| 339 | + | |
| 340 | + | |
| 341 | + | |
| 342 | + | |
| 343 | + | |
| 344 | + | |
| 345 | + | |
| 346 | + | |
| 347 | + | |
| 348 | + | |
| 349 | + | |
| 350 | + | |
| 351 | + | |
| 352 | + | |
| 353 | + | |
| 354 | + | |
| 355 | + | |
| 356 | + | |
| 357 | + | |
| 358 | + | |
| 359 | + | |
| 360 | + | |
| 361 | + | |
| 362 | + | |
| 363 | + | |
| 364 | + | |
| 365 | + | |
| 366 | + | |
| 367 | + | |
| 368 | + | |
| 369 | + | |
| 370 | + | |
| 371 | + | |
| 372 | + | |
| 373 | + | |
| 374 | + | |
| 375 | + | |
| 376 | + | |
| 377 | + | |
| 378 | + | |
| 379 | + | |
| 380 | + | |
| 381 | + | |
| 382 | + | |
| 383 | + | |
| 384 | + | |
| 385 | + | |
| 386 | + | |
327 | 387 | | |
328 | 388 | | |
329 | 389 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
28 | 28 | | |
29 | 29 | | |
30 | 30 | | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
31 | 47 | | |
32 | 48 | | |
33 | 49 | | |
| |||
62 | 78 | | |
63 | 79 | | |
64 | 80 | | |
65 | | - | |
66 | | - | |
67 | | - | |
68 | | - | |
69 | | - | |
70 | | - | |
| 81 | + | |
71 | 82 | | |
72 | | - | |
| 83 | + | |
73 | 84 | | |
74 | 85 | | |
75 | 86 | | |
76 | | - | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
77 | 90 | | |
78 | 91 | | |
79 | 92 | | |
| |||
333 | 346 | | |
334 | 347 | | |
335 | 348 | | |
336 | | - | |
| 349 | + | |
337 | 350 | | |
338 | | - | |
339 | | - | |
340 | | - | |
| 351 | + | |
| 352 | + | |
| 353 | + | |
| 354 | + | |
341 | 355 | | |
342 | | - | |
| 356 | + | |
| 357 | + | |
| 358 | + | |
| 359 | + | |
| 360 | + | |
| 361 | + | |
| 362 | + | |
| 363 | + | |
| 364 | + | |
| 365 | + | |
| 366 | + | |
| 367 | + | |
| 368 | + | |
| 369 | + | |
| 370 | + | |
| 371 | + | |
| 372 | + | |
| 373 | + | |
| 374 | + | |
| 375 | + | |
| 376 | + | |
| 377 | + | |
| 378 | + | |
| 379 | + | |
343 | 380 | | |
344 | | - | |
345 | 381 | | |
| 382 | + | |
346 | 383 | | |
347 | 384 | | |
348 | 385 | | |
349 | | - | |
350 | | - | |
351 | | - | |
352 | | - | |
353 | | - | |
354 | 386 | | |
355 | 387 | | |
356 | | - | |
357 | | - | |
| 388 | + | |
| 389 | + | |
| 390 | + | |
358 | 391 | | |
359 | 392 | | |
360 | 393 | | |
361 | | - | |
362 | | - | |
363 | | - | |
364 | | - | |
365 | | - | |
366 | | - | |
| 394 | + | |
| 395 | + | |
| 396 | + | |
| 397 | + | |
| 398 | + | |
367 | 399 | | |
0 commit comments