registry  /  relay-companion  /  0.1.5

relay-companion@0.1.5

Relay companion: connects local coding agents to Relay tasks, approvals, and connector tools.

AI Security Review

scanned 12d ago · by lpm-firewall-ai

No confirmed malicious attack surface. The package is an explicit Relay companion CLI/MCP/daemon that can persist itself and integrate with local AI agents only after user-invoked setup/install.

Static reason
No blocking static signals were detected.; previous stored version diff introduced dangerous source
Trigger
User runs `relay pair`, `relay setup`, `relay install`, `relay daemon`, `relay mcp`, or `relay open`.
Impact
Package-aligned local Relay integration; no unconsented install-time execution or unrelated data theft identified.
Mechanism
User-invoked Relay CLI, MCP server, daemon, and agent-session materialization
Rationale
Static inspection shows powerful AI-agent integration and persistence features, but they are explicit product functionality activated by user commands and not lifecycle/import-time abuse. No concrete credential harvesting, unrelated exfiltration, destructive action, or unconsented AI-agent control mutation was found.
Evidence
package.jsonbin/relay.jssrc/install.jssrc/config.jssrc/client.jssrc/mcp.jssrc/task-daemon.jssrc/runtime.jssrc/setup-activation.jssrc/codex-session-writer.jssrc/claude-session-writer.jssrc/host-paths.js~/.relay/config.json~/.relay/task-ledger.json~/Library/LaunchAgents/work.relay.companion.plist~/Library/LaunchAgents/work.relay.companion.pill.plist~/.relay-companion~/.codex~/.claude
Network endpoints2
aia6vj5pgp.us-east-1.awsapprunner.comsendrelays.com

Decision evidence

public snapshot
AI called this Clean at 86.0% confidence as Benign with medium false-positive risk.
Evidence for block
  • src/install.js registers Relay MCP into Claude/Codex and creates macOS LaunchAgents, but only from explicit `relay setup`/`relay install` commands.
  • src/runtime.js can launch Codex/Claude task agents with permissive settings for Relay background tasks, a high-risk but package-aligned capability.
Evidence against
  • package.json has no preinstall/install/postinstall lifecycle hooks; main/bin only runs when invoked as `relay`.
  • bin/relay.js dispatches explicit commands and does not run pairing, install, daemon, or agent launch at import time.
  • src/config.js stores only Relay device config under ~/.relay and uses documented RELAY_* env overrides.
  • src/client.js network traffic is to configured Relay API endpoints with bearer device token, matching package purpose.
  • src/mcp.js exposes Relay messaging/task/connector tools over MCP; no credential harvesting or unrelated exfiltration found.
  • No obfuscated payloads, destructive filesystem behavior, or reviewer/prompt manipulation found in inspected source.
Behavioral surface
Source
ChildProcessCryptoDynamicRequireEnvironmentVarsFilesystemNetworkShell
Supply chain
HighEntropyStringsUrlStrings
Manifest
NoLicense
scanned 23 file(s), 251 KB of source, external domains: aia6vj5pgp.us-east-1.awsapprunner.com, sendrelays.com, www.apple.com

Source & flagged code

3 flagged · loading source
bin/relay.jsView file
matchType = previous_version_dangerous_delta matchedPackage = relay-companion@0.1.3 matchedIdentity = npm:cmVsYXktY29tcGFuaW9u:0.1.3 similarity = 0.762 summary = stored previous version shares package body but lacks this dangerous source file
Critical
Previous Version Dangerous Delta

This package version adds a dangerous source file absent from the previous stored version.

bin/relay.jsView on unpkg
239const overlayMain = path.resolve(here, "../overlay/main.cjs"); L240: // require("electron") returns the path to the electron binary when resolved under node. L241: let electronPath;
Medium
Dynamic Require

Package source references dynamic require/import behavior.

bin/relay.jsView on unpkg · L239
src/install.jsView file
1import { spawnSync } from "node:child_process"; L2: import fs from "node:fs"; ... L50: const rootRes = spawnSync("npm", ["root", "-g"], { encoding: "utf8", timeout: 20_000 }); L51: const root = (rootRes.stdout || "").trim(); L52: const globalBin = path.join(root, ...PACKAGE_NAME.split("/"), "bin", "relay.js"); ... L67: try { L68: const require = createRequire(path.join(packageRoot, "package.json")); L69: const electronPath = require("electron"); ... L97: export function installDaemonAutostart(bin = relayBinPath(), node = process.execPath) { L98: if (process.platform !== "darwin") return { ok: false, reason: "autostart_unsupported_platform" }; L99: const home = os.homedir(); L100: const plistPath = path.join(home, "Library", "LaunchAgents", `${DAEMON_LAUNCH_LABEL}.plist`);
Medium
Install Persistence

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

src/install.jsView on unpkg · L1

Findings

1 Critical4 Medium5 Low
CriticalPrevious Version Dangerous Deltabin/relay.js
MediumDynamic Requirebin/relay.js
MediumNetwork
MediumEnvironment Vars
MediumInstall Persistencesrc/install.js
LowScripts Present
LowFilesystem
LowHigh Entropy Strings
LowUrl Strings
LowNo License