registry  /  mixdog  /  0.9.21

mixdog@0.9.21

Standalone mixdog coding-agent CLI/TUI workspace.

AI Security Review

scanned 2d ago · by lpm-firewall-ai

No confirmed malicious install-time or import-time attack surface was found. Risky primitives are aligned with a coding-agent CLI: provider networking, explicit shell/tool execution, plugin hooks, and managed voice-runtime downloads.

Static reason
High-risk behavior combination matched malicious policy.; previous stored version diff introduced dangerous source
Trigger
User runs the mixdog CLI or explicitly enables runtime features such as providers, plugins, hooks, channels, or voice transcription.
Impact
No concrete unauthorized credential theft, persistence, destructive action, or AI-agent control hijack identified.
Mechanism
User-invoked agent CLI capabilities with pinned runtime downloads and configured provider API calls.
Rationale
Static inspection shows a feature-rich coding-agent CLI with expected networking, process spawning, plugins, hooks, and voice-runtime downloads, but no lifecycle hook, stealth execution, credential harvesting, or unconsented mutation of a foreign AI-agent control surface. Scanner findings are explained by package-aligned runtime features and tests rather than a concrete malicious chain.
Evidence
package.jsonsrc/cli.mjssrc/app.mjssrc/standalone/channel-worker.mjssrc/runtime/channels/lib/whisper-server.mjssrc/runtime/channels/lib/voice-runtime-fetcher.mjssrc/runtime/channels/data/voice-runtime-manifest.jsonsrc/standalone/plugin-admin.mjssrc/standalone/hook-bus/handlers.mjssrc/session-runtime/provider-auth-api.mjs
Network endpoints6
raw.githubusercontent.com/tribgames/mixdog/main/src/runtime/channels/data/voice-runtime-manifest.jsonhuggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-large-v3-turbo.bingithub.com/ggml-org/whisper.cpp/releases/download/v1.8.4/whisper-bin-x64.zipgithub.com/eugeneware/ffmpeg-static/releases/download/b6.1.1/ffmpeg-linux-x64.gzapi.openai.com/v1/modelsapi.anthropic.com/v1/models

Decision evidence

public snapshot
AI called this Clean at 86.0% confidence as Benign with medium false-positive risk.
Evidence for block
  • Runtime code can spawn child processes for agent/channel workers and voice transcription.
  • Voice runtime fetcher downloads executable archives and model files on user-invoked voice setup/use.
  • Plugin/hook admin code can clone plugins and run configured hook commands when explicitly enabled.
Evidence against
  • package.json has no preinstall/install/postinstall hooks; bin only launches src/cli.mjs.
  • src/app.mjs routes to help, REPL, headless role, or TUI only after explicit CLI invocation.
  • Downloaded voice binaries are manifest-pinned with sha256 and written under mixdog data dirs.
  • src/standalone/channel-worker.mjs forks package-owned worker code with bounded tool allowlist and cleanup.
  • src/runtime/channels/lib/format.mjs contains zero-width escaping inside code-fence handling, not control-flow-hiding Trojan Source logic.
  • Provider API keys are used for configured LLM provider calls; no source path shows broad credential harvesting or exfiltration.
Behavioral surface
Source
ChildProcessCryptoDynamicRequireEnvironmentVarsEvalFilesystemNetworkShellWebSocket
Supply chain
HighEntropyStringsUrlStrings
ManifestNo manifest risk signals triggered.
scanned 707 file(s), 8.53 MB of source, external domains: 127.0.0.1, aistudio.google.com, api.anthropic.com, api.deepseek.com, api.openai.com, api.telegram.org, api.x.ai, auth.openai.com, auth.x.ai, changed.example, chatgpt.com, claude.com, cli-chat-proxy.grok.com, console.anthropic.com, console.x.ai, example.com, generativelanguage.googleapis.com, github.com, management-api.x.ai, models.dev, opencode.ai, platform.claude.com, platform.deepseek.com, platform.openai.com, raw.githubusercontent.com, registry.npmjs.org

Source & flagged code

