Skip to content

Audit fixes 2026-07-14: import/share XSS, data integrity, validation - #23

Merged
ollikurki merged 1 commit into
mainfrom
fix/audit-2026-07-14
Jul 14, 2026
Merged

ollikurki merged 1 commit into
mainfrom
fix/audit-2026-07-14

Conversation

@ollikurki

Copy link
Copy Markdown
Contributor

Closes #22. codex audit + PO line-by-line review of every fix. #12 (publish localStorage hook) left as-is — deliberate owner test hook, server rejects independently (verified).

Security (XSS via imported/shared page JSON)

# Sev Fix
1 high meta.surface + photoShape allowlisted like siblings; body class escAttr-escaped
2 high invalid custom accent → canonical palette fallback; only #rrggbb to CSS
4 med imported image dataURL validated (MIME+size+base64+magic bytes) + escaped before srcdoc
6 med email split across data-attrs, assembled on click — no full address in source/text/attr

Data integrity + robustness

# Fix
3 page IDs crypto.randomUUID(); dup IDs migrated on load (was length-based → collision/data-loss)
7,8 complete SiteData decoder for saved-state load and file import (was version+name only → .forEach crash)
9 import fully replaces draft incl lang/favicon
10 undo: structural always snapshots; only same-control text coalesces
11 persistence returns success/failure; unsaved warning on quota fail
5 AA guard fits foregrounds vs bg and surface
13 QR byte-limit guard + friendly error
14 OG long-name wrap/truncate

Verification (ran locally)

  • 175 tests pass (was 157; added hostile image/look fixtures, DOM-security, decoder, history, OG, QR, contrast)
  • typecheck pass
  • surface allowlist == types.ts union card|flat|bordered|tinted; photoShape == circle|rounded|square — no regression
  • validImageDataUrl checks MIME + size + base64 + JPEG/PNG magic bytes

Note

Email links now require JS (activation script) to assemble the address — a deliberate trade for scraper resistance. Generated pages are browser-viewed; acceptable.

…rity)

Closes #22. Read-only audit (codex) + PO line-by-line review. (#12 publish
localStorage hook left as-is: deliberate owner test hook, server-authoritative.)

Security (XSS-via-import/share):
- meta.surface + photoShape now allowlisted like their siblings, and the body
  class is escAttr-escaped (hostile imported/shared meta can no longer inject a
  body attribute)
- invalid custom accent falls back to a canonical palette color; only #rrggbb
  reaches CSS (was returned unchanged -> CSS injection)
- imported image data URLs validated (MIME + size + base64 + magic bytes) and
  escAttr-escaped before entering the preview srcdoc
- email links split across data attributes, assembled on click; no complete
  address in source, text, or a single attribute

Data integrity + robustness:
- page IDs use crypto.randomUUID(); duplicate stored IDs migrated on load
  (was length-based -> create/delete/create collision + data loss)
- new complete SiteData runtime decoder validates/defaults arrays, sections,
  items, images, meta; applied to both saved-state load and file import
  (was version+name only -> links:null / links:{} crashed on load/import)
- import fully replaces the draft incl lang/favicon; clears absent optionals
- history: structural changes always snapshot; only same-control text edits
  coalesce (was 800ms blanket coalescing -> undo dropped a typed name)
- persistence returns success/failure; unsaved warning shown on quota failure
- AA guard fits foregrounds against both bg and surface; rejects impossible
  custom surface
- QR enforces the version-40 byte limit with a friendly error (was uncaught throw)
- OG long names wrap + grapheme-truncate below 36px (was clipped)

175 tests pass (was 157; added hostile image/look fixtures, DOM-security,
decoder, history, OG, contrast, QR coverage; happy-dom dev dep for parsed-DOM
assertions). typecheck passes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TmgNzbG2MaXd1ckGxmuEfu
@ollikurki
ollikurki merged commit fc24e03 into main Jul 14, 2026
1 check passed
@ollikurki
ollikurki deleted the fix/audit-2026-07-14 branch July 14, 2026 13:16
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.

Audit 2026-07-14: XSS-via-import, data-integrity, validation

1 participant