registry  /  @firatcand/roster  /  1.5.0

@firatcand/roster@1.5.0

A CLI that scaffolds a structured multi-agent workspace on top of AI coding tools (Claude Code, Codex CLI, Gemini)

AI Security Review

scanned 4d ago · by lpm-firewall-ai

No confirmed malicious attack surface was established. The risky primitives are package-aligned CLI features for installing agent assets, hooks, schedules, task integrations, and optional embeddings.

Static reason
High-risk behavior combination matched malicious policy.
Trigger
User runs the roster CLI subcommands such as install, hooks install, schedule install, skills sync, task, or brain.
Impact
Can write project/user AI-tool configuration and schedules by design; no evidence of unauthorized install-time execution, secret harvesting, or unrelated exfiltration.
Mechanism
User-invoked workspace and AI-tool scaffolding CLI
Rationale
Static inspection shows a large AI-agent workspace CLI with powerful but disclosed, user-invoked behavior and no lifecycle hook or import-time execution. Scanner exfiltration and persistence labels appear to be false positives from package-aligned API clients, credential preflight checks, crontab scheduling, and hook installation.
Evidence
package.jsonbin/roster.jsbin/tripwire-hook.jstemplates/hooks/banner.shREADME.md
Network endpoints7
api.notion.comapi.openai.com/v1/embeddingsgithub.comraw.githubusercontent.comclaude.ai/codegithub.com/openai/codexgithub.com/google-gemini/gemini-cli

Decision evidence

public snapshot
AI called this Clean at 88.0% confidence as Benign with medium false-positive risk.
Evidence for block
  • bin/roster.js imports child_process and can spawn git, npx, crontab, and codex from explicit subcommands.
  • bin/roster.js can install skills/agents and hooks into .claude, .codex, .gemini or user home when the CLI is invoked.
  • bin/roster.js has user-configured network integrations for Notion, OpenAI embeddings, and GitHub skill refs.
Evidence against
  • package.json has no preinstall/install/postinstall lifecycle scripts; only a roster bin entrypoint.
  • README.md discloses the CLI purpose: scaffold/install AI-tool skills, agents, schedules, hooks, Notion tasks, and optional embeddings.
  • bin/roster.js network calls are tied to named user commands/config such as task, brain embeddings, skills sync/update; no import-time exfiltration path found.
  • Credential/env reads are validation or user-authenticated API use, not collection to an unrelated endpoint.
  • File writes are bounded by workspace/tool paths with path traversal checks and prompts for symlink replacement.
Behavioral surface
Source
ChildProcessCryptoEnvironmentVarsFilesystemNetworkShell
Supply chain
HighEntropyStringsUrlStrings
ManifestNo manifest risk signals triggered.
scanned 2 file(s), 479 KB of source, external domains: api.notion.com, claude.ai, developers.openai.com, github.com

Source & flagged code

7 flagged · loading source
bin/roster.jsView file
11import YAML, { parse, stringify } from "yaml"; L12: import { execFile, execFileSync, spawn, spawnSync } from "node:child_process"; L13: import { createInterface } from "node:readline"; ... L24: for (const dir of candidates) try { L25: if (JSON.parse(readFileSync(resolve(dir, "package.json"), "utf8")).name === "@firatcand/roster") return dir; L26: } catch { ... L39: function claudeHome$1() { L40: return process.env["ROSTER_CLAUDE_HOME"] ?? join(homedir(), ".claude"); L41: } ... L59: agentsLayout: "md-copy", L60: installLink: "https://claude.ai/code" L61: },
Critical
Credential Exfiltration

Source appears to send environment or credential material to an external endpoint.

