Conversation
dfb88b0 to
e4fa884
Compare
There was a problem hiding this comment.
Findings
-
[Major] Untrusted iframe content can toggle interaction mode via forged
postMessage—onParentMessageaccepts any message with__codesign/typeand does not verify sender, so generated page code can self-postSET_MODEand force comment interception unexpectedly, evidencepackages/runtime/src/overlay.ts:79
Suggested fix:function onParentMessage(ev) { if (!ev || ev.source !== window.parent) return; var data = ev.data; if (!data || data.__codesign !== true || data.type !== 'SET_MODE') return; var next = data.mode === 'comment' ? 'comment' : 'default'; if (next === currentMode) return; currentMode = next; if (currentMode === 'default') clearHover(); }
-
[Minor] Hardcoded color in toolbar button breaks token-only UI rule — added class uses literal
text-whiteinstead of a design token, evidenceapps/desktop/src/renderer/src/components/PreviewToolbar.tsx:166
Suggested fix:commentActive ? 'border-[var(--color-accent)] bg-[var(--color-accent)] text-[var(--color-text-on-accent)] hover:bg-[var(--color-accent-hover)]' : 'border-[var(--color-border)] bg-[var(--color-surface)] text-[var(--color-text-primary)] hover:bg-[var(--color-surface-hover)] hover:border-[var(--color-border-strong)]'
Summary
- Review mode: initial
- 2 issues found in the latest diff (1 Major, 1 Minor).
docs/VISION.mdanddocs/PRINCIPLES.md: Not found in repo/docs.- Residual risk: no automated coverage added for preview-runtime message trust boundary in this PR.
Testing
- Not run (automation)
open-codesign Bot
| } | ||
| function onParentMessage(ev) { | ||
| var data = ev && ev.data; | ||
| if (!data || data.__codesign !== true || data.type !== 'SET_MODE') return; |
There was a problem hiding this comment.
onParentMessage currently trusts any sender. Please gate on ev.source === window.parent before parsing data so untrusted iframe scripts cannot self-toggle comment mode via forged postMessage.
| onClick={() => setInteractionMode(commentActive ? 'default' : 'comment')} | ||
| className={`inline-flex items-center gap-1.5 h-[var(--size-control-xs)] px-3 rounded-[var(--radius-md)] text-[var(--text-sm)] font-medium border transition-[background-color,border-color,color] duration-[var(--duration-fast)] ease-[var(--ease-out)] disabled:opacity-40 disabled:pointer-events-none ${ | ||
| commentActive | ||
| ? 'border-[var(--color-accent)] bg-[var(--color-accent)] text-white hover:bg-[var(--color-accent-hover)]' |
There was a problem hiding this comment.
This introduces a literal color class (text-white). Please switch to a UI token class (for example text-[var(--color-text-on-accent)]) to satisfy the token-only styling constraint.
There was a problem hiding this comment.
Findings
-
[Major] Missing sender validation on
SET_MODEcontrol message —onParentMessageaccepts anymessageevent with the right envelope and does not verifyev.source === window.parent, so untrusted in-iframe scripts can forge control messages and toggle interaction mode. Evidence:packages/runtime/src/overlay.ts:77
Suggested fix:function onParentMessage(ev) { if (!ev || ev.source !== window.parent) return; var data = ev.data; if (!data || data.__codesign !== true || data.type !== 'SET_MODE') return; var next = data.mode === 'comment' ? 'comment' : 'default'; if (next === currentMode) return; currentMode = next; if (currentMode === 'default') clearHover(); }
-
[Minor] Hardcoded text color violates token-only UI constraint — active comment-mode button uses
text-whiteinstead of a UI token-backed color. Evidence:apps/desktop/src/renderer/src/components/PreviewToolbar.tsx:166
Suggested fix:commentActive ? 'border-[var(--color-accent)] bg-[var(--color-accent)] text-[var(--color-text-on-accent)] hover:bg-[var(--color-accent-hover)]' : 'border-[var(--color-border)] bg-[var(--color-surface)] text-[var(--color-text-primary)] hover:bg-[var(--color-surface-hover)] hover:border-[var(--color-border-strong)]'
Summary
- Review mode: follow-up after new commits
- 2 issues found in the latest diff (1 Major, 1 Minor).
docs/VISION.mdanddocs/PRINCIPLES.md: Not found in repo/docs.- Residual risk: no integration test asserts that forged iframe
SET_MODEmessages are ignored at runtime boundary.
Testing
- Not run (automation)
open-codesign Bot
| } | ||
| function onParentMessage(ev) { | ||
| var data = ev && ev.data; | ||
| if (!data || data.__codesign !== true || data.type !== 'SET_MODE') return; |
There was a problem hiding this comment.
onParentMessage still trusts any message sender. Please gate on ev.source === window.parent before accepting SET_MODE to prevent forged control messages from untrusted iframe code.
Suggested patch:
if (!ev || ev.source !== window.parent) return;
const data = ev.data;
if (!data || data.__codesign !== true || data.type !== "SET_MODE") return;| onClick={() => setInteractionMode(commentActive ? 'default' : 'comment')} | ||
| className={`inline-flex items-center gap-1.5 h-[var(--size-control-xs)] px-3 rounded-[var(--radius-md)] text-[var(--text-sm)] font-medium border transition-[background-color,border-color,color] duration-[var(--duration-fast)] ease-[var(--ease-out)] disabled:opacity-40 disabled:pointer-events-none ${ | ||
| commentActive | ||
| ? 'border-[var(--color-accent)] bg-[var(--color-accent)] text-white hover:bg-[var(--color-accent-hover)]' |
There was a problem hiding this comment.
This adds a literal color class (text-white), which conflicts with the token-only UI rule. Please switch to a token, e.g. text-[var(--color-text-on-accent)].
Suggested patch:
commentActive
? "border-[var(--color-accent)] bg-[var(--color-accent)] text-[var(--color-text-on-accent)] hover:bg-[var(--color-accent-hover)]"
: "border-[var(--color-border)] bg-[var(--color-surface)] text-[var(--color-text-primary)] hover:bg-[var(--color-surface-hover)] hover:border-[var(--color-border-strong)]"Codex review on PR #75 flagged: the iframe-side `onParentMessage` handler checks the message envelope (__codesign + type=SET_MODE) but never confirms the event actually originated from window.parent. Untrusted in-iframe scripts can synthesise MessageEvent-shaped objects or bounce events off the iframe itself via window.postMessage(self,...), both of which would slip past the type check. Today only SET_MODE is processed and the worst case is a no-op mode flip, but the structural fix protects every future control type added to the switch. - overlay.ts: reject onParentMessage events whose ev.source !== window.parent - overlay.test.ts: harness captures the registered message + click listeners and asserts a forged-source SET_MODE leaves currentMode unchanged (click still passes through), while the same envelope from window.parent flips into comment mode (click is intercepted)
e07c92c to
0865b6b
Compare
|
Addressed Codex review (Major) on the missing sender validation for the SET_MODE control message. Latest force-push (
Branch was rebased onto latest Verified locally:
|
There was a problem hiding this comment.
Findings
-
[Major] Silent fallback hides preview control-channel failures — both new
postMessagecalls catch and ignore errors, which breaks the "no silent fallbacks" constraint and makes mode-sync failures invisible to users. Evidenceapps/desktop/src/renderer/src/components/PreviewPane.tsx:126,apps/desktop/src/renderer/src/components/PreviewPane.tsx:186
Suggested fix:} catch (err) { pushIframeError(formatIframeError('bridge', 'Failed to sync preview interaction mode')); console.warn('[PreviewPane] failed to post SET_MODE', err); }
-
[Minor] Hardcoded color class violates token-only UI rule — active comment mode uses
text-whiteinstead of a UI token-backed value. Evidenceapps/desktop/src/renderer/src/components/PreviewToolbar.tsx:181
Suggested fix:commentActive ? 'border-[var(--color-accent)] bg-[var(--color-accent)] text-[var(--color-text-on-accent)] hover:bg-[var(--color-accent-hover)]' : 'border-[var(--color-border)] bg-[var(--color-surface)] text-[var(--color-text-primary)] hover:bg-[var(--color-surface-hover)] hover:border-[var(--color-border-strong)]'
Summary
- Review mode: follow-up after new commits
- 2 issues found in the latest diff (1 Major, 1 Minor).
docs/VISION.mdanddocs/PRINCIPLES.md: Not found in repo/docs.
Testing
- Not run (automation)
open-codesign Bot
| if (!win) return; | ||
| try { | ||
| win.postMessage({ __codesign: true, type: 'SET_MODE', mode: interactionMode }, '*'); | ||
| } catch { |
There was a problem hiding this comment.
This catch swallows a newly introduced control-channel failure. Given the project constraint of no silent fallbacks, please surface this (UI error and/or throw with context) instead of ignoring it.
Suggested patch:
} catch (err) {
pushIframeError(formatIframeError('bridge', 'Failed to sync preview interaction mode'));
console.warn('[PreviewPane] failed to post SET_MODE', err);
}| onClick={() => setInteractionMode(commentActive ? 'default' : 'comment')} | ||
| className={`inline-flex items-center gap-1.5 h-[var(--size-control-xs)] px-3 rounded-[var(--radius-md)] text-[var(--text-sm)] font-medium border transition-[background-color,border-color,color] duration-[var(--duration-fast)] ease-[var(--ease-out)] disabled:opacity-40 disabled:pointer-events-none ${ | ||
| commentActive | ||
| ? 'border-[var(--color-accent)] bg-[var(--color-accent)] text-white hover:bg-[var(--color-accent-hover)]' |
There was a problem hiding this comment.
This adds text-white, which violates the token-only UI value rule. Please use a token-backed text color for the active state.
Suggested patch:
commentActive
? 'border-[var(--color-accent)] bg-[var(--color-accent)] text-[var(--color-text-on-accent)] hover:bg-[var(--color-accent-hover)]'
: 'border-[var(--color-border)] bg-[var(--color-surface)] text-[var(--color-text-primary)] hover:bg-[var(--color-surface-hover)] hover:border-[var(--color-border-strong)]'|
Addressed the Codex [Major] finding on Both SET_MODE Commit: bb442ec |
There was a problem hiding this comment.
Findings
- [Minor] Hardcoded color class violates token-only UI rule — active comment state uses
text-white, which bypassespackages/uitoken values required by project constraints. Evidenceapps/desktop/src/renderer/src/components/PreviewToolbar.tsx:181
Suggested fix:commentActive ? 'border-[var(--color-accent)] bg-[var(--color-accent)] text-[var(--color-text-on-accent)] hover:bg-[var(--color-accent-hover)]' : 'border-[var(--color-border)] bg-[var(--color-surface)] text-[var(--color-text-primary)] hover:bg-[var(--color-surface-hover)] hover:border-[var(--color-border-strong)]'
Summary
- Review mode: follow-up after new commits
- 1 issue found in the latest diff (Minor).
docs/VISION.mdanddocs/PRINCIPLES.md: Not found in repo/docs.
Testing
- Not run (automation)
open-codesign Bot
| onClick={() => setInteractionMode(commentActive ? 'default' : 'comment')} | ||
| className={`inline-flex items-center gap-1.5 h-[var(--size-control-xs)] px-3 rounded-[var(--radius-md)] text-[var(--text-sm)] font-medium border transition-[background-color,border-color,color] duration-[var(--duration-fast)] ease-[var(--ease-out)] disabled:opacity-40 disabled:pointer-events-none ${ | ||
| commentActive | ||
| ? 'border-[var(--color-accent)] bg-[var(--color-accent)] text-white hover:bg-[var(--color-accent-hover)]' |
There was a problem hiding this comment.
This introduces text-white, which violates the token-only UI value rule in project constraints. Please switch to a token-backed text color for the active state.
Suggested patch:
commentActive
? 'border-[var(--color-accent)] bg-[var(--color-accent)] text-[var(--color-text-on-accent)] hover:bg-[var(--color-accent-hover)]'
: 'border-[var(--color-border)] bg-[var(--color-surface)] text-[var(--color-text-primary)] hover:bg-[var(--color-surface-hover)] hover:border-[var(--color-border-strong)]'The runtime overlay used to always intercept hover and click on the iframe. That broke the underlying design (links unclickable, every click popped the comment composer) and contradicted Claude Design's mode-based interaction. Add an explicit Comment mode the user enters from the preview toolbar; until then the iframe behaves normally. - store: interactionMode (default | comment) + setter that clears selectedElement when leaving comment mode - runtime overlay: gate mouseover/mouseout/click on currentMode and accept SET_MODE postMessage from the parent; clear outline on exit - PreviewPane: post SET_MODE on mode change and on iframe load; only render InlineCommentComposer + comment hint in comment mode - PreviewToolbar: Comment mode button (lucide MessageSquare) with active token styling - App: ESC exits comment mode before navigating views - i18n: preview.commentMode + preview.commentModeHint (en + zh-CN) - tests: store interactionMode default, set, and selection cleanup
…SET_MODE) Untrusted iframe content could call window.parent.postMessage with a SET_MODE envelope. Today the listener happens to ignore it, but that is incidental — any future handler additions would silently expose host state to model-generated code. Replace the implicit ignore with an explicit type-allowlist switch (ELEMENT_SELECTED, IFRAME_ERROR) that warns on unknown types. SET_MODE remains parent → iframe only. Vitest covers the trust boundary: a forged SET_MODE is rejected and interactionMode stays unchanged.
Codex review on PR #75 flagged: the iframe-side `onParentMessage` handler checks the message envelope (__codesign + type=SET_MODE) but never confirms the event actually originated from window.parent. Untrusted in-iframe scripts can synthesise MessageEvent-shaped objects or bounce events off the iframe itself via window.postMessage(self,...), both of which would slip past the type check. Today only SET_MODE is processed and the worst case is a no-op mode flip, but the structural fix protects every future control type added to the switch. - overlay.ts: reject onParentMessage events whose ev.source !== window.parent - overlay.test.ts: harness captures the registered message + click listeners and asserts a forged-source SET_MODE leaves currentMode unchanged (click still passes through), while the same envelope from window.parent flips into comment mode (click is intercepted)
Codex flagged the two SET_MODE postMessage sites in PreviewPane for catching and ignoring errors, leaving mode-sync failures invisible (violates the no-silent-fallback rule). Extract a shared helper that forwards the failure reason through the existing pushIframeError sink so the CanvasErrorBar surfaces it.
…mode active state
bb442ec to
1cbacf4
Compare
|
Addressed Codex minor: replaced |
There was a problem hiding this comment.
Findings
- No high-confidence issues found on added/modified lines in the latest diff.
Summary
- Review mode: follow-up after new commits
- No new actionable issues identified in this revision.
- and : Not found in repo/docs.
- Residual risk: no integration test in this PR that validates end-to-end mode toggle + iframe click pass-through behavior in the renderer.
Testing
- Not run (automation)
open-codesign Bot
Summary
Fixes the always-on iframe click listener that violated Claude Design's mode-based interaction. Previously every click on a preview element popped the inline comment composer (and
preventDefaultkilled any real link/button inside the design). Now the iframe is click-pass-through by default and only intercepts when the user enters Comment mode from the preview toolbar.Behaviour
interactionMode('default' | 'comment') in the renderer store; defaults to'default'.MessageSquareComment button. Clicking toggles the mode andpostMessages{__codesign:true, type:'SET_MODE', mode}into the iframe.currentMode, gatesmouseover/mouseout/clickon it, and clears any outline when leaving comment mode. Listener is registered in the same idempotent reattach loop as the existing handlers.InlineCommentComposerand the comment hint badge only render in comment mode.interactionModealong with the rest of the workspace state.Test plan
pnpm typecheckpnpm test(added 3 store unit tests for default state, set, and selection cleanup on exit)pnpm lintCompatibility / upgradeability / no bloat / elegance
SET_MODEpayload tagged with__codesigndiscriminator, easy to extend with future modes.