Jul 14, 2026·5 min read·27 visits
Unauthenticated remote code execution occurs when TidGi Desktop automatically registers and runs malicious startup modules found in imported TiddlyWiki repositories.
A critical remote code execution vulnerability exists in TidGi Desktop up to version 0.13.0. The flaw allows an attacker to execute arbitrary code with Node.js privileges when a user imports or clones a malicious TiddlyWiki repository. This occurs due to the automatic execution of 'startup' modules defined in user-imported tiddler files.
TidGi Desktop is a desktop-based manager for TiddlyWiki workspaces, providing users with Git integration and synchronization features. When running local or cloned wikis, the application spins up a Node.js-based wiki worker process to compile and serve the workspace.
The attack surface of this application expands significantly when it imports third-party wikis. A severe vulnerability exists within the workspace initialization phase. This flaw permits arbitrary code execution if an attacker convinces a user to import or clone a maliciously crafted TiddlyWiki repository.
The bug class is categorized as Improper Control of Generation of Code ('Code Injection'), tracking under CWE-94. Because the wiki worker executes with full Node.js privileges, arbitrary code executed within this context compromises the underlying host operating system.
The root cause lies in TiddlyWiki's core initialization design and TidGi Desktop's lack of sandboxing during the workspace boot sequence. When the application loads a wiki, it performs automatic discovery of tiddler files from the local directory structure. This process is handled recursively, reading and registering files ending in the .tid extension.
During the boot phase, the system iterates over all registered tiddlers. If a loaded tiddler contains the metadata field module-type set to a valid system category such as startup, the loader treats the file as an executable plugin module. This metadata tag instructs TiddlyWiki's engine to register the file content as executable JavaScript.
Finally, during the execution phase, the bootstrapper collects all modules categorized under the startup type. It calls their exported startup functions sequentially. There are no isolation barriers or validation checks to ensure that these modules originate from a trusted vendor space or signed package, resulting in immediate execution of user-supplied code.
In TidGi Desktop's wiki worker initialization pipeline, specifically within src/services/wiki/wikiWorker/loadWikiTiddlersWithSubWikis.ts, the application reads the filesystem contents and registers tiddlers directly into the workspace memory without validating the attributes of the loaded objects:
const tiddlerFiles = wikiInstance.loadTiddlersFromPath(subWikiTiddlersPath);
for (const tiddlerFile of tiddlerFiles) {
// Unconditionally add tiddlers to the active wiki instance
wikiInstance.wiki.addTiddlers(tiddlerFile.tiddlers);
}Once added, the TiddlyWiki core bootloader (node_modules/tiddlywiki/boot/boot.js) parses these tiddlers inside defineTiddlerModules. It converts tiddlers with module-type fields into executable modules:
$tw.Wiki.prototype.defineTiddlerModules = function() {
this.each(function(tiddler, title) {
if (tiddler.hasField("module-type") && (!tiddler.hasField("draft.of"))) {
switch (tiddler.fields.type) {
case "application/javascript":
$tw.modules.define(
tiddler.fields.title,
tiddler.fields["module-type"],
tiddler.fields.text
);
break;
}
}
});
};Because the system is running in a Node.js backend context rather than a browser sandbox, the subsequent execution of $tw.boot.remainingStartupModules invokes the custom startup hook. The worker thread directly runs the arbitrary payload under the permissions of the parent desktop application process.
To execute the attack, an adversary constructs a malicious TiddlyWiki repository. This repository contains a customized tiddler file located under the tiddlers/ directory structure, for example, tiddlers/payload.tid. The attacker structures the file with specific metadata tags to register it as a startup module.
title: $:/plugins/poc/startup.js
type: application/javascript
module-type: startup
exports.startup = function() {
require('child_process').execSync('touch /tmp/TidGi-RCE-PoC.txt');
};Once the victim clones this repository via the TidGi interface or loads the folder locally, the workspace boot sequence is triggered automatically. The loader detects the metadata, registers the module, and invokes the exported startup method. This spawns the operating system command specified in the execSync payload.
No authorization is needed, as the exploit leverages the standard repository import workflow. The only prerequisite is user interaction to import or clone the malicious repository folder into TidGi Desktop.
The security impact of this vulnerability is critical, reflected by its CVSS base score of 9.6. By gaining arbitrary code execution within the wiki worker, an attacker effectively gains full control over the user's host environment under the privilege level of the running application.
An attacker can read, modify, or delete sensitive local files, access environmental credentials, or extract SSH keys and system configuration files. Since the worker process has unrestricted outbound network connectivity, extracted secrets can be exfiltrated easily over standard protocols.
Furthermore, the execution capability allows the attacker to establish persistent access. By executing system commands, the payload can install permanent backdoors, modify startup configurations, or register persistent execution tasks on the victim's operating system.
Currently, there is no official patched release for TidGi Desktop to resolve this flaw. Users should refrain from importing or cloning untrusted TiddlyWiki repositories. For developers or maintainers of downstream forks, implementing defense-in-depth mitigations is highly advised.
One approach is restricting the allowed values of module-type on user-imported tiddlers. System-level modules like startup should only be loaded from internal or signed plugin spaces. Below is an example of checking and rejecting unsafe modules during definition:
const ALLOWED_USER_MODULE_TYPES = ['widget', 'macro', 'filter', 'parser'];
if (!ALLOWED_USER_MODULE_TYPES.includes(tiddler.fields['module-type'])) {
return;
}Additionally, evaluating imported javascript modules in a sandboxed context (such as the vm module in Node.js) rather than the main thread will limit access to dangerous native modules like child_process and fs.
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:H| Product | Affected Versions | Fixed Version |
|---|---|---|
TidGi Desktop Lin Onetwo | <= 0.13.0 | null |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-94 |
| Attack Vector | Network (AV:N) |
| CVSS Score | 9.6 |
| Exploit Status | PoC |
| KEV Status | Not Listed |
| Impact | Remote Code Execution (RCE) |
A path traversal vulnerability (CWE-22) in Contao CMS allows unauthenticated remote attackers to bypass directory boundary restrictions in ImagesController and access files within the project directory.
Contao Open Source CMS versions 4.0.0 through 5.3.49 and 5.4.0-RC1 through 5.7.11 contain a Cross-Site Request Forgery (CSRF) vulnerability in backend parameter handling. The `RequestTokenListener` component validates anti-CSRF tokens solely for HTTP POST requests, while GET-based declarative guards run only when an `act` parameter is present in the query string. Consequently, custom backend actions dispatched via alternative parameters such as `key=` can execute without CSRF token verification when triggered by an authenticated user.
Contao CMS versions 4.1.0 through 5.3.49 and 5.4.0-RC1 through 5.7.11 fail to validate form submission tokens and enforce rate limiting when processing activation email resend requests via HTTP POST, enabling resource exhaustion and account state enumeration.
An information disclosure vulnerability in Contao CMS allows unauthenticated site visitors to view protected page titles, URLs, and text excerpts through search queries when protected page indexing is disabled after previously being enabled.
In Vikunja prior to version 2.6.0, relation creation via the CalDAV endpoint fails to invoke the TaskRelation.CanCreate authorization check. This missing access control allows an authenticated user to establish unauthorized relationships and perform write operations against any task, provided its unique identifier (UID) is known.
A cross-project information disclosure vulnerability in Vikunja allows authenticated users with read access to one project to view private task details from unauthorized projects via subtask expansion parameters.