registry  /  @firatcand/roster  /  1.8.0

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

LPM treats this as warn-only first-party agent extension lifecycle risk. No confirmed malicious attack surface. The package is an AI-agent workspace CLI that can modify agent/tool config under user-invoked commands, creating lifecycle risk but not unconsented install-time hijack.

Static reason
High-risk behavior combination matched malicious policy.
Trigger
User runs roster install, roster schedule install, roster skills sync, second-opinion, or brain/task subcommands.
Impact
Can add skills/agents, schedules, and service integrations chosen by the user; no evidence of stealth exfiltration or automatic persistence.
Mechanism
explicit CLI scaffolding and integration setup for AI agent tools
Rationale
Source inspection shows risky but package-aligned AI-agent setup capabilities activated by user CLI commands, with no install-time mutation, credential exfiltration, remote payload execution, or stealth persistence. This should not be publish-blocked, but the agent control-surface writes justify a warning classification.
Evidence
package.jsonbin/roster.jsbin/tripwire-hook.jsREADME.mdtemplates/hooks/banner.sh.claude/skills.claude/agents.agents/skills.codex/agents.gemini/extensions.gemini/agents.roster/schedule-specscrontabconfig/project.yaml.env.example.gitignore
Network endpoints4
api.notion.comapi.openai.com/v1/embeddingsgithub.com/firatcand/founder-skillsgithub.com/openai/codex

Decision evidence

public snapshot
AI called this Suspicious at 86.0% confidence as Benign with medium false-positive risk.
Evidence for warning
  • bin/roster.js writes bundled skills/agents into .claude, .codex/.agents, and .gemini config paths via user-invoked install.
  • bin/roster.js can install Codex schedules by writing crontab entries that spawn codex exec.
  • bin/roster.js can fetch/install founder skills from GitHub through explicit roster skills sync using npx skills add.
Evidence against
  • package.json has no preinstall/install/postinstall lifecycle scripts.
  • bin/roster.js main dispatch only runs actions from CLI subcommands; no import-time payload beyond setup.
  • Network use is feature-aligned: Notion API, OpenAI embeddings, S3, Postgres, GitHub skill sources.
  • Credential reads are for preflight/config or user-selected services, not sent to attacker-controlled endpoints.
  • Install paths include root containment and symlink checks before writes.
Behavioral surface
Source
ChildProcessCryptoEnvironmentVarsFilesystemNetworkShell
Supply chain
HighEntropyStringsUrlStrings
ManifestNo manifest risk signals triggered.
scanned 2 file(s), 545 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