Client audit 2026-10: tracking index #281
Closed
opened 2026-10-04 17:41:58 -04:00 by jared
·
5 comments
No Branch/Tag Specified
lotus
fix/call-theme-before-ready
fix/dfn-worklet-file
test/lotus-feature-e2e
fix/own-presence-display
fix/sso-uia-desktop
seasonal/lunar
seasonal/newyear
seasonal/christmas
chore/build-hygiene
fix/status-save-speed
chore/typing-hygiene
feat/settings-search
feat/settings-pages
chore/security-deps
feat/settings-quick-wins
feat/data-export
feat/stale-sessions
feat/landscape-call
feat/expected-devices
feat/oauth-detect
chore/ec-0.28
chore/sdk-44
feat/key-upload-recovery
feat/keychain-session
feat/vimeo-events
feat/widget-always-on-screen
feat/call-summary-details
feat/widget-popout
fix/ios-long-press
chore/any-cleanup
chore/soundboard-mic-mix
fix/phone-call-controls
fix/a11y-axe-findings
fix/copy-and-reddit-context
feat/about-build-info
fix/schedule-24h
fix/connecting-strip
fix/ui-polish-batch
fix/outbox-multi-tab
fix/widget-share-hardening
fix/side-panel-width
fix/topic-markdown
fix/acl-ip-literals-default
feat/decorations-host
fix/call-disconnected-bar
fix/linux-update-verify
perf/lazy-settings
fix/dnd-busy-presence
fix/threads-stay-unread
fix/private-note-wording
fix/audio-output-frame-ids
fix/pip-minimise
fix/translate-unavailable-copy
fix/status-expiry-account-data
ci/reseed-bundle-budget
fix/close-no-tray
fix/soundboard-not-permitted
fix/denoise-state-notice
docs/features-catchup
fix/desktop-settings-section
fix/dev-denoise-theme
fix/pwa-manifest
fix/translate-feedback
fix/consent-retry-snooze
fix/strip-metadata-packs
fix/preview-deceptive-links
fix/embed-ogurl-provider
fix/settingtile-nesting
fix/shortcuts-dialog
fix/forward-encryption-warning
fix/compress-alpha-anim
fix/screenshare-double-toast
fix/sw-reply-checks
fix/pip-default-position
fix/inapp-toast-permission
fix/mute-timers-account-data
fix/policy-dedupe
fix/nudge-dismissed-strip
fix/kuma-plain-text
fix/rejoin-dm
fix/search-edit-dupes
fix/room-filter-empty
fix/emoji-board-escape
fix/call-failed-retry
fix/share-links-lotus
fix/poll-vote-local-echo
fix/scheduled-from-server
fix/delayed-restart-dedupe
fix/decline-references-notification
fix/stall-watchdog
fix/filtered-timeline-double-count
fix/call-listener-limit
fix/voice-room-no-room-ping
fix/reactions-collapse-loop
fix/group-call-permission
fix/dialog-enter-closes
fix/delivery-status-live
fix/room-upgrade-lotus-state
fix/quiet-hours-tick
fix/logout-wipe-leftovers
fix/inter-font-name
fix/retention-floor-grace
fix/firefox-persist-hang
fix/phantom-ring-after-reload
fix/local-room-names-rest
fix/missed-call-voice-rooms
fix/animated-bg-compositor
fix/link-safety-bypasses
fix/e2e-register-403
fix/local-room-names-everywhere
fix/collapsible-messages
fix/logout-volume-residue
fix/enter-newline-device-local
fix/dnd-restore-status
fix/presence-sticky
fix/location-confirm
fix/reminders-stick
fix/voice-full-distinct-users
fix/presence-pagehide-status
fix/gif-card-aspect
deps/npm-audit-fixes
security-nudge
linux-package-updates
audit-brace-expansion
server-status-banner
desktop-keychain-mirror
desktop-call-origin
clock-skew-lag
offline-outbox
desktop-lotus-links
poll-ui
calls-open-in-browser
screenshare-prompt
call-origin-split
update-packages
sw-fix
read-me-update
image-path-changes
dm-calls
fix-2469
renovate/element-hq-element-call-embedded-0.x
renovate/npm-i18next-http-backend-vulnerability
renovate/npm-vite-vulnerability
dev
docs-update
more-theme
fix-257
imporve-thread-reply
revert-2402-improve-menu-congestion
mxidColor-toggle
update-sw-main-msg
v4.11.1
v4.10.5
v4.10.4
v4.10.3
v4.10.2
v4.10.1
v4.10.0
v4.9.1
v4.9.0
v4.8.1
v4.8.0
v4.7.1
v4.7.0
v4.6.0
v4.5.1
v4.5.0
v4.4.0
v4.3.2
v4.3.0
v4.2.3
v4.2.2
v4.2.1
v4.2.0
v4.1.0
v4.0.3
v4.0.0
v3.2.0
v3.1.0
v3.0.0
v2.2.6
v2.2.5
v2.2.4
v2.2.3
v2.2.2
v2.2.1
v2.2.0
v2.1.3
v2.1.2
v2.1.1
v2.1.0
v2.0.4
v2.0.3
v2.0.2
v2.0.1
v2.0.0
v1.8.2
v1.8.1
v1.8.0
v1.7.0
v1.6.1
v1.6.0
v1.5.1
v1.5.0
v1.4.0
v1.3.2
v1.3.1
v1.3.0
v1.2.1
v1.2.0
v1.1.0
v1.0.0
Labels
Clear labels
a11y
area: appearance
area: auth-session
area: build-ci
area: calls
area: desktop
area: media
area: messaging
area: mobile
area: moderation
area: navigation
area: notifications
area: settings
area: threads
bug
dependencies
docs
duplicate
enhancement
help wanted
invalid
needs-human-review
performance
planning
priority: critical
priority: high
priority: low
priority: medium
qa
question
research
security
tech-debt
ux
wontfix
Accessibility: keyboard, screen reader, contrast, motion
Client area: appearance
Client area: auth-session
Client area: build-ci
Client area: calls
Client area: desktop
Client area: media
Client area: messaging
Client area: mobile
Client area: moderation
Client area: navigation
Client area: notifications
Client area: settings
Client area: threads
Something is not working
Third-party package versions and advisories
README / LOTUS_* docs wrong or missing
This issue or pull request already exists
New feature
Need some help
Something is wrong
Re-render storms, leaks, heavy work on hot paths
Data loss, security hole, or crash on a main path
Broken feature or serious usability problem
Minor issue or polish
Wrong behaviour in an edge case or notable degradation
Manual QA: shipped, needs a human in a real environment
More information is needed
XSS, unsafe URLs, data leaks, auth/session
Code health, dead code, fragile patterns
Usability or visual inconsistency
This won't be fixed
No labels
Milestone
No items
No Milestone
Projects
Clear projects
No projects
No Assignees
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: LotusGuild/cinny#281
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
October 2026 client audit: tracking issue
Scope: the Lotus-specific integrations on top of upstream: cinny
lotus@30e2dbcd, cinny-desktopmain@8f67ec7(Linux nightly 4.12.377), element-calllotus@3b0050e8, and the production config/CSP inmatrix.How
Every finding was reproduced or verified before filing. Issues already open (e.g. #126, #166, #199, #205, #225) were not refiled.
Labels: one
priority: *, one type (bug/ux/security/a11y), onearea: *, as in #89. New labels created for this audit: cinny-desktopux,security,area: config; matrixbug.Totals: 25 issues (1 high, 7 medium, 17 low): cinny 22, cinny-desktop 2, matrix 1.
High
bugarea: messagingMedium
io.lotus.denoise_stateis unhandled, and the oldlotus-denoise-statuslistener is dead and accepts any windowbugarea: callsallow_ip_literalsas false, so the first save silently blocks IP-literal serversbugarea: moderation_or*(broken links for every client)bugarea: settingsuxarea: navigationbugarea: mobileuxarea: callsframe-srcblocks room widgets (Jitsi, Etherpad, …); web allows thembugarea: configLow
buginfrasecurityarea: auth-session/share-target, and stashed shared files aren't cleared on logoutsecurityarea: messagingbugarea: messagingbugarea: messagingbugarea: settingsuxarea: settingsuxarea: settingsuxarea: settingsuxarea: navigationbugarea: messaginguxarea: desktopuxarea: callsa11yarea: settingsuxarea: settingscontext=, which changes what a comment permalink showsbugarea: messagingbugneeds-human-reviewarea: configChecked and found OK (not filed)
Round 2 — feature test matrix (2026-10-04)
Every Lotus feature found in the fork histories was driven through Playwright: 1,036 cinny commits since the upstream merge base, 365 cinny-desktop commits and ~100 element-call fork commits. The runs used a local Synapse + LiveKit stack, with two or three real accounts and E2EE where relevant. ✅ = works as described; the ❌ items are filed above or in round 1.
language-jsblock; markdown; KaTeX; up-arrow edit; length counter; @mention and :emoji autocomplete; poll creation; location share; voice message record/pause/send; schedule tray + Send nowwebAppUrlon desktop); Copy Text; Report; reply media thumbnail; media grid; audio-file inline playeru.*sections, mark unread (bothm.and famedly keys), rename-for-me, room filter, sort menu, DM previews, quick switcher, jump to time, back-to-where-you-were, invite QR, title unread count, knock → Request to joinfrom:,in:(+ quoted),after:/before:relative, recent searches, operator → chipNot reachable from here (left to the existing QA issues): Windows-only native features (#18, #20); OIDC (#183); real-phone checks (#198).
Measured but not filed. Seasonal overlays render at ~15 fps without a GPU (software raster) against 61 fps with them off. Main-thread cost stays at 1–6%, so this only matters on machines without GPU compositing.
Corrections to round 1
Round 2 issues
High
Medium
Low
(React warnings on every Settings page)
npm start, and every call logs a lotusTransparent/lotusTheme warningRound 3 (2026-10-04)
Decisions recorded (Jared):
New issues
bugarea: calls(medium)UploadCardRenderer→TauriDesktopFeaturessetState-in-render warning (fires on every image upload).Additionally verified working
org.matrix.mjolnir.rule.*).youtube-nocookie).io.lotus.set_quality);/.well-known/matrix/support).Inconclusive / not filed
Round 4 (2026-10-04)
New issues
max_lifetime: 1000blanked the timeline, and 4/4 of my messages were redacted on the server in 40 s.bugarea: messaging(high)securityarea: auth-session(medium)uxarea: calls(low)securityarea: notifications(low)bugarea: settings(low)Additionally verified working
?shortcuts dialog traps focus.check_for_update,update_install_kind, close behaviour; keychain and global hotkeys report unsupported on Linux as expected);24d6460e), so no third-party error reporting.Small items — now filed: #301 (call-load screen has no Try again), #302 (rejoin wording/ended DM calls); pinned-popout focus added to #278; Autumn/Deep Space label added to #279.
Noted, not filed
Round 5 (2026-10-04): cross-browser
initClientawaitsnavigator.storage.persist(), which stays pending in Firefox. (high)isMobile/touch), so phone checks were run in WebKit (iPhone 14) and Chromium only.Round 6 (2026-10-04): rendering cost and infrastructure
margin: -2makes the measured width 4 px larger. Chromium loops at 1348–1351 px (33 layouts and 216 ms of script per 2 s); Firefox loops at the default 1440 px. The same style also wipes the timeline's 8 pxmarginTop(−2 px while collapsed, 0 px after expanding again). (medium)Cache-Control, and a new PHP session (four cookies) for every image. (low)Round 7 (2026-10-05): outbox, status banner, security nudge, share target, call extras
deviceIds differ, the fork falls back to Default, and the host menu still shows ✓. (medium)#,_,*,>and backtick (#room→room,<b>→<b). (low)#309duplicate of #267 (share target): new evidence added there.matrixstatus page has the expected groups, 60 s beats, CORS*, and prod CSP allows it.call.ogg, chime uses oscillators, silent is silent;javascript:URI guard;setState in renderwarning fromUploadCardRenderer.startUpload()(the fork's taskbar-progress hook is the subscriber).refreshRoom()fixes it. (high)call.memberevent instead of thertc.notification. The caller keeps "Calling…" for 90 s, Element X declines don't stop Lotus ringing, and declined calls are logged as "Missed call". (medium)allConnections$→switchMap), and each restart resetsspeakingWhileMutedbefore the host's 1.5 s hold. (medium)from:ask for a word, as designed).IconButton, so it's the form's default submit button. (medium)POST /users/{id}/reportwith[Category] reason(200); a private note saves toio.lotus.user_notesand survives reload; pronouns save tom.pronouns; Pause Notifications ("Paused until …", Resume); the thread notification menu (4 modes, saved to account data); Sort rooms (3 orders); the Advanced Push Rules editor./,/home/…,/login/…) has noCache-Control(thelocation /rewrite bypasses the no-cache block), and deploysrsync --deletethe old hashed assets, so a heuristically cached shell can load a blank app after a deploy. Also: duplicate HSTS and Cache-Control headers. (medium)sw.js,config.json,manifest.jsonand the call page are no-cache; hashed assets are cached for 1 y, immutable; the call page hasframe-ancestors https://chat.lotusguild.organd a scoped Permissions-Policy; the desktop WebView permission allow-list includes the call originhttp://127.0.0.1:44548.m.pronounsformat vs MSC4247 (not confirmed offline).Round 8 (2026-10-05): leaks, resilience, cross-browser
state_updatesubscriber tripsMaxListenersExceededWarning, and the console keeps the warning, theCallControland the whole Element Call document alive. Measured 52 → 97 MB over 5 calls; with the warning suppressed, 0 retained. (medium)fetch failed), #306 (the stuck "Sending..." reproduced with a real stall)..deband.pkg.tar.zstare unsigned: cinny-desktop#36).pagehidedraft flush rewrites it after the wipe. (medium, security).deb/.pkg.tar.zst) have no signature or checksum; the pacman command relies on that. (low, security)logout/allfrom another device wipes IndexedDB and the outbox, then shows the login screen (except the draft, #319).https://chat.lotusguild.org/home/<room>, which the web app redirects to the space path); Join is disabled; the first-close dialog appears and relaunching restores a hidden window.'InterVariable', but@fontsource-variable/inter5 registers'Inter Variable', so prod renders in the system fallback (Liberation Sans, Arial, DejaVu…). On the Linux desktop, emoji also mix monochrome DejaVu and colour Noto glyphs. (medium)m.read.private(room open, thread, sidebar "Mark as read"); hide activity → no typing and private receipts.audioMaxBitrate: 32000,screenshareMaxBitrate: 1500000,screenshareMaxFramerate: 15).io.lotus.focus_participantwith the per-device id.@font-face.Round 9 (2026-10-05): cross-device, call UI, notifications
GET …/msc4140/delayed_eventslists them. (medium)m.marked_unreadpluscom.famedly.marked_unreadand clears both when the room is opened.useNotificationsQuietis only evaluated on re-render; measured toast + sound inside the window with the app left idle, silence only after a reload. The snooze expiry likely has the same problem. (medium)og:urlwith no domain check, and the card links to the attacker's site. (low, security)trust: falseandmaxSize/maxExpandcaps; the sanitizer tightens colours andpreclasses compared with upstream.Round 10 (2026-10-05): upgrades, trust boundaries
m.room.retentionpolicy, so a 7-day-retention room keeps messages forever after an upgrade. (medium)lk-jwt-servicelistens on0.0.0.0:8071(open from another LAN host), so LAN clients can mint tokens directly and skip the voice-limit/audio-only guard. Also other internals bound to0.0.0.0. (low, security)matrix:URIs only navigate; unjoined rooms go to the preview/join flow; no auto-join or auto-DM.widgetId: "call-embed"is rejected (restrictWidgetMessageschecks source and origin for the call embed and room widgets).127.0.0.1:44548) has no IPC object (capabilityremote.urls=localhost:44548only).[PostmessageTransport] Sending objectlog; during calls the fork'sio.lotus.mic_level(~10/s) prints two console lines per message.call.memberstays atstate_default50 (the PL-0 override exists only for voice rooms). Members get no ring, and see "1 Live · Join", then "You don't have permission to join!". (medium)io.lotus.user_notes) that server admins can read. (low, security)canPublishSourcesrefuses ("insufficient permissions"), and the host shows nothing. (medium)canPublishSources: ["microphone"], and open rooms are unrestricted.isValidDecorationSlug), including those sent to calls.Round 11 (2026-10-05)
rgba(0,0,0,255)) and animated GIF/WebP into a still JPEG; only PNG is skipped. (low)io.lotus.soundboard, and children keepm.space.parentpointing at the old space.Retry-After.npm test: 1319 pass / 2 skipped.tsc --noEmit: clean.--max-warnings 36limit).vitest src/lotus: 116 pass./login/evil-homeserver.example/→/login/matrix.lotusguild.org), so a link can't turn the real Lotus login page into a credential phish.Round 12 (2026-10-05)
?) lists 7 shortcuts. It omits Ctrl+K, ↑ to edit, all composer formatting keys, and the user's push-to-talk and deafen keys. (low, a11y)x.github.iovsevil.github.io,pages.dev); there's no Public Suffix List. (low, security)img_index(carousel position) is stripped as if it were tracking.analyzeLinkflags userinfo (good@evil), lookalike-suffix (good.org.evil.example) and punycode homograph links.Round 13 (2026-10-05)
background-position, so the whole chat area repaints every frame (45–70 % main-thread busy while idle in headless testing; pause / reduced motion are respected). (low, performance)pagehidewrite{"presence":"offline"}omitsstatus_msg, which Synapse treats as clearing it (verified directly; intermittent because of the 10 s presence limit). Linked from #300. (medium)/home/.pagehidekeeps your custom status, both while you're online and after Synapse marks you unavailable (the heartbeat re-sends the server's status).document.hidden;requestAnimationFramedrops to 0 frames and timers are throttled (comment on #337).Round 14 (2026-10-10)
aria-expanded; the fade leaves a band in bubble layout. (low, a11y)pg-13; picker sends carry the realdownsizedw/h.npm auditfails on the new high advisory in source-map-js 1.2.1 (sanitize-html → postcss); 1.2.2 fixes it. (high, build-ci)lotuspush CI at022e5e69is green incl. e2e, and the desktop build was triggered. chat.lotusguild.org serves the new bundle (KaTeX chunk 0.18.11, the new GIF card).lotus-per-user-volume(who you adjusted in calls, with their volumes) andsettings-sync-meta:<userId>in localStorage. (low, privacy)Fix batch 1 (2026-10-12), merged and deployed
;u=.lotuspush CI at1618d71eis green incl. e2e; chat.lotusguild.org redeployed 03:35 GMT.Fix batch 2 (2026-10-12)
Fix batch 3 (2026-10-12)
Fix batch 4 (2026-10-16/17), merged and deployed 01:09 GMT
utils/callRing.ts). Reported by Jared.Fix batch (October audit, continued)
Element Call fork
sendNotificationType=none, released as 0.25.0-lotus.23 and pinned in #378.Not fixed in a PR
Every PR has before/after measurements against the local stack in its description. The merges go through one CI runner, about 20 min per PR.
🤖 Claude Code
Follow-up batch
cinny
fix/call-disconnected-barelement-call: #50 (call error / reconnect), #51 (#45 mic-sampler churn), #52 (#47 not_permitted), #53 (#43
LOTUS.mdprotocol docs), #54 (#46: a stall shorter than the leave window no longer ends the call; with prod config a 40 s stall went from "Connection lost" to no drop). #44 closed (lotus.24).cinny-desktop (open PRs, not merged):
frame-src https:so room widgets load.has_tray_hostnative command.matrix (open PRs, production changes, waiting for the owner):
🤖 Claude Code
First-round findings (#259–#280): fix batch
allow_ip_literalsmeans allowed#alias:server,@user:servercontext=keptaria-pressed, labels, avatar alt, placeholder contrast; the a11y spec covers more pagesSec-Fetch-Sitecheck can't work, because fetch-metadata headers never reach a service worker (logged). The worker usesOrigininstead, and /share now says where the content came from.opacity: 0.333overrode it.🤖 Claude Code
Complete. All 25 audit issues are closed: cinny #259–#280, cinny-desktop #33 and #34, and matrix #18. The checkboxes above were never ticked as they closed. Closing the index.
🤖 Generated with Claude Code
Correction: the check covered every round, not just round 1. Every issue filed from this audit is closed:
🤖 Generated with Claude Code