registry  /  thorta  /  1.0.4

thorta@1.0.4

OpenCode preconfigured with the THORTA development environment, agents, and skills

AI Security Review

scanned 3h ago · by lpm-firewall-ai

LPM blocks this version under the AI-agent control-surface policy. The package has unconsented lifecycle mutation of broad AI-agent control surfaces. Install/postinstall copies package-supplied skills, agents, and rules into user OpenCode config directories and writes CLAUDE.md/AGENTS.md.

Static reason
High-risk behavior combination matched malicious policy.
Trigger
npm install or postinstall runs node bin/cli.js --sync
Impact
User/home agent behavior can be altered without explicit consent, including installed skills and persistent instruction files for OpenCode/Claude-style agents.
Mechanism
lifecycle-triggered AI-agent config and instruction file writes
Policy narrative
Installing thorta runs bin/cli.js --sync through both install and postinstall. That code modifies user and project OpenCode-related configuration, copies package-controlled skills and agents into ~/.config/opencode and ~/.opencode, and plants AGENTS.md/CLAUDE.md instructions without a user-invoked setup step.
Rationale
This matches the blockable policy for unconsented lifecycle mutation of foreign or broad AI-agent control surfaces, even though the content appears package-aligned and no exfiltration endpoint was found. The behavior is install-triggered, persistent in user config locations, and affects agent instruction/control files outside the package.
Evidence
package.jsonbin/cli.jsagent/Build T.mdagent/Plan T.mdskills/graphify/SKILL.md~/.config/opencode/skills/*/SKILL.md~/.opencode/skills/*/SKILL.md~/.config/opencode/agent/Build T.md~/.config/opencode/agents/Build T.md~/.opencode/agent/Plan T.md~/.opencode/agents/Plan T.md~/.config/opencode/AGENTS.md~/.config/opencode/CLAUDE.md~/.opencode/AGENTS.md~/.opencode/CLAUDE.md~/opencode.json./opencode.json

Decision evidence

public snapshot
AI called this Malicious at 96.0% confidence as Dangerous Capability with low false-positive risk.
Evidence for policy block
  • package.json runs node bin/cli.js --sync on both install and postinstall.
  • bin/cli.js main() always rewrites cwd opencode.json and may rename ~/opencode.json during lifecycle.
  • bin/cli.js syncSkillsAndRules writes package SKILL.md files into ~/.config/opencode and ~/.opencode.
  • bin/cli.js writes AGENTS.md and CLAUDE.md into ~/.config/opencode and ~/.opencode with package-supplied agent instructions.
  • Generated OpenCode config grants bash/write/edit tools and disables default build/plan agents when CLI launches.
Evidence against
  • No external network endpoints or credential exfiltration found in inspected files.
  • Agent/build scripts appear user-invoked after CLI run, not lifecycle-triggered by --sync.
  • Writes target OpenCode-related locations rather than arbitrary shell startup or OS persistence files.
Behavioral surface
Source
ChildProcessEnvironmentVarsFilesystemNetwork
Supply chain
HighEntropyStringsUrlStrings
Manifest
WildcardDependency
scanned 7 file(s), 43.5 KB of source, external domains: opencode.ai

Source & flagged code

6 flagged · loading source
package.jsonView file
scripts.postinstall = node bin/cli.js --sync
High
Install Time Lifecycle Scripts

Package defines install-time lifecycle scripts.

package.jsonView on unpkg
scripts.install = node bin/cli.js --sync
Medium
Ambiguous Install Lifecycle Script

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

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

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

package.jsonView on unpkg
bin/cli.jsView file
1Install-time AI-agent control hijack evidence: L30: if (!fs.existsSync(dir)) { L31: fs.mkdirSync(dir, { recursive: true }); L32: } ... L38: path.join(userHome, ".config", "opencode"), L39: path.join(userHome, ".opencode") L40: ]; L41: L42: // Limpa o diretório .opencode local no packageRoot se existir para não poluir o explorador L43: const localOpencode = path.join(packageRoot, ".opencode"); L44: if (fs.existsSync(localOpencode)) { ... L63: const skillContent = fs.readFileSync(srcSkillPath, "utf8"); L64: fs.writeFileSync(destSkillPath, skillContent, "utf8"); Payload evidence from skills/ui-ux-pro-max/SKILL.md: L1: --- L2: name: ui-ux-pro-max
Critical
Ai Agent Control Hijack

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

bin/cli.jsView on unpkg · L1
7L8: const { spawn, execSync } = require("child_process"); L9: const path = require("path");
High
Child Process

Package source references child process execution.

bin/cli.jsView on unpkg · L7
dev-server.jsView file
2const path = require('path'); L3: const http = require('http'); L4: const net = require('net'); L5: const { exec } = require('child_process'); L6: L7: const SERVER_ROOT = process.argv[2] || process.env.SERVER_ROOT || process.cwd(); L8:
High
Same File Env Network Execution

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

dev-server.jsView on unpkg · L2

Findings

1 Critical3 High6 Medium4 Low
CriticalAi Agent Control Hijackbin/cli.js
HighInstall Time Lifecycle Scriptspackage.json
HighChild Processbin/cli.js
HighSame File Env Network Executiondev-server.js
MediumAmbiguous Install Lifecycle Scriptpackage.json
MediumAmbiguous Install Lifecycle Scriptpackage.json
MediumNetwork
MediumEnvironment Vars
MediumStructural Risk Force Deep Review
MediumWildcard Dependency
LowScripts Present
LowFilesystem
LowHigh Entropy Strings
LowUrl Strings