Skip to content

fix(markdown): enforce explicit trust posture - #75

Merged
64ix merged 3 commits into
fork-mainfrom
codex/issue-59-markdown-trust
Aug 5, 2026
Merged

fix(markdown): enforce explicit trust posture#75
64ix merged 3 commits into
fork-mainfrom
codex/issue-59-markdown-trust

Conversation

@64ix

@64ix 64ix commented Aug 5, 2026

Copy link
Copy Markdown
Owner

Closes #59.

Summary

  • require every MarkdownRenderer caller to choose a trust posture
  • block raw HTML, remote images, and unclaimed navigation for untrusted content
  • audit all current call sites and add rendered-DOM security coverage

Checks

  • packages workspace build
  • app typecheck and release-script typecheck
  • targeted oxlint
  • markdown-renderer node tests (7 passed)
  • browser test not run locally: Playwright Chromium is not installed

64ix and others added 3 commits August 5, 2026 22:24
The default-deny added to handleAnchorClick preventDefault()s every click before
dispatching, which is right for the hrefs this renderer owns — an unclaimed
relative href would navigate the whole renderer away from the app — but it also
swallowed `#fragment` links, in trusted content as well as untrusted.

A fragment cannot leave the document, reach the network, or leak anything, and a
rendered README's table of contents consists of nothing else. Both neighbours
already treat them that way: html-renderer.tsx exempts `#` alongside absolute
schemes, and resolveWorkspaceResourcePath returns null for them rather than
resolving a path, so openWorkspaceLink was declining them anyway and the click
simply did nothing.

Pinned in the node test project, which CI runs, rather than the browser project,
which it does not; both assertions fail without the guard.
@64ix
64ix force-pushed the codex/issue-59-markdown-trust branch from b8bbcda to c980fac Compare August 5, 2026 20:26
@64ix
64ix marked this pull request as ready for review August 5, 2026 20:30
@64ix
64ix merged commit a944c8a into fork-main Aug 5, 2026
1 check passed
@64ix
64ix deleted the codex/issue-59-markdown-trust branch August 5, 2026 20:30
64ix added a commit that referenced this pull request Aug 5, 2026
`ipc.ts` guarded on `typeof window !== 'undefined'` and then read
`window.electronAPI`, so outside Electron — browser-mode tests, Storybook — it took
the first branch and left `electronAPI` undefined. The `createRPCClient` call one line
down then threw while the module was still evaluating, which took down every module
that transitively imports it, at import time, before any test body ran.

That is how #75's browser suite shipped red: `markdown-renderer-security.test.tsx`
failed with `Cannot read properties of undefined (reading 'invoke')` and nothing
noticed, because fork-ci.yml runs node/main-db/migrations/scripts and not the browser
project. Guarding on the bridge itself makes the unavailable-channel errors below
reachable, which is what they were written for.

The suite also needed the ipc stub every other renderer test installs: importing the
markdown renderer constructs the SSH connection store, whose Resources call RPC from
their constructor, and those rejections failed the file even with both assertions
passing.

Full workspace suite now green: 398 files, browser project included.

Co-authored-by: 64ix <64ix@users.noreply.github.com>
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.

Shared MarkdownRenderer follows remote images and parses raw HTML before sanitizing — unsafe for untrusted content

1 participant