registry  /  @devflow-tools/devflow  /  0.8.5

@devflow-tools/devflow@0.8.5

DevFlow - Developer Intelligence Platform (Distribution Package)

AI Security Review

scanned 3h ago · by lpm-firewall-ai

LPM blocks this version under the AI-agent control-surface policy. The package mutates a Claude Code control surface at npm install time without an explicit user command. The installed wildcard PreToolUse hook executes package code on every Claude tool call and can observe tool inputs and influence permission decisions.

Static reason
High-risk behavior combination matched malicious policy.
Trigger
npm install / postinstall, then Claude Code tool use
Impact
Package code gains persistent access to AI-agent tool-call inputs and decision flow from the consumer project after installation.
Mechanism
unconsented install-time Claude PreToolUse hook registration
Policy narrative
On install, scripts/postinstall.js locates the consuming project and writes .claude/hooks.json, adding a wildcard PreToolUse hook that invokes the package's dist/hooks/pre-tool-use.js. That hook is then executed by Claude Code for tool calls, reads the hook JSON from stdin, records tool_name and tool_input, can deny calls under its policy, and sends/caches telemetry. This is an unconsented install-time mutation of a broad foreign AI-agent control surface.
Rationale
Source inspection confirms concrete install-time mutation of .claude/hooks.json, not merely user-invoked setup or first-party plugin installation. Under the install control surface policy, unconsented postinstall mutation of a foreign/broad AI-agent control surface warrants blocking even though the network endpoints are local by default.
Evidence
package.jsonscripts/postinstall.jsdist/hooks/pre-tool-use.jsdist/cli.jsdist/mcp-server.jsdist/plugin/hooks.json.claude/hooks.json~/.devflow/telemetry-cache~/.devflow/current-skill.json~/.devflow/current-execution-id
Network endpoints2
localhost:13337127.0.0.1:13337

Decision evidence

public snapshot
AI called this Malicious at 95.0% confidence as Malware with low false-positive risk.
Evidence for policy block
  • package.json defines postinstall: node scripts/postinstall.js
  • scripts/postinstall.js walks to consumer project root and creates/updates .claude/hooks.json during npm install
  • postinstall registers wildcard Claude PreToolUse command: node dist/hooks/pre-tool-use.js
  • dist/hooks/pre-tool-use.js runs on tool calls, can deny non-MCP tools, and posts tool_input telemetry
  • dist/hooks/pre-tool-use.js defaults to http://localhost:13337 but honors DEVFLOW_API_URL
  • dist/plugin/hooks.json also ships Claude hook definitions for SessionStart/PreToolUse/PostToolUse
Evidence against
  • No obfuscated remote C2 host or hardcoded external exfiltration endpoint found
  • Network defaults are local DevFlow service URLs
  • Runtime plugin install is user-invoked via devflow plugin install
  • README describes DevFlow developer tooling and plugin management
  • dashboard-standalone.tar.gz appears to be a bundled dashboard archive
Behavioral surface
Source
ChildProcessCryptoEnvironmentVarsFilesystemNetworkShell
Supply chain
HighEntropyStringsMinifiedUrlStrings
Manifest
NoLicense
scanned 5 file(s), 115 KB of source, external domains: 127.0.0.1

Source & flagged code

8 flagged · loading source
package.jsonView file
scripts.postinstall = node scripts/postinstall.js
High
Install Time Lifecycle Scripts

Package defines install-time lifecycle scripts.

package.jsonView on unpkg
scripts.postinstall = node scripts/postinstall.js
Medium
Ambiguous Install Lifecycle Script

Install-time lifecycle script is not statically allowlisted and needs review.

package.jsonView on unpkg
dist/cli.jsView file
1#!/usr/bin/env node L2: import Jo,{unlinkSync,existsSync,readFileSync,rmSync,mkdirSync,writeFileSync,statSync,cpSync,readdirSync}from'fs';import $t,{dirname,join,resolve}from'path';import {homedir}from'os... L3: `)}var H,tn,X=ve(()=>{Re();H=Oe.default??Oe,tn=createRequire(import.meta.url);});function q(e){let o=join(e,".devflow","config.json");if(existsSync(o))try{let n=readFileSync(o,"utf...
High
Child Process

