registry  /  @swirls/cli  /  0.1.100

@swirls/cli@0.1.100

Swirls command line application

AI Security Review

scanned 4d ago · by lpm-firewall-ai

Global installation triggers an unpinned remote shell installer. The behavior is package-aligned but gives swirls.ai install-time code execution outside npm package integrity.

Static reason
High-risk behavior combination matched malicious policy.
Trigger
npm install -g @swirls/cli or Bun global install with lifecycle scripts enabled
Impact
Remote installer can execute arbitrary shell commands and replace bin/swirls with an external binary
Mechanism
postinstall curl-to-bash remote installer
Attack narrative
On global non-CI Unix installs, npm runs scripts/install.js. That script executes curl -fsSL https://swirls.ai/install | bash, then copies the resulting $HOME/.local/bin/swirls into the package bin path and marks it executable.
Rationale
The package contains real install-time remote code execution, but the endpoint and binary installation are disclosed and aligned with the Swirls CLI purpose. Without evidence of credential theft, persistence, destructive behavior, or unrelated endpoints, this is dangerous/unpinned installer behavior rather than confirmed malware.
Evidence
package.jsonscripts/install.jsbin/swirlsREADME.md$HOME/.local/bin/swirls
Network endpoints1
swirls.ai/install

Decision evidence

public snapshot
AI called this Suspicious at 86.0% confidence as Dangerous Capability with medium false-positive risk.
Evidence for warning
  • package.json defines postinstall: node scripts/install.js
  • scripts/install.js runs execSync('curl -fsSL https://swirls.ai/install | bash') on global non-CI Unix installs
  • scripts/install.js copies $HOME/.local/bin/swirls over package bin/swirls and chmods it executable
Evidence against
  • README.md documents this as a global CLI installer for Swirls
  • bin/swirls is a placeholder telling users postinstall installs the real CLI
  • No credential harvesting, persistence, destructive file operations, or unrelated exfiltration found in package source
  • Network endpoint is swirls.ai, matching package author/docs
Behavioral surface
Source
ChildProcessEnvironmentVarsFilesystemShell
Supply chain
UrlStrings
Manifest
NoLicense
scanned 1 file(s), 1.35 KB of source, external domains: swirls.ai

Source & flagged code

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

Package defines install-time lifecycle scripts.

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

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

package.jsonView on unpkg
scripts/install.jsView file
13L14: import { execSync } from 'node:child_process' L15: import { chmodSync, copyFileSync, existsSync } from 'node:fs' ... L18: L19: const INSTALL_URL = 'https://swirls.ai/install' L20: ... L28: const INSTALLED_BINARY = join( L29: process.env.HOME || process.env.USERPROFILE || '', L30: '.local', ... L36: L37: if (process.env.CI === 'true' || process.env.CI === '1') { L38: process.exit(0)
Critical
Download Execute

Source downloads or fetches remote code and executes it.

scripts/install.jsView on unpkg · L13
13Trigger-reachable chain: scripts.postinstall -> scripts/install.js L13: L14: import { execSync } from 'node:child_process' L15: import { chmodSync, copyFileSync, existsSync } from 'node:fs' ... L18: L19: const INSTALL_URL = 'https://swirls.ai/install' L20: ... L28: const INSTALLED_BINARY = join( L29: process.env.HOME || process.env.USERPROFILE || '', L30: '.local', ... L36: L37: if (process.env.CI === 'true' || process.env.CI === '1') { L38: process.exit(0)
Critical
Trigger Reachable Dangerous Capability

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

scripts/install.jsView on unpkg · L13
13L14: import { execSync } from 'node:child_process' L15: import { chmodSync, copyFileSync, existsSync } from 'node:fs'
High
Child Process

Package source references child process execution.

scripts/install.jsView on unpkg · L13
49stdio: 'inherit', L50: shell: true, L51: })
High
Shell

Package source references shell execution.

scripts/install.jsView on unpkg · L49
13L14: import { execSync } from 'node:child_process' L15: import { chmodSync, copyFileSync, existsSync } from 'node:fs' ... L18: L19: const INSTALL_URL = 'https://swirls.ai/install' L20: ... L28: const INSTALLED_BINARY = join( L29: process.env.HOME || process.env.USERPROFILE || '', L30: '.local', ... L36: L37: if (process.env.CI === 'true' || process.env.CI === '1') { L38: process.exit(0)
High
Sandbox Evasion Gated Capability

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

scripts/install.jsView on unpkg · L13

Findings

2 Critical4 High3 Medium4 Low
CriticalDownload Executescripts/install.js
CriticalTrigger Reachable Dangerous Capabilityscripts/install.js
HighInstall Time Lifecycle Scriptspackage.json
HighChild Processscripts/install.js
HighShellscripts/install.js
HighSandbox Evasion Gated Capabilityscripts/install.js
MediumAmbiguous Install Lifecycle Scriptpackage.json
MediumEnvironment Vars
MediumStructural Risk Force Deep Review
LowScripts Present
LowFilesystem
LowUrl Strings
LowNo License