fix(web): don't crash reading a non-object thread-layout entry - #6677
Merged
Conversation
sanitizeThreadLayout assumed its argument was an object. readStore's own filter only checks the stored tuple's shape ([id, layout], id a string) — it never validates that the layout half is an object, so a tampered/malformed sessionStorage entry like ["a", null] passes the filter and crashes sanitizeThreadLayout with a TypeError on layout.tab, taking down readThreadLayout (and anything that calls it, e.g. a thread switch) with it. The module's own doc comment says stored JSON can be tampered with and every read is sanitized — this closes that gap.
decocms Bot
pushed a commit
that referenced
this pull request
Aug 28, 2026
PR: #6677 fix(web): don't crash reading a non-object thread-layout entry Bump type: patch - decocms (apps/api/package.json): 4.291.0 -> 4.291.1 - @decocms/native (apps/native/package.json): 4.291.0 -> 4.291.1 Deploy-Scope: web
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Source: a bug found reading
apps/web/src/lib/thread-layout-memory.ts(recently touched by #6667, the destination-by-path work).Why:
sanitizeThreadLayout(the boundary the module's own comment claims sanitizes every read of tampered/untrustedsessionStorageJSON) assumes its argument is an object.readStore's validation only checks the stored tuple's shape ([id, layout],ida string) — it never checks thatlayoutitself is an object. A malformed entry such as["a", null](privacy-mode quirks, a manual tamper, or a future format bug) passes that filter, andsanitizeThreadLayout(null)throws aTypeErroronlayout.tab, which propagates out ofreadThreadLayout— called on every thread switch (resolveTaskSwitchSearch) — crashing that flow instead of degrading to "no memory" as the module promises.Fix:
sanitizeThreadLayoutnow returns{}fornull/non-object input instead of throwing, matching every other tampered-value case it already handles.Regression test:
thread-layout-memory.test.ts— new case feedsnull/undefined/a string/a number/an array intosanitizeThreadLayoutand asserts it returns{}instead of throwing.Reviewer command:
bun test apps/web/src/lib/thread-layout-memory.test.tsLocal checks run:
bun run fmt,bunx oxlint apps/web/src/lib/thread-layout-memory.ts apps/web/src/lib/thread-layout-memory.test.ts(clean), and the targeted test file above (8 pass). Skipped the workspacetsc --noEmit— it fails on a pre-existing, unrelated prosemirror version-mismatch error inmention-suggestion.tsxthat predates this change. Full CI validates the rest.Summary by cubic
Fixes a crash when reading a tampered or malformed thread-layout entry from
sessionStorage.sanitizeThreadLayoutnow returns{}for non-object input instead of throwing, soreadThreadLayoutno longer blows up on entries like["a", null]and degrades to "no memory" as the module promises. Adds a regression test coveringnull,undefined, strings, numbers, and arrays.Written for commit 0364f79. Summary will update on new commits.