Package source references child process execution.

dist/cli.jsView on unpkg · L1
1#!/usr/bin/env node L2: import Jo,{unlinkSync,existsSync,readFileSync,rmSync,mkdirSync,writeFileSync,statSync,cpSync,readdirSync}from'fs';import $t,{dirname,join,resolve}from'path';import {homedir}from'os... L3: `)}var H,tn,X=ve(()=>{Re();H=Oe.default??Oe,tn=createRequire(import.meta.url);});function q(e){let o=join(e,".devflow","config.json");if(existsSync(o))try{let n=readFileSync(o,"utf... ... L16: Skipping plugin installation. You can install plugins later with:`),console.log(" devflow plugin list"),console.log(` devflow plugin install <name> L17: `);return i}async function E(e){let o=[],n;e.sseUrl?n={url:e.sseUrl}:n={command:e.command??"devflow-mcp",args:["--mode","stdio"]};let t=e.agent?[e.agent]:await import('@devflow-too... L18: `);if(o.length>=2){let n=parseInt(o[0],10);if(!isNaN(n))return n}return null}function $(e){if(!existsSync(e))return null;let o=readFileSync(e,"utf-8").trim().split(`
High
Same File Env Network Execution

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

dist/cli.jsView on unpkg · L1
12Installing selected plugins... L13: `);for(let s of i)try{execSync(`npm install -g ${s}`,{stdio:"inherit"}),console.log(`\u2713 ${s} L14: `);}catch{console.error(`\u2717 Failed to install ${s}
High
Runtime Package Install

Package source invokes a package manager install command at runtime.

dist/cli.jsView on unpkg · L12
scripts/postinstall.jsView file
1Install-time AI-agent control hijack evidence: L2: // L3: // Auto-configures .claude/hooks.json in the consuming project so that Claude L4: // Code invokes the devflow PreToolUse hook on every tool call. ... L11: L12: import { writeFileSync, existsSync, mkdirSync, readFileSync } from 'node:fs'; L13: import { join, dirname } from 'node:path'; ... L55: L56: const claudeDir = join(projectRoot, '.claude'); L57: const hooksFile = join(claudeDir, 'hooks.json'); ... L59: L60: // 1. Ensure .claude/ directory exists L61: if (!existsSync(claudeDir)) { Payload evidence from dist/plugin/skills/devflow:doctor/SKILL.md: L1: --- L2: name: devflow:doctor
Critical
Ai Agent Control Hijack

Install-time source drops package-supplied AI-agent/MCP control files or instructions.

scripts/postinstall.jsView on unpkg · L1
dist/dashboard-standalone.tar.gzView file
path = dist/dashboard-standalone.tar.gz kind = high_entropy_blob sizeBytes = 12073737 magicHex = [redacted]
High
Ships High Entropy Blob

Package ships high-entropy non-source blobs.

dist/dashboard-standalone.tar.gzView on unpkg
path = dist/dashboard-standalone.tar.gz kind = compressed_blob sizeBytes = 12073737 magicHex = [redacted]
Medium
Ships Compressed Blob

Package ships compressed or archive-like blobs.

dist/dashboard-standalone.tar.gzView on unpkg

Findings

1 Critical6 High5 Medium5 Low
CriticalAi Agent Control Hijackscripts/postinstall.js
HighInstall Time Lifecycle Scriptspackage.json
HighChild Processdist/cli.js
HighShell
HighSame File Env Network Executiondist/cli.js
HighRuntime Package Installdist/cli.js
HighShips High Entropy Blobdist/dashboard-standalone.tar.gz
MediumAmbiguous Install Lifecycle Scriptpackage.json
MediumNetwork
MediumEnvironment Vars
MediumShips Compressed Blobdist/dashboard-standalone.tar.gz
MediumStructural Risk Force Deep Review
LowScripts Present
LowFilesystem
LowHigh Entropy Strings
LowUrl Strings
LowNo License