registry  /  @astrale-os/cli  /  0.6.3-alpha.0

@astrale-os/cli@0.6.3-alpha.0

Astrale CLI — connect to existing Astrale kernels

AI Security Review

scanned 2h ago · by lpm-firewall-ai

Default-on telemetry records normal CLI sessions, then a later ordinary CLI invocation silently starts a detached analyzer. The analyzer finds local Codex/Claude transcripts and launches the authenticated `claude` CLI with instructions to read those transcripts and the workspace.

Static reason
One or more suspicious static signals were detected.
Trigger
Run normal `astrale` commands, allow a session to become idle, then run `astrale` again with telemetry enabled by default.
Impact
Potential exfiltration of local workspace and AI-agent transcript contents to the Claude service without an explicit analysis command or consent.
Mechanism
Automatic local agent-transcript and workspace collection through headless Claude.
Attack narrative
The package defaults telemetry to enabled, records regular CLI invocations, and on a later CLI start automatically analyzes a closed session. That analysis locates local Codex and Claude Code transcript files for the workspace, launches `claude -p`, and explicitly authorizes filesystem inspection of those transcripts and the workspace. Headless Claude analysis is not restricted to an explicit user `session analyze` request, so local developer and agent data can be supplied to an external model service without consent.
Rationale
This is a concrete, default-on, automatic data-collection and external-agent execution chain, not a scanner-only primitive. The benign preinstall guard does not mitigate the runtime exfiltration behavior.
Evidence
package.json.check-workspace.cjsdist/astrale.jssrc/telemetry/settings.tssrc/telemetry/trigger.tssrc/telemetry/analyze.tssrc/telemetry/adapters/codex.tssrc/telemetry/adapters/claude-code.tssrc/telemetry/recorder.ts~/.astrale/sessions/<id>/~/.codex/sessions/~/.claude/projects/

Decision evidence

public snapshot
AI called this Malicious at 93.0% confidence as Malware with low false-positive risk.
Evidence for block
  • `src/telemetry/settings.ts` enables telemetry by default when no config exists.
  • `dist/astrale.js` calls `beginInvocation` and `maybeTriggerAnalysis` on ordinary non-session CLI starts.
  • `src/telemetry/analyze.ts` discovers overlapping Codex/Claude transcripts and directs `claude -p` to inspect them and the workspace.
  • `src/telemetry/analyze.ts` permits Claude `Read`, `Glob`, `Grep`, `LS`, and `Bash(astrale:*)`, then logs its output locally.
Evidence against
  • `.check-workspace.cjs` is a non-mutating workspace-install guard.
  • No preinstall code writes agent configuration or launches network/process payloads.
  • The separate `.claude/skills` symlink is only reached through explicit `astrale setup` and avoids clobbering existing paths.
Behavioral surface
Source
ChildProcessCryptoDynamicRequireEnvironmentVarsEvalFilesystemNetworkShell
Supply chain
HighEntropyStringsMinifiedObfuscatedTelemetryUrlStrings
Manifest
WildcardDependency
scanned 197 file(s), 1.94 MB of source, external domains: 127.0.0.1, admin.eu.astrale.ai, api.example.com, api.workos.com, bun.sh, contract.astrale.ai, crm.acme.dev, crm.workers.dev, example.authkit.app, github.com, json-schema.org, kernel.example.com, raw.githubusercontent.com, react.dev, registry.npmjs.org, unregistered.invalid, www.w3.org
Oversized source lightweight scan
dist/astrale.js2.49 MB file, sampled 256 KB
FilesystemNetworkChildProcessEnvironmentVarsCryptoShellHighEntropyStringsUrlStrings127.0.0.1admin.eu.astrale.aiapi.example.comapi.workos.comcontract.astrale.aicrm.acme.devcrm.workers.devexample.authkit.appgithub.comkernel.example.comregistry.npmjs.org
studio/client/dist/assets/index-CyN5G8IA.js2.38 MB file, sampled 256 KB
NetworkHighEntropyStringsMinifiedTelemetryUrlStringsreact.dev

Source & flagged code

9 flagged · loading source
package.jsonView file
scripts.preinstall = node .check-workspace.cjs
High
Install Time Lifecycle Scripts

Package defines install-time lifecycle scripts.

package.jsonView on unpkg
studio/server/agent/claude.tsView file
11*/ L12: import { spawn } from 'node:child_process' L13: import { existsSync, readdirSync, readFileSync } from 'node:fs'
High
Child Process

