registry  /  @aznex/worker  /  0.1.6

@aznex/worker@0.1.6

Aznex local worker — captures coding-agent sessions, extracts memories via your Claude subscription, scrubs secrets, ships them to your team's Aznex service

AI Security Review

scanned 3h ago · by lpm-firewall-ai

LPM treats this as warn-only first-party agent extension lifecycle risk. No confirmed malicious behavior or unconsented install-time mutation was found. The package does create a persistent local worker and modifies Claude Code integration when the user runs setup, so it carries agent extension lifecycle risk.

Static reason
No blocking static signals were detected.
Trigger
User runs `aznex-worker setup`; runtime hooks fire during Claude Code sessions; daemon self-update runs on start/daily.
Impact
Captures selected coding-agent hook data, extracts/scrubs memories locally, and sends structured results to the configured Aznex service; can persist as a user daemon and self-update.
Mechanism
explicit user-command Claude hook/MCP setup plus local worker ingest pipeline
Rationale
Static source inspection supports a warn-level lifecycle risk rather than malicious: agent-control changes are explicit setup behavior, package-aligned, and documented, with no npm install hook or hidden execution path. The persistent daemon, self-update, global Claude hooks, and ingest of coding-session-derived data justify not marking fully clean.
Evidence
package.jsoncli.tssetup.tssrc/index.tssrc/server.tssrc/pipeline.tssrc/ingest-client.tssrc/scrub.tssrc/extract.tssrc/self-update.tshooks/claude-code-hook.tsdaemon/install.ts~/.aznex/config.json~/.aznex/logs/worker.log~/.claude/settings.json~/Library/LaunchAgents/ai.aznex.worker.plist~/.config/systemd/user/aznex-worker.service/tmp/aznex-obs-*.jsonl
Network endpoints12
registry.npmjs.org/@aznex/worker/latestlocalhost:29639/healthlocalhost:29639/hooklocalhost:29639/contextlocalhost:29639/file-context${serviceUrl}/health${serviceUrl}/api/repos${serviceUrl}/v1/ingest${serviceUrl}/mcp${serviceUrl}/api/memories/context${serviceUrl}/api/memories/by-path${serviceUrl}/api/cli-auth/exchange

Decision evidence

public snapshot
AI called this Suspicious at 88.0% confidence as Dangerous Capability with medium false-positive risk.
Evidence for warning
  • setup.ts explicitly writes global Claude Code hooks to ~/.claude/settings.json on `aznex-worker setup`.
  • setup.ts registers a user-scope Claude MCP server named aznex with Authorization header.
  • daemon/install.ts installs launchd/systemd user daemon for persistent background worker.
  • src/self-update.ts daemon checks npm and runs `bun install -g @aznex/worker@latest` unless AZNEX_AUTO_UPDATE=off.
  • src/pipeline.ts processes Claude hook events and posts extracted memories to configured service /v1/ingest.
Evidence against
  • package.json has no npm lifecycle hooks; setup is invoked via bin command, not install-time.
  • server binds only to 127.0.0.1 and hook adapter posts to localhost by default.
  • setup.ts validates user-provided service URL/API key and stores config mode 0600.
  • src/scrub.ts redacts detected secrets before ingest and drops still-dirty memory.
  • src/extract.ts limits Claude extraction tool use to Read and removes temp observation files.
  • README.md describes the daemon, Claude hooks, MCP registration, self-update, and ingest behavior.
Behavioral surface
Source
ChildProcessCryptoEnvironmentVarsFilesystemNetworkShell
Supply chain
HighEntropyStringsUrlStrings
ManifestNo manifest risk signals triggered.
scanned 21 file(s), 65.9 KB of source, external domains: registry.npmjs.org, www.apple.com

Source & flagged code

1 flagged · loading source
setup.tsView file
3// L4: // aznex-worker setup --service-url https://aznex.up.railway.app [--api-key] [--agents claude-code] L5: // aznex-worker setup --uninstall ... L22: L23: const CLAUDE_SETTINGS = join(homedir(), ".claude", "settings.json"); L24: ... L51: async function ask(question: string): Promise<string> { L52: const rl = createInterface({ input: process.stdin, output: process.stdout }); L53: const answer = (await rl.question(question)).trim(); ... L165: const existing = existsSync(CLAUDE_SETTINGS) L166: ? (JSON.parse(readFileSync(CLAUDE_SETTINGS, "utf-8")) as Record<string, unknown>) L167: : {};
Medium
Install Persistence

Source writes installer persistence such as shell profile or service configuration.

setup.tsView on unpkg · L3

Findings

3 Medium4 Low
MediumNetwork
MediumEnvironment Vars
MediumInstall Persistencesetup.ts
LowScripts Present
LowFilesystem
LowHigh Entropy Strings
LowUrl Strings