critical · 9.6Jul 14, 2026

TidGi Desktop Remote Code Execution via Malicious TiddlyWiki Repository Import

Shubham Kandhare
Security Engagement Manager, SecureLayer7

Importing a crafted TiddlyWiki Git repository into TidGi Desktop automatically executes attacker-supplied JavaScript with full Node.js access, giving an attacker complete control over the victim's mac

Packagetidgi
Ecosystemnpm
Affected<= 0.13.0

The problem

TidGi Desktop through 0.13.0 boots every imported wiki by calling `$tw.boot.startup()`, which loads all `.tid` files from the wiki's `tiddlers/` directory into the wiki store unconditionally.

Any tiddler carrying `type: application/javascript` and `module-type: startup` is then registered as an executable module via `defineTiddlerModules()` and its `exports.startup()` function is called automatically during the boot sequence. The Wiki Worker process runs full Node.js, so the attacker's code has access to `require('child_process')`, `require('fs')`, and everything else.

No authentication, no prompt, and no sandbox stand between the import action and code execution.

Proof of concept

A working proof-of-concept for this issue in tidgi, with the exact payload below.

text
title: $:/plugins/poc/startup.js
type: application/javascript
module-type: startup

exports.startup = function() {
  require('child_process').execSync('touch /tmp/TidGi-RCE-PoC.txt');
  console.log('STARTUP_EXECUTED');
};

The root cause is the absence of any trust boundary between user-supplied tiddler files and TiddlyWiki's module system. `loadWikiTiddlers` reads every `.tid` file from disk and passes it straight to `wiki.addTiddlers()`. Immediately after, `defineTiddlerModules()` iterates the full wiki store: any tiddler with `module-type: startup` and `type: application/javascript` is handed to `$tw.modules.define()` and scheduled for execution.

The platform guard in `doesTaskMatchPlatform()` returns `true` by default when no `platforms` field is set, so the startup function runs unconditionally.

The advisory recommends stripping `module-type` from non-system tiddlers (titles not starting with `$:/`), sandboxing user module execution with `vm.runInNewContext`, or allowlisting safe module types such as `widget`, `macro`, `filter`, and `parser`. Any of these mitigations breaks the exploit chain.

CWE-94 (Improper Control of Code Generation) applies directly: attacker-controlled text is promoted to executable code with no sanitization or isolation step.

The fix

No patched release was publicly available at the time of writing. The advisory recommends: (1) filtering out `module-type` fields on tiddlers whose titles do not start with `$:/`, so user-repository tiddlers can never register executable modules; (2) running user modules inside `vm.runInNewContext` with a restricted sandbox; or (3) allowlisting safe `module-type` values (`widget`, `macro`, `filter`, `parser`) and rejecting `startup`, `library`, `saver`, etc. for user tiddlers.

Monitor the TidGi-Desktop releases page at https://github.com/tiddly-gittly/TidGi-Desktop/releases for a patched build. Until a fix ships, do not import wiki repositories from untrusted sources.

Reported by nuii.

References: [1][2]

Related research