13 flagged · loading source
scripts/compact-smoke.mjsView file
388patternName = generic_password severity = medium line = 388 matchedText = { id: 'c...} },
Medium
Secret Pattern

Package contains a possible secret pattern.

scripts/compact-smoke.mjsView on unpkg · L388
scripts/smoke-loop.mjsView file
2import { appendFileSync, mkdirSync } from 'node:fs'; L3: import { spawnSync } from 'node:child_process'; L4: import { dirname, isAbsolute, resolve } from 'node:path';
High
Child Process

Package source references child process execution.

scripts/smoke-loop.mjsView on unpkg · L2
scripts/bench-run.mjsView file
208const { raw, ok } = await new Promise((resolveRun) => { L209: const child = spawn('codex', args, { shell: true, env: { ...process.env, ...(opts.env || {}) } }); L210: let out = '';
High
Shell

Package source references shell execution.

scripts/bench-run.mjsView on unpkg · L208
scripts/ingest-pure-conversation-smoke.mjsView file
12// require it directly to mirror the pipeline without booting the MCP server. L13: const require = createRequire(import.meta.url) L14: const { cleanMemoryText } = require('../src/lib/text-utils.cjs')
Medium
Dynamic Require

Package source references dynamic require/import behavior.

scripts/ingest-pure-conversation-smoke.mjsView on unpkg · L12
src/standalone/plugin-admin.mjsView file
1import { spawnSync } from 'node:child_process'; L2: import { ... L37: function readJsonSafe(path) { L38: try { return JSON.parse(readFileSync(path, 'utf8')); } catch { return null; } L39: } ... L93: type: 'git', L94: url: `https://github.com/${source}.git`, L95: displaySource: source, ... L104: } L105: const localPath = source.replace(/^~(?=$|[\\/])/, homedir()); L106: const resolved = resolve(localPath); ... L120: if (result.status !== 0) {
Low
Weak Crypto

Package source references weak cryptographic algorithms.

src/standalone/plugin-admin.mjsView on unpkg · L1
src/runtime/agent/orchestrator/tools/shell-snapshot.mjsView file
13L14: import { spawn } from 'node:child_process'; L15: import { existsSync, mkdirSync, statSync, readFileSync, unlinkSync } from 'node:fs'; ... L86: const lower = shellPath.toLowerCase(); L87: if (lower.includes('zsh')) return join(homedir(), '.zshrc'); L88: if (lower.includes('bash')) return join(homedir(), '.bashrc'); ... L154: const script = getSnapshotScript(shellPath, snapshotPath, configFileExists); L155: let stderrBuf = ''; L156: // Mirror reference implementation (bash/ShellSnapshot.ts:458): ... L169: // even when the snapshot itself is fine). L170: // R11: scrub loader/execution vars from process.env before L171: // handing it to the snapshot shell. This site previously passed
Medium
Install Persistence

Source writes installer persistence such as shell profile or service configuration.

src/runtime/agent/orchestrator/tools/shell-snapshot.mjsView on unpkg · L13
src/runtime/channels/lib/whisper-server.mjsView file
35L36: import net from 'node:net'; L37: import path from 'node:path'; L38: import fs from 'node:fs'; L39: import { spawn, spawnSync } from 'node:child_process'; L40: import { setTimeout as delay } from 'node:timers/promises'; ... L46: const FIXED_PORT = (() => { L47: const raw = process.env.MIXDOG_WHISPER_SERVER_PORT; L48: const n = raw ? Number.parseInt(raw, 10) : NaN;
High
Same File Env Network Execution

A single source file combines environment access, network access, and code or shell execution; review context before blocking.

src/runtime/channels/lib/whisper-server.mjsView on unpkg · L35
src/runtime/memory/lib/runtime-fetcher.mjsView file
1const __mixdogMemoryStderrWrite = process.stderr.write.bind(process.stderr); L2: function __mixdogMemoryLog(...args) { L3: if (process.env.MIXDOG_QUIET_MEMORY_LOG) return true; L4: return __mixdogMemoryStderrWrite(...args); ... L30: import { pipeline } from 'stream/promises' L31: import { spawnSync } from 'child_process' L32: import { renameWithRetrySync, writeFileAtomicSync, writeJsonAtomicSync } from '../../shared/atomic-file.mjs' ... L38: // GitHub raw URL fallback — used only when no cached or bundled manifest exists. L39: const MANIFEST_URL = 'https://raw.githubusercontent.[redacted]-manifest.json' L40: const LEGACY_RUNTIME_RELEASE_REPOSITORY = 'trib-plugin/mixdog' ... L46: function platformKey() { L47: const os = process.platform === 'win32' ? 'win32' : process.platform
High
Sandbox Evasion Gated Capability

Source gates dangerous network, credential, or execution behavior behind CI, host, platform, time, or geo fingerprint checks.

src/runtime/memory/lib/runtime-fetcher.mjsView on unpkg · L1
src/runtime/channels/lib/format.mjsView file
129contains invisible/control Unicode U+200B (zero width space) return line.replace(/```/g, "`<U+200B>``");
Critical
Trojan Source Unicode

Source contains bidi control or invisible Unicode characters associated with Trojan Source attacks.

src/runtime/channels/lib/format.mjsView on unpkg · L129
scripts/boot-smoke.mjsView file
1Cross-file remote execution chain: scripts/boot-smoke.mjs spawns src/tui/dist/index.mjs; helper contains network access plus dynamic code execution. L1: #!/usr/bin/env node L2: import { spawnSync } from 'node:child_process'; L3: import { dirname, resolve } from 'node:path'; ... L6: const root = resolve(dirname(fileURLToPath(import.meta.url)), '..'); L7: const THRESHOLD_MS = Number(process.env.MIXDOG_BOOT_SMOKE_LIMIT_MS || 5_000); L8: const FAST_BACKGROUND_ENV = { ... L23: L24: function runCase(name, args, { env = {}, input = null, expectStdout = null, expectStderr = null, maxMs = THRESHOLD_MS } = {}) { L25: const startedAt = performance.now(); ... L134: for (const row of rows) { L135: process.stdout.write(`${row.name}: ${row.ms}ms\n`); L136: }
High
Cross File Remote Execution Context

Source spawns a local helper that also contains network and dynamic execution context; review data flow before blocking.

scripts/boot-smoke.mjsView on unpkg · L1
scripts/build-runtime-linux.shView file
path = scripts/build-runtime-linux.sh kind = build_helper sizeBytes = 14047 magicHex = [redacted]
Medium
Ships Build Helper

Package ships non-JavaScript build or shell helper files.

scripts/build-runtime-linux.shView on unpkg
src/standalone/channel-worker.mjsView file
matchType = previous_version_dangerous_delta matchedPackage = mixdog@0.9.20 matchedIdentity = npm:bWl4ZG9n:0.9.20 similarity = 0.942 summary = stored previous version shares package body but lacks this dangerous source file
Critical
Previous Version Dangerous Delta

This package version adds a dangerous source file absent from the previous stored version; route for source-aware review.

src/standalone/channel-worker.mjsView on unpkg
scripts/session-ingest-smoke.mjsView file
59patternName = generic_password severity = medium line = 59 matchedText = const js... });
Medium
Secret Pattern

Hardcoded password in scripts/session-ingest-smoke.mjs

scripts/session-ingest-smoke.mjsView on unpkg · L59

Findings

2 Critical5 High8 Medium6 Low
CriticalTrojan Source Unicodesrc/runtime/channels/lib/format.mjs
CriticalPrevious Version Dangerous Deltasrc/standalone/channel-worker.mjs
HighChild Processscripts/smoke-loop.mjs
HighShellscripts/bench-run.mjs
HighSame File Env Network Executionsrc/runtime/channels/lib/whisper-server.mjs
HighSandbox Evasion Gated Capabilitysrc/runtime/memory/lib/runtime-fetcher.mjs
HighCross File Remote Execution Contextscripts/boot-smoke.mjs
MediumSecret Patternscripts/compact-smoke.mjs
MediumDynamic Requirescripts/ingest-pure-conversation-smoke.mjs
MediumNetwork
MediumEnvironment Vars
MediumInstall Persistencesrc/runtime/agent/orchestrator/tools/shell-snapshot.mjs
MediumShips Build Helperscripts/build-runtime-linux.sh
MediumStructural Risk Force Deep Review
MediumSecret Patternscripts/session-ingest-smoke.mjs
LowScripts Present
LowEval
LowWeak Cryptosrc/standalone/plugin-admin.mjs
LowFilesystem
LowHigh Entropy Strings
LowUrl Strings