bin/roster.jsView on unpkg · L11
11Trigger-reachable chain: manifest.bin -> bin/roster.js L11: import YAML, { parse, stringify } from "yaml"; L12: import { execFile, execFileSync, spawn, spawnSync } from "node:child_process"; L13: import { createInterface } from "node:readline"; ... L24: for (const dir of candidates) try { L25: if (JSON.parse(readFileSync(resolve(dir, "package.json"), "utf8")).name === "@firatcand/roster") return dir; L26: } catch { ... L39: function claudeHome$1() { L40: return process.env["ROSTER_CLAUDE_HOME"] ?? join(homedir(), ".claude"); L41: } ... L59: agentsLayout: "md-copy", L60: installLink: "https://claude.ai/code" L61: },
Critical
Trigger Reachable Dangerous Capability

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

bin/roster.jsView on unpkg · L11
11import YAML, { parse, stringify } from "yaml"; L12: import { execFile, execFileSync, spawn, spawnSync } from "node:child_process"; L13: import { createInterface } from "node:readline";
High
Child Process

Package source references child process execution.

bin/roster.jsView on unpkg · L11
5195if (fromEnv !== void 0 && fromEnv !== "") return fromEnv; L5196: const r = spawnSync("/bin/sh", ["-c", "command -v codex"], { L5197: encoding: "utf8", ... L5200: if (r.status === 0) { L5201: const out = (r.stdout ?? "").trim(); L5202: if (out.length > 0) return out; ... L5205: header: `${chalk.red.bold("roster:")} codex binary not found on PATH`, L5206: body: " Install codex CLI (https://developers.openai.com/codex) and ensure it is on your PATH.", L5207: remedy: " Or pass ROSTER_CODEX_PATH=/abs/path/to/codex when invoking roster.",
High
Command Output Exfiltration

Source combines command execution, command-output handling, and outbound requests; review data flow before blocking.

bin/roster.jsView on unpkg · L5195
11import YAML, { parse, stringify } from "yaml"; L12: import { execFile, execFileSync, spawn, spawnSync } from "node:child_process"; L13: import { createInterface } from "node:readline"; ... L24: for (const dir of candidates) try { L25: if (JSON.parse(readFileSync(resolve(dir, "package.json"), "utf8")).name === "@firatcand/roster") return dir; L26: } catch { ... L39: function claudeHome$1() { L40: return process.env["ROSTER_CLAUDE_HOME"] ?? join(homedir(), ".claude"); L41: } ... L59: agentsLayout: "md-copy", L60: installLink: "https://claude.ai/code" L61: },
Medium
Install Persistence

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

bin/roster.jsView on unpkg · L11
11import YAML, { parse, stringify } from "yaml"; L12: import { execFile, execFileSync, spawn, spawnSync } from "node:child_process"; L13: import { createInterface } from "node:readline"; ... L24: for (const dir of candidates) try { L25: if (JSON.parse(readFileSync(resolve(dir, "package.json"), "utf8")).name === "@firatcand/roster") return dir; L26: } catch { ... L39: function claudeHome$1() { L40: return process.env["ROSTER_CLAUDE_HOME"] ?? join(homedir(), ".claude"); L41: } ... L59: agentsLayout: "md-copy", L60: installLink: "https://claude.ai/code" L61: },
Low
Weak Crypto

Package source references weak cryptographic algorithms.

bin/roster.jsView on unpkg · L11
templates/hooks/banner.shView file
path = templates/hooks/banner.sh kind = build_helper sizeBytes = 2362 magicHex = [redacted]
Medium
Ships Build Helper

Package ships non-JavaScript build or shell helper files.

templates/hooks/banner.shView on unpkg

Findings

2 Critical3 High5 Medium5 Low
CriticalCredential Exfiltrationbin/roster.js
CriticalTrigger Reachable Dangerous Capabilitybin/roster.js
HighChild Processbin/roster.js
HighShell
HighCommand Output Exfiltrationbin/roster.js
MediumNetwork
MediumEnvironment Vars
MediumInstall Persistencebin/roster.js
MediumShips Build Helpertemplates/hooks/banner.sh
MediumStructural Risk Force Deep Review
LowScripts Present
LowWeak Cryptobin/roster.js
LowFilesystem
LowHigh Entropy Strings
LowUrl Strings