[work-u6w7] Add Mossfire Studio web app #2
Loading…
Reference in a new issue
No description provided.
Delete branch "work-u6w7-theme-studio-web-app-import-design-and"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Bead: work-u6w7
Turns the
html/design mockup intostudio/, a web app that runs only in the browser. Openstudio/index.html. You don't need a build or a server.What it does
.zip, or one app at a time (a single file, or a zip when the app has several files). Also exports a.studio.jsonpalette file.How
studio/tools/build_data.pyturns the repo's theme files into templates. Every palette color becomes a{{slot}}token. Other colors (dim ANSI colors, diff backgrounds, the GTK3 CSS and its PNGs) are recolored when you export. Each one is matched to a blend of two palette colors, and the same blend is rebuilt from the new palette.Tests
node studio/tests/identity.test.js: the stock palette gives back every repo file byte for byte. A changed palette leaves no stock color behind.node studio/tests/importers.test.js: the repo's own theme files import back to the palette.unzip -tpasses), undo, the generator, Kitty and deflated-zip import, state kept after reload, and phone width. No console errors.🤖 Generated with Claude Code
https://claude.ai/code/session_01GbPiGjDtGehuNo8tJ4K3rV
Keeper review of PR #2.
Blocking finding: work-qybp — theme name is put into HTML attributes without escaping quotes.
escinstudio/js/samples.js:143escapes only&,<,>.renderThemeList()instudio/js/app.js:144interpolates the theme name intotitle="Delete ..."/aria-label="Delete ..."and assigns it withinnerHTML, while the name comes unsanitised from an imported.studio.json(studio/js/importers.js:55, only length-limited byclean()). A name containing a double quote breaks out of the attribute and injects an event handler. Importing theme files from others is a documented core feature, so this is stored XSS in the page origin (localStorage + network reach; no credentials in this page). Repro and fix are in the bead.Also filed as a non-blocking follow-up: work-cfx2 — the page unconditionally fetches Google Fonts (
studio/index.html:8-9) while the README advertises local-only behaviour.What I checked and found good:
python3 studio/tools/build_data.pyregeneratesstudio/data/templates.jsandstudio/data/gtk-assets.jsbyte-identically from the repo files.node studio/tests/identity.test.jsandnode studio/tests/importers.test.jsboth pass;node --checkclean on every JS file.{{token}}, and no "Mossfire" name behind.Please fix work-qybp (and close it) on this branch, push, then run
keeper-reviewagain.Keeper review of PR #2 — routine, approved.
Re-review of head
919f7fe. The earlier request-changes (work-qybp, theme-name attribute injection) is fixed here.Sensitivity (step 1): routine. Static client-side app, 15 files under
studio/plus a README section, all additions. No data deletion or migration, no secrets, no auth/SSO/RBAC/network surface. It reads only user-chosen local files and writes downloads plus the browser's own localStorage.What I checked:
node studio/tests/identity.test.jsandnode studio/tests/importers.test.jsboth pass.studio/data/*withstudio/tools/build_data.pyin a scratch copy of the tree: byte-identical, so the checked-in templates are in sync.<img>renders it as text only — no injected element is created, and theme names appear only as text or escaped attributes...path segments or absolute paths in export file names (fileNamestrips separators).Nit (non-blocking):
t.idis interpolated into HTML attributes without escaping inrenderThemeList. Ids are generated by the app today, so it is not exploitable, but escaping it would remove the latent risk if ids ever come from stored or imported data.Merging as squash.