Package source references child process execution.

studio/server/agent/claude.tsView on unpkg · L11
src/commands/studio.tsView file
103function openBrowser(url: string): void { L104: // win32: `start` is a cmd.exe builtin, not a PATH executable — must go through L105: // `cmd /c start "" <url>` (the empty "" is the title arg `start` consumes).
High
Shell

Package source references shell execution.

src/commands/studio.tsView on unpkg · L103
viewer/dist/main.jsView file
1var $I=Object.defineProperty;var JI=($)=>$;function vI($,J){this[$]=JI.bind(null,J)}var o4=($,J)=>{for(var Q in J)$I($,Q,{get:J[Q],enumerable:!0,configurable:!0,set:vI.bind(J,Q)})}... L2: `)}var j1=($)=>(J,Q,X,v)=>{let W=X?{...X,async:!1}:{async:!1},Y=J._zod.run({value:Q,issues:[]},W);if(Y instanceof Promise)throw new E4;if(Y.issues.length){let V=new(v?.Err??$)(Y.is...
Low
Eval

Package source references a known benign dynamic code generation pattern.

viewer/dist/main.jsView on unpkg · L1
studio/server/introspect/core-extractor.tsView file
75if (!domainFile) throw new Error('core-extractor: missing <domainFile>') L76: const mod: AnyRec = await import(domainFile) L77: const core = findCore(mod)
Medium
Dynamic Require

Package source references dynamic require/import behavior.

studio/server/introspect/core-extractor.tsView on unpkg · L75
studio/server/view-dev-server.tsView file
150const port = await this.reservePort() L151: const url = `http://127.0.0.1:${port}` L152: const child = spawn( L153: 'pnpm', ... L157: detached: process.platform !== 'win32', L158: env: { ...process.env, BROWSER: 'none', FORCE_COLOR: '0', NO_UPDATE_NOTIFIER: '1' }, L159: stdio: ['ignore', 'pipe', 'pipe'],
High
Same File Env Network Execution

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

studio/server/view-dev-server.tsView on unpkg · L150
src/lib/idp.tsView file
210entry: IdpIndexEntry L211: metadata: OidcMetadata L212: client: IdpClientConfig ... L215: export const BUILTIN_WORKOS_IDP_NAME = 'workos' L216: const DEFAULT_WORKOS_API_HOST = 'https://api.workos.com' L217: const DEFAULT_WORKOS_CLIENT_ID = 'client_01KC29HEGD7B40TV2C4QZ436BG' ... L239: const raw = await readFile(IDPS_PATH, 'utf-8') L240: return IdpStoreSchema.parse(JSON.parse(raw)) L241: } catch (e) { ... L390: clientIdOverride?: string, L391: env: NodeJS.ProcessEnv = process.env, L392: ): IdpConfig | null {
High
Credential Exfiltration

Source combines credential-like environment material and outbound requests; review data flow before blocking.

src/lib/idp.tsView on unpkg · L210
studio/client/dist/assets/index-CyN5G8IA.jsView file
path = studio/client/dist/assets/index-CyN5G8IA.js kind = oversized_source_file sizeBytes = 2499950 magicHex = [redacted]
High
Oversized Source File

Package contains source files above the static scanner size ceiling.

studio/client/dist/assets/index-CyN5G8IA.jsView on unpkg
dist/astrale.jsView file
path = dist/astrale.js kind = oversized_cli_entrypoint sizeBytes = 2613030 magicHex = [redacted]
Medium
Oversized Cli Entrypoint

Package contains an oversized executable-looking CLI entrypoint.

dist/astrale.jsView on unpkg

Findings

6 High6 Medium7 Low
HighInstall Time Lifecycle Scriptspackage.json
HighChild Processstudio/server/agent/claude.ts
HighShellsrc/commands/studio.ts
HighSame File Env Network Executionstudio/server/view-dev-server.ts
HighCredential Exfiltrationsrc/lib/idp.ts
HighOversized Source Filestudio/client/dist/assets/index-CyN5G8IA.js
MediumDynamic Requirestudio/server/introspect/core-extractor.ts
MediumNetwork
MediumEnvironment Vars
MediumOversized Cli Entrypointdist/astrale.js
MediumStructural Risk Force Deep Review
MediumWildcard Dependency
LowScripts Present
LowEvalviewer/dist/main.js
LowFilesystem
LowObfuscated
LowHigh Entropy Strings
LowTelemetry
LowUrl Strings