Summary
A static review of version 1.0.8 found two security issues. No network exfiltration, hidden downloads, shell/file-system access, credential handling, or deliberate obfuscation was found in the reviewed archive.
1. Unvalidated persisted color values can reach HTML sinks
Task-note data following the __task_colors__= marker is parsed as JSON and returned without type or color-format validation. Values from synced settings are also inserted into HTML strings. Those values subsequently reach concatenated htmlContent / innerHTML attributes and styles.
Affected examples:
plugin.js: getCurrentColor() around lines 23–35; task picker rendering around lines 571–577
index.html: side-panel rendering around lines 385–394
A malicious or corrupted synced/imported task note could supply a value that escapes a quoted attribute when the generated HTML is parsed. This may allow DOM XSS in the plugin context, including access to the plugin's task/tag APIs.
Recommended fix
- Validate every loaded color using a strict allowlist such as
/^#[0-9a-f]{6}$/i.
- Reject invalid records in task notes and synced data.
- Prefer DOM APIs (
.value, .dataset, style properties) over concatenated HTML; escape any remaining dynamic attributes.
2. postMessage handlers do not validate sender
The iframe sends open-tag-colors with targetOrigin = '*' and accepts tag-colors-result without checking event.origin or event.source. The host listener also accepts open-tag-colors from any sender and replies using the sender-controlled event.origin.
Affected examples:
index.html: around lines 498–509
plugin.js: around lines 737–750
An untrusted window that obtains a reference to the plugin frame could trigger privileged UI/data flow or spoof a result message. Updates still require the user to save the dialog, which limits automatic modification.
Recommended fix
- Use the known fixed origin instead of
*.
- Verify both
event.origin and event.source against the expected iframe/parent window.
- Apply a narrow message schema and bind request/response pairs with a per-frame nonce.
Scope
This was a static review only; the Super Productivity runtime's CSP and plugin isolation were not dynamically verified.
Summary
A static review of version
1.0.8found two security issues. No network exfiltration, hidden downloads, shell/file-system access, credential handling, or deliberate obfuscation was found in the reviewed archive.1. Unvalidated persisted color values can reach HTML sinks
Task-note data following the
__task_colors__=marker is parsed as JSON and returned without type or color-format validation. Values from synced settings are also inserted into HTML strings. Those values subsequently reach concatenatedhtmlContent/innerHTMLattributes and styles.Affected examples:
plugin.js:getCurrentColor()around lines 23–35; task picker rendering around lines 571–577index.html: side-panel rendering around lines 385–394A malicious or corrupted synced/imported task note could supply a value that escapes a quoted attribute when the generated HTML is parsed. This may allow DOM XSS in the plugin context, including access to the plugin's task/tag APIs.
Recommended fix
/^#[0-9a-f]{6}$/i..value,.dataset, style properties) over concatenated HTML; escape any remaining dynamic attributes.2.
postMessagehandlers do not validate senderThe iframe sends
open-tag-colorswithtargetOrigin = '*'and acceptstag-colors-resultwithout checkingevent.originorevent.source. The host listener also acceptsopen-tag-colorsfrom any sender and replies using the sender-controlledevent.origin.Affected examples:
index.html: around lines 498–509plugin.js: around lines 737–750An untrusted window that obtains a reference to the plugin frame could trigger privileged UI/data flow or spoof a result message. Updates still require the user to save the dialog, which limits automatic modification.
Recommended fix
*.event.originandevent.sourceagainst the expected iframe/parent window.Scope
This was a static review only; the Super Productivity runtime's CSP and plugin isolation were not dynamically verified.