// npm package
@actagent/acpx
ACTAgent ACP runtime backend with plugin-owned session and transport management.
versions
1
maintainers
1
first publish
2026-06-05
publisher
nidaye0525
tarball
407,730 B
AUTO-PUBLISHED·1 version indexed·latest published 2026-06-05
// exfil path
what is read → where it shipssteals
- ● npm token
- ● GitHub PAT
- ● AI API keys
- ○ home dir
sends to
(no destination string extracted — payload may be dynamic / obfuscated)
→ view full payload// publisher campaignby nidaye0525
2 caught packages from this accountThis is not an isolated catch. The same publisher has shipped 1 other package that our pipeline flagged — the shape of a coordinated campaign, not a one-off. Each link below opens that sibling's analysis.
// offending code· @2026.6.2· 3 files flagged
- @2026.6.2··AUTO-PUBLISHED·publisher: nidaye0525heuristic 74/100static flags 6llm skippednew-publisher:0dfirst-version-of-packagehas-source-repopublisher-multi-name-burst:10publisher-version-pump:11reads-env-varsreads-npmrcreads-github-tokensreads-ai-api-keysreads-homedirchild-process-spawn
// offending code· 3 files flaggedpatterns: 6
--- package/register.runtime.ts (excerpt) --- /** * Lazy ACPX runtime service registration. The plugin exposes an ACP backend * immediately, then imports the heavier service only when a session needs it. */ import { getAcpRuntimeBackend, registerAcpRuntimeBackend, unregisterAcpRuntimeBackend, type AcpRuntime, } from "actagent/plugin-sdk/acp-runtime-backend"; import type { ACTAgentPluginService, ACTAgentPluginServiceContext } from "actagent/plugin-sdk/core"; import { createLazyAcpRuntimeProxy } from "./src/runtime-proxy.js"; const ACPX_BACKEND_ID = "acpx"; type RealAcpxServiceModule = typeof import("./src/service.js"); type CreateAcpxRuntimeServiceParams = NonNullable< Parameters<RealAcpxServiceModule["createAcpxRuntimeService"]>[0] >; type DeferredServiceState = { ctx: ACTAgentPluginServiceContext | null; params: CreateAcpxRuntimeServiceParams; realRuntime: AcpRuntime | null; realService: ACTAgentPluginService | null; startPromise: Promise<AcpRuntime> | null; }; let serviceModulePromise: Promise<RealAcpxServiceModule> | null = null; function loadServiceModule(): Promise<RealAcpxServiceModule> { serviceModulePromise ??= import("./src/service.js"); return serviceModulePromise; } async function startRealService(state: DeferredServiceState): Promise<AcpRuntime> { if (state.realRuntime) { return state.realRuntime; } if (!state.ctx) { throw new Error("ACPX runtime service is not started"); } state.startPromise ??= (async () => { const { createAcpxRuntimeService: createAcpx --- package/src/codex-auth-bridge.ts (excerpt) --- /** * Prepares isolated Codex and Claude ACP wrapper commands for ACPX. The bridge * copies safe auth/config state into plugin-owned homes and redacts diagnostics. */ import fsSync from "node:fs"; import fs from "node:fs/promises"; import { createRequire } from "node:module"; import os from "node:os"; import path from "node:path"; import { readJsonFileWithFallback } from "actagent/plugin-sdk/json-store"; import { extractTrustedCodexProjectPaths, renderIsolatedCodexConfig, } from "./codex-trust-config.js"; import { quoteCommandPart, splitCommandParts } from "./command-line.js"; import { resolveAcpxPluginRoot } from "./config.js"; import type { ResolvedAcpxPluginConfig } from "./config.js"; import { ACTAGENT_ACPX_LEASE_ID_ARG, ACTAGENT_ACPX_LEASE_ID_ENV, ACTAGENT_GATEWAY_INSTANCE_ID_ARG, } from "./process-lease.js"; const CODEX_ACP_PACKAGE = "@zed-industries/codex-acp"; const CODEX_ACP_BIN = "codex-acp"; const CLAUDE_ACP_PACKAGE = "@agentclientprotocol/claude-agent-acp"; const CLAUDE_ACP_BIN = "claude-agent-acp"; const RUN_CONFIGURED_COMMAND_SENTINEL = "--actagent-run-configured"; const requireFromHere = createRequire(import.meta.url); type PackageManifest = { name?: unknown; bin?: unknown; dependencies?: Record<string, unknown>; }; function readSelfManifest(): PackageManifest { const manifestPath = path.join(resolveAcpxPluginRoot(import.meta.url), "package.json"); return JSON.parse(fsSync.readFileSync(manifestPath, "utf8")) as PackageManifest; } func --- package/src/codex-trust-config.ts (excerpt) --- /** * Builds isolated Codex config for ACPX sessions. It preserves safe inherited * runtime options while rendering only trusted project entries for the session. */ import path from "node:path"; function stripTomlComment(line: string): string { let quote: "'" | '"' | null = null; let escaping = false; for (let index = 0; index < line.length; index += 1) { const ch = line[index]; if (escaping) { escaping = false; continue; } if (quote === '"' && ch === "\\") { escaping = true; continue; } if (quote) { if (ch === quote) { quote = null; } continue; } if (ch === "'" || ch === '"') { quote = ch; continue; } if (ch === "#") { return line.slice(0, index); } } return line; } function parseTomlString(value: string): string | undefined { const trimmed = value.trim(); if (trimmed.startsWith('"') && trimmed.endsWith('"')) { try { return JSON.parse(trimmed) as string; } catch { return undefined; } } if (trimmed.startsWith("'") && trimmed.endsWith("'")) { return trimmed.slice(1, -1); } return undefined; } function parseTomlDottedKey(value: string): string[] { const parts: string[] = []; let current = ""; let quote: "'" | '"' | null = null; let escaping = false; for (const ch of value.trim()) { if (escaping) { current += ch; escaping = false; continue; } if (quote === '"' && ch === "\\
