registry  /  @firatcand/roster  /  1.7.0

@firatcand/roster@1.7.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 2h ago · by lpm-firewall-ai

No confirmed malicious attack surface. This is a user-invoked CLI for scaffolding roster workspaces and installing first-party skills/agents into AI tool config directories.

Static reason
High-risk behavior combination matched malicious policy.
Trigger
User runs roster commands such as install, init, hooks, schedule, or migrate.
Impact
Creates or updates roster project files, skills, agents, hooks, schedules, and templates as documented CLI behavior.
Mechanism
explicit workspace and AI-tool scaffold/config writer
Rationale
Source inspection supports a benign scaffolding CLI with explicit user-command mutation of first-party/project AI-agent extensions, not install-time hijack, credential exfiltration, or remote payload execution. Scanner hints appear to conflate package-aligned config writing, secret-safety text, and local subprocess use with malicious behavior.
Evidence
package.jsonbin/roster.jsbin/tripwire-hook.jstemplates/hooks/banner.shtemplates/scaffold/founder-skills.yaml.example~/.claude/skills~/.claude/agents~/.codex/agents~/.agents/skills~/.gemini/extensions~/.gemini/agentsCLAUDE.mdAGENTS.mdCONTEXT.mdconfig/project.yamlroster/
Network endpoints6
claude.ai/codegithub.com/openai/codexgithub.com/google-gemini/gemini-cligithub.com/firatcand/roster.gitgithub.com/firatcand/roster#readmegithub.com/firatcand/roster/issues

Decision evidence

public snapshot
AI called this Clean at 78.0% confidence as Benign with low false-positive risk.
Evidence for block
  • CLI can write AI tool skills/agents under Claude, Codex, and Gemini config roots on user command.
  • bin/tripwire-hook.js contains scanner logic for risky prompt text, including secret-egress patterns.
Evidence against
  • package.json has no preinstall/install/postinstall lifecycle hooks.
  • bin/roster.js network strings are help/repository/install URLs; no outbound request flow found.
  • process.env usage is limited to ROSTER_* home overrides/config, not credential harvesting.
  • child_process use appears in explicit CLI flows such as git init, probes, and script execution.
  • Writes are package-aligned scaffolding/config operations guarded by commands, prompts, force flags, and path checks.
Behavioral surface
Source
ChildProcessCryptoEnvironmentVarsFilesystemNetworkShell
Supply chain
HighEntropyStringsUrlStrings
ManifestNo manifest risk signals triggered.
scanned 2 file(s), 523 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
5224if (fromEnv !== void 0 && fromEnv !== "") return fromEnv; L5225: const r = spawnSync("/bin/sh", ["-c", "command -v codex"], { L5226: encoding: "utf8", ... L5229: if (r.status === 0) { L5230: const out = (r.stdout ?? "").trim(); L5231: if (out.length > 0) return out; ... L5234: header: `${chalk.red.bold("roster:")} codex binary not found on PATH`, L5235: body: " Install codex CLI (https://developers.openai.com/codex) and ensure it is on your PATH.", L5236: 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 · L5224
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