registry  /  roadmapped  /  0.2.3

roadmapped@0.2.3

Project management as flat files in your repo — YAML tasks, a computed roadmap, driven by your AI agent through a CLI and a Claude skill. No database, no SaaS, no account.

AI Security Review

scanned 2h ago · by lpm-firewall-ai

LPM treats this as warn-only first-party agent extension lifecycle risk. Starting `roadmapped dashboard` can silently update from the package's GitHub repository. The background update invokes `roadmapped upgrade`, which modifies first-party AI-agent integration and Git hook configuration in the host repository.

Static reason
One or more suspicious static signals were detected.; previous stored version diff introduced dangerous source
Trigger
User runs `roadmapped dashboard` while the installed GitHub-sourced package is behind remote `main`.
Impact
A remote upstream change can be installed and then update host `.mcp.json`, Claude settings, skill files, `CLAUDE.md`, and a pre-commit hook without a new explicit setup command.
Mechanism
Moving-head GitHub self-update followed by agent-extension and hook setup.
Rationale
No concrete credential theft, stealth payload, or install-time foreign-agent hijack was found. The automatic moving-head update that performs agent and hook configuration warrants a warning rather than a block.
Evidence
package.jsonbin/roadmapped.mjssrc/lib/updateNotifier.tsscripts/install.mjssrc/server/api.tspackage-lock.json.mcp.json.claude/settings.json.claude/skills/roadmappedCLAUDE.md.git/hooks/pre-commit
Network endpoints1
github.com/5e1y/roadmapped.git

Decision evidence

public snapshot
AI called this Suspicious at 84.0% confidence as Dangerous Capability with low false-positive risk.
Evidence for warning
  • `bin/roadmapped.mjs` runs `autoUpdate` whenever `roadmapped dashboard` starts.
  • `src/lib/updateNotifier.ts` checks `https://github.com/5e1y/roadmapped.git` then backgrounds `npm install github:5e1y/roadmapped && npx roadmapped upgrade`.
  • `scripts/install.mjs` upgrade merges `.mcp.json`, `.claude/settings.json`, `CLAUDE.md`, a package skill, and a pre-commit hook.
  • The update source is moving GitHub `main`, not a pinned version or commit.
Evidence against
  • `package.json` has no `preinstall`, `install`, `postinstall`, or `prepare` hook.
  • Mutations originate from explicit CLI/dashboard use and target Roadmapped-owned entries.
  • No credential harvesting, data exfiltration, hidden remote payload URL, or destructive wipe was found.
Behavioral surface
Source
ChildProcessCryptoDynamicRequireEnvironmentVarsFilesystemNetworkShell
Supply chain
HighEntropyStringsMinifiedObfuscatedUrlStrings
ManifestNo manifest risk signals triggered.
scanned 83 file(s), 2.09 MB of source, external domains: base-ui.com, github.com, graphify.com, reactjs.org, www.w3.org

Source & flagged code

6 flagged · loading source
bin/roadmapped.mjsView file
20L21: const { spawnSync } = await import('node:child_process') L22: const { fileURLToPath, pathToFileURL } = await import('node:url')
High
Child Process

Package source references child process execution.

bin/roadmapped.mjsView on unpkg · L20
20Manifest entrypoint (manifest.bin) carries capability families absent from dist/build output: environment+network, execution+network L20: L21: const { spawnSync } = await import('node:child_process') L22: const { fileURLToPath, pathToFileURL } = await import('node:url') ... L78: const { findHostRoot } = await importPkg('src/lib/paths.ts') L79: const envRoot = process.env.ROADMAPPED_ROOT L80: const hostRoot = envRoot && envRoot.trim() !== '' ? resolve(envRoot) : findHostRoot() ... L101: try { L102: const res = await fetch(`http://localhost:${p}/api/tree`, { signal: AbortSignal.timeout(500) }) L103: const body = res.ok ? await res.json().catch(() => null) : null L104: return body && typeof body.ok === 'boolean' && body.hostRoot === hostRoot ? p : null
High
Entrypoint Build Divergence

Manifest entrypoint contains risky behavior absent from dist/build output.

bin/roadmapped.mjsView on unpkg · L20
20L21: const { spawnSync } = await import('node:child_process') L22: const { fileURLToPath, pathToFileURL } = await import('node:url')
Medium
Dynamic Require

Package source references dynamic require/import behavior.

bin/roadmapped.mjsView on unpkg · L20
src/lib/updateNotifier.tsView file
matchType = previous_version_dangerous_delta matchedPackage = roadmapped@0.2.2 matchedIdentity = npm:cm9hZG1hcHBlZA:0.2.2 similarity = 0.939 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/lib/updateNotifier.tsView on unpkg
125const child = spawn(`npm install github:${REPO} && npx roadmapped upgrade`, { L126: cwd: hostRoot, detached: true, stdio: 'ignore', shell: true, L127: })
High
Shell

Package source references shell execution.

src/lib/updateNotifier.tsView on unpkg · L125
124function runUpdate(hostRoot: string): void { L125: const child = spawn(`npm install github:${REPO} && npx roadmapped upgrade`, { L126: cwd: hostRoot, detached: true, stdio: 'ignore', shell: true,
High
Runtime Package Install

Package source invokes a package manager install command at runtime.

src/lib/updateNotifier.tsView on unpkg · L124

Findings

1 Critical4 High4 Medium5 Low
CriticalPrevious Version Dangerous Deltasrc/lib/updateNotifier.ts
HighChild Processbin/roadmapped.mjs
HighShellsrc/lib/updateNotifier.ts
HighEntrypoint Build Divergencebin/roadmapped.mjs
HighRuntime Package Installsrc/lib/updateNotifier.ts
MediumDynamic Requirebin/roadmapped.mjs
MediumNetwork
MediumEnvironment Vars
MediumStructural Risk Force Deep Review
LowScripts Present
LowFilesystem
LowObfuscated
LowHigh Entropy Strings
LowUrl Strings