Summary
Twine 2 desktop can execute attacker-controlled markup when an imported story file is opened in the editor. If a user opens a specially crafted story file, the resulting script may abuse an exposed desktop bridge to write files and execute code with the user's privileges.
Affected context
The vulnerability occurs in Twine 2 desktop releases through 2.12.0 when importStories() renders content from an imported story file in the editor window without sufficiently separating story markup from executable script context. Risk depends on a user opening an attacker-controlled story file and on the desktop application's IPC bridge being accessible to content rendered in that window.
Exploit preconditions
- Attack surface: Twine 2 desktop editor window and its story-import workflow
- Required access: Ability to deliver or persuade a user to open a crafted story file
- Trigger point: Processing imported story content through
importStories() - Why exploitation is possible: Imported markup can execute in the editor context and may reach a privileged desktop IPC bridge capable of file operations
Why this happens
The underlying bug is a failure to treat imported story content as untrusted data before rendering it in a desktop editor context. This creates a cross-site scripting condition under CWE-79, where attacker-controlled markup or script is interpreted rather than safely represented as content. The risk is amplified when the renderer has access to privileged Electron APIs without strict origin, capability, or message validation.
Potential impact
- Arbitrary script execution in the editor context may occur
- Files may be created or modified with the user's permissions
- Code may execute through an exposed desktop integration
- User data and local project content could be disclosed or altered
- Workstations or development environments could be compromised
General mitigation guidance
Mitigation generally focuses on treating imported stories as untrusted content and preventing renderer content from accessing privileged capabilities. Common defensive patterns include encoding or sanitizing imported markup, using a restrictive content security policy, and keeping executable content separate from story data. Desktop bridges should expose narrowly scoped operations through secure preload interfaces, validate every IPC message and path, and avoid direct filesystem or shell access from rendered content. User-facing workflows can also reduce trust in imported files, while the application should operate with least privilege and apply filesystem protections where practical.
How teams detect issues like this
Detection can include static analysis for unsafe HTML insertion, dynamic evaluation, permissive webview settings, and renderer access to unrestricted Electron APIs. Code review should examine import and preview paths, IPC handlers, preload exposure, origin checks, and validation of file-operation requests. Security policies can require sanitization of imported content, restrictive CSP settings, and explicit allowlists for renderer-to-main process communication. Automated application-security review tools may help identify these patterns during development.

