registry  /  @firatcand/roster  /  1.6.0

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

No confirmed malicious attack surface by source inspection. Risky primitives are user-invoked CLI features aligned with a multi-agent workspace scaffolder.

Static reason
High-risk behavior combination matched malicious policy.; previous stored version diff introduced dangerous source
Trigger
User runs roster CLI subcommands such as install, hooks install, schedule, skills, brain, or task.
Impact
Expected local workspace/tool configuration changes and optional calls to configured third-party APIs.
Mechanism
scaffolding, hook installation, scheduler management, and optional API integrations
Rationale
Static inspection found no install-time/import-time execution, credential harvesting, or unconsented exfiltration; scanner hits map to documented CLI capabilities. AI hook and cron mutations are explicit user commands with bounded, visible target files.
Evidence
package.jsonbin/roster.jsbin/tripwire-hook.jstemplates/hooks/banner.sh
Network endpoints4
api.notion.comapi.openai.com/v1/embeddingsgithub.com/${owner}/${repo}.gitgithub.com/${owner}/${repo}/tree/${spec.ref}/${spec.skill}

Decision evidence

public snapshot
AI called this Clean at 92.0% confidence as Benign with low false-positive risk.
Evidence for block
    Evidence against
    • package.json has no install/preinstall/postinstall lifecycle hooks; only a user-invoked bin entry bin/roster.js.
    • bin/roster.js network use is package-aligned: Notion API, OpenAI embeddings, GitHub tag/skill fetches.
    • bin/roster.js child_process use is tied to explicit CLI features such as crontab scheduling, git/npx founder-skills sync, and tool invocation.
    • Hook writes in bin/roster.js are behind explicit `roster hooks install` and install visible Claude/Codex hook configs, not lifecycle execution.
    • bin/tripwire-hook.js scans tool output for prompt-injection/secret-egress patterns and does not send data externally.
    • File writes target scaffold/workspace or AI-tool config paths for documented install/init/doctor/schedule commands.
    Behavioral surface
    Source
    ChildProcessCryptoEnvironmentVarsFilesystemNetworkShell
    Supply chain
    HighEntropyStringsUrlStrings
    ManifestNo manifest risk signals triggered.
    scanned 2 file(s), 496 KB of source, external domains: api.notion.com, claude.ai, developers.openai.com, github.com

    Source & flagged code

    8 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
    matchType = previous_version_dangerous_delta matchedPackage = @firatcand/roster@1.5.0 matchedIdentity = npm:QGZpcmF0Y2FuZC9yb3N0ZXI:1.5.0 similarity = 0.500 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; route for source-aware review.

    bin/roster.jsView on unpkg
    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

    3 Critical3 High5 Medium5 Low
    CriticalCredential Exfiltrationbin/roster.js
    CriticalTrigger Reachable Dangerous Capabilitybin/roster.js
    CriticalPrevious Version Dangerous Deltabin/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