registry  /  @oxgeneral/orch  /  1.0.27

@oxgeneral/orch@1.0.27

AI agent runtime — orchestrate Claude, Cursor, Codex & OpenCode as one team. Multi-agent task automation with state machine, auto-retry, inter-agent messaging, goals and teams. Zero-config CLI + programmatic API.

AI Security Review

scanned 59m ago · by lpm-firewall-ai

LPM blocks this version under the AI-agent control-surface policy. The package performs an npm postinstall mutation of a foreign AI-agent control surface by copying its bundled Claude Code skill into the user's home directory. It also patches installed Ink dependency files under node_modules.

Static reason
High-risk behavior combination matched malicious policy.
Trigger
npm install of @oxgeneral/orch@1.0.27
Impact
Registers package-supplied /orch instructions in Claude Code outside the package namespace at install time, giving the package an agent control foothold without explicit user invocation.
Mechanism
unconsented lifecycle write to Claude Code skill directory
Policy narrative
On install, npm runs scripts/postinstall.cjs. The script reads skills/orch/SKILL.md from the package, creates ~/.claude/skills/orch, and writes SKILL.md there, registering a Claude Code skill from a lifecycle hook rather than an explicit user command. The same hook also rewrites Ink build files under node_modules.
Rationale
Static source inspection confirms lifecycle-triggered writes into ~/.claude/skills, a foreign/broad AI-agent control surface covered by the block policy. The absence of network exfiltration does not remove the unconsented install-time agent control mutation.
Evidence
package.jsonscripts/postinstall.cjsskills/orch/SKILL.md~/.claude/skills/orch/SKILL.mdnode_modules/ink/build/wrap-text.jsnode_modules/ink/build/measure-text.jsnode_modules/ink/build/output.js

Decision evidence

public snapshot
AI called this Malicious at 97.0% confidence as Dangerous Capability with low false-positive risk.
Evidence for policy block
  • package.json runs postinstall: node scripts/postinstall.cjs || true
  • scripts/postinstall.cjs writes package skill to ~/.claude/skills/orch/SKILL.md during npm install
  • scripts/postinstall.cjs mutates dependency files under node_modules/ink/build at install time
  • skills/orch/SKILL.md is packaged agent-facing instruction content for Claude Code
Evidence against
  • No network calls or endpoint use in scripts/postinstall.cjs
  • Postinstall catches errors and only shows banner in interactive stderr
  • Main package purpose is AI-agent orchestration with Claude/Codex/Cursor/OpenCode bins
  • No credential harvesting or exfiltration found in inspected install script
Behavioral surface
Source
ChildProcessCryptoDynamicRequireEnvironmentVarsFilesystemShell
Supply chain
HighEntropyStringsMinifiedUrlStrings
ManifestNo manifest risk signals triggered.
scanned 96 file(s), 644 KB of source, external domains: github.com

Source & flagged code

6 flagged · loading source
package.jsonView file
scripts.postinstall = node scripts/postinstall.cjs || true
High
Install Time Lifecycle Scripts

Package defines install-time lifecycle scripts.

package.jsonView on unpkg
scripts.postinstall = node scripts/postinstall.cjs || true
Medium
Ambiguous Install Lifecycle Script

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

package.jsonView on unpkg
dist/chunk-6DWHQPTE.jsView file
9} L10: require(kind) { L11: const adapter = this.adapters.get(kind);
Medium
Dynamic Require

Package source references dynamic require/import behavior.

dist/chunk-6DWHQPTE.jsView on unpkg · L9
scripts/postinstall.cjsView file
1Install-time AI-agent control hijack evidence: L7: L8: const { readFileSync, writeFileSync, existsSync, mkdirSync } = require('node:fs'); L9: const { join } = require('node:path'); ... L22: s = s.replace('cache[cacheKey] = wrappedText;', `cache[cacheKey] = wrappedText;\n _lruKeys.push(cacheKey);\n if (_lruKeys.length > _MAX) { delete cache[_lruKeys.shift()]; }`)... L23: writeFileSync(wrapPath, s); L24: } ... L32: s = s.replace('cache.set(text, dimensions);', `cache.set(text, dimensions);\n if (cache.size > _MAX_MT) { const first = cache.keys().next().value; cache.delete(first); }`); L33: writeFileSync(measurePath, s); L34: } ... L46: s = s.replace('this.blockWidths.set(text, cached);', `this.blockWidths.set(text, cached);${lru('blockWidths')}`); L47: writeFileSync(outputPath, s); L48: } Payload evidence from skills/orch/SKILL.md: L1: --- L2: name: orch
Critical
Ai Agent Control Hijack

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

scripts/postinstall.cjsView on unpkg · L1
13Manifest entrypoint (scripts.postinstall) carries capability families absent from dist/build output: environment+network L13: try { L14: const inkBuild = join(__dirname, '..', 'node_modules', 'ink', 'build'); L15: const MAX = 2000; ... L69: // Skip banner in CI or non-interactive environments L70: if (process.env.CI || !process.stderr.isTTY) process.exit(0); L71: ... L76: L77: process.stderr.write(` L78: ${green('✓')} ${bold('orchestry')} installed ... L82: ${sk[redacted] ? ` ${dim('or use')} ${bold('/orch')} ${dim('in Claude Code')}\n` : ''} L83: ${dim('⭐ Like it? Star us on GitHub: https://github.com/oxgeneral/ORCH')} L84:
High
Entrypoint Build Divergence

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

scripts/postinstall.cjsView on unpkg · L13
scripts/release.shView file
path = scripts/release.sh kind = build_helper sizeBytes = 929 magicHex = [redacted]
Medium
Ships Build Helper

Package ships non-JavaScript build or shell helper files.

scripts/release.shView on unpkg

Findings

1 Critical2 High5 Medium5 Low
CriticalAi Agent Control Hijackscripts/postinstall.cjs
HighInstall Time Lifecycle Scriptspackage.json
HighEntrypoint Build Divergencescripts/postinstall.cjs
MediumAmbiguous Install Lifecycle Scriptpackage.json
MediumDynamic Requiredist/chunk-6DWHQPTE.js
MediumEnvironment Vars
MediumShips Build Helperscripts/release.sh
MediumStructural Risk Force Deep Review
LowNon Install Lifecycle Scripts
LowScripts Present
LowFilesystem
LowHigh Entropy Strings
LowUrl Strings