ProtonMail / ProtonMail/WebClients
[Security] Lumo HtmlPreviewPanel message listener missing origin/source check - UI spoofing
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 5.6k
- Forks
- 715
- PR merge metrics
- No merged PRs in 30d
Description
Summary
The message listener in Lumo's HtmlPreviewPanel does not validate event.source or event.origin before displaying attacker-controlled content as a "render error".
Vulnerable code
applications/lumo/src/app/components/HtmlPreview/HtmlPreviewPanel.tsx:69-74 (current master):
const handleMessage = (e: MessageEvent) => {
if (e.data?.type === 'lumo-error' && typeof e.data.message === 'string') {
// e.source / e.origin not checked
setRenderError(e.data.message);
}
};
window.addEventListener('message', handleMessage);
The injected iframe script (INJECTED_SCRIPT, lines 26-38) posts { type: 'lumo-error', message } to window.parent — any window that holds a reference to the Lumo page (e.g., a popup opened via window.open) can send the same-shaped message from any origin.
Impact
UI spoofing / phishing: attacker can display arbitrary error text in the Lumo panel (e.g., "Session expired — sign in at https://evil.example") to trick the user. No data exfiltration, no code execution. Severity: Low.
Suggested fix
Verify the sender:
if (e.source === iframeRef.current?.contentWindow && e.data?.type === 'lumo-error' && ...) {
setRenderError(e.data.message);
}
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in applications/lumo/src/app/components/HtmlPreview/HtmlPreviewPanel.tsx at the message listener around lines 69-74, then inspect INJECTED_SCRIPT around lines 26-38 and the iframeRef. Ensure only messages from the preview iframe can set the render error, while its posted errors still display; messages from other windows or origins should be ignored.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- react, typescript
- Domain
- frontend, security
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 82/100