registry  /  artor-cli  /  0.12.1

artor-cli@0.12.1

Artor CLI — version, publish, and preview your web prototypes.

AI Security Review

scanned 8d ago · by lpm-firewall-ai

No confirmed malicious attack surface was found. The package is a feature-rich Artor CLI with network, file-write, and child_process capabilities gated behind user-invoked commands.

Static reason
High-risk behavior combination matched malicious policy.
Trigger
Explicit runtime use of artor subcommands such as login, publish, skill sync, registry login, update, or install.
Impact
Can publish project artifacts or modify local config when the user requests those CLI operations; no evidence of covert credential harvesting or install-time execution.
Mechanism
Package-aligned CLI API calls and local project configuration writes.
Rationale
Scanner findings are explained by an authenticated publishing/admin CLI: credentials are read only for explicit commands and sent to Artor API endpoints, while local file and process operations implement documented build, publish, registry, and skill workflows. I found no lifecycle hook, hidden exfiltration endpoint, persistence, destructive install-time behavior, or unconsented AI-agent control-surface mutation.
Evidence
package.jsondist/index.js~/.artor/config.json.artor/skills.lock.json.claude/skills/org/*AGENTS.md.npmrc.env.local
Network endpoints4
dash.artor.appregistry.npmjs.org/github.com/artorapp/skill/tree/main/artorlocalhost:3000

Decision evidence

public snapshot
AI called this Clean at 89.0% confidence as Benign with medium false-positive risk.
Evidence for block
  • dist/index.js has user-invoked child_process use for project build/install, global update/install, and Artor skill/plugin install commands.
  • dist/index.js can write project files such as .npmrc, .env.local, .claude/skills/org/*, AGENTS.md, and ~/.artor/config.json when matching CLI commands run.
  • dist/index.js sends ARTOR_GITHUB_TOKEN or ARTOR_REGISTRY_TOKEN only in explicit skill add/registry add request bodies.
Evidence against
  • package.json has no install/postinstall lifecycle hooks; bin only maps artor to ./dist/index.js.
  • Network traffic is CLI-aligned to configured Artor API default https://dash.artor.app, plus public npm/GitHub skill installer URLs for explicit update/install paths.
  • API verbose logging redacts authorization/cookie/token/password/secret fields and token-like values.
  • No import-time execution beyond dispatching the invoked CLI command; dangerous actions are behind explicit subcommands/prompts.
  • Publish uploads current project artifact/source to /api/cli/publish, which matches the package purpose of publishing prototypes.
Behavioral surface
Source
ChildProcessCryptoEnvironmentVarsFilesystemNetworkShell
Supply chain
HighEntropyStringsUrlStrings
Manifest
NoLicense
scanned 1 file(s), 189 KB of source, external domains: claude.com, dash.artor.app, github.com, nodejs.org, registry.npmjs.org

Source & flagged code

5 flagged · loading source
dist/index.jsView file
36try { L37: return JSON.stringify(redactForLog(JSON.parse(body))); L38: } catch { ... L115: try { L116: const raw = readFileSync(new URL("../package.json", import.meta.url), "utf8"); L117: return JSON.parse(raw); ... L142: const body = typeof init2.body === "string" ? redactBody(init2.body) : void 0; L143: process.stderr.write(`\x1B[2m\u2192 ${method} ${url}\x1B[0m L144: `); ... L193: try { L194: res = await fetch(url, { ...init2, headers }); L195: } catch {
Critical
Credential Exfiltration

Source appears to send environment or credential material to an external endpoint.

dist/index.jsView on unpkg · L36
36Trigger-reachable chain: manifest.bin -> dist/index.js L36: try { L37: return JSON.stringify(redactForLog(JSON.parse(body))); L38: } catch { ... L115: try { L116: const raw = readFileSync(new URL("../package.json", import.meta.url), "utf8"); L117: return JSON.parse(raw); ... L142: const body = typeof init2.body === "string" ? redactBody(init2.body) : void 0; L143: process.stderr.write(`\x1B[2m\u2192 ${method} ${url}\x1B[0m L144: `); ... L193: try { L194: res = await fetch(url, { ...init2, headers }); L195: } catch {
Critical
Trigger Reachable Dangerous Capability

A package entrypoint or install-time lifecycle script reaches a source file with blocking dangerous behavior.

dist/index.jsView on unpkg · L36
506// src/build.ts L507: import { spawnSync } from "node:child_process"; L508: function runBuild(cwd, pm) {
High
Child Process

Package source references child process execution.

dist/index.jsView on unpkg · L506
5182} L5183: process.stdout.write(`${plan.message} L5184: `); ... L5188: // src/commands/install.ts L5189: import { spawnSync as spawnSync4 } from "node:child_process"; L5190: ... L5192: var SKILL_REPO = "artorapp/skill"; L5193: var SKILL_SOURCE_URL = "https://github.[redacted]"; L5194: function installPlan(target, platform = process.platform) {
High
Command Output Exfiltration

Source combines command execution, command-output handling, and outbound requests; review data flow before blocking.

dist/index.jsView on unpkg · L5182
36try { L37: return JSON.stringify(redactForLog(JSON.parse(body))); L38: } catch { ... L115: try { L116: const raw = readFileSync(new URL("../package.json", import.meta.url), "utf8"); L117: return JSON.parse(raw); ... L142: const body = typeof init2.body === "string" ? redactBody(init2.body) : void 0; L143: process.stderr.write(`\x1B[2m\u2192 ${method} ${url}\x1B[0m L144: `); ... L193: try { L194: res = await fetch(url, { ...init2, headers }); L195: } catch {
High
Sandbox Evasion Gated Capability

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

dist/index.jsView on unpkg · L36

Findings

2 Critical4 High3 Medium5 Low
CriticalCredential Exfiltrationdist/index.js
CriticalTrigger Reachable Dangerous Capabilitydist/index.js
HighChild Processdist/index.js
HighShell
HighCommand Output Exfiltrationdist/index.js
HighSandbox Evasion Gated Capabilitydist/index.js
MediumNetwork
MediumEnvironment Vars
MediumStructural Risk Force Deep Review
LowScripts Present
LowFilesystem
LowHigh Entropy Strings
LowUrl Strings
LowNo License