registry  /  @spinabot/brigade  /  1.19.2

@spinabot/brigade@1.19.2

Brigade — your personal AI crew

AI Security Review

scanned 5d ago · by lpm-firewall-ai

No confirmed malicious attack surface was found. The main concern is a postinstall cosmetic write into a dependency's OAuth callback page, but inspected source shows branding-only behavior without exfiltration or execution payload.

Static reason
High-risk behavior combination matched malicious policy.
Trigger
npm install runs postinstall; runtime actions are user-invoked CLI commands
Impact
No confirmed credential theft, persistence, destructive action, or unauthorized network exfiltration
Mechanism
CLI dispatch plus cosmetic dependency OAuth page branding
Rationale
Static source inspection found risky primitives, but they are aligned with a feature-rich AI agent CLI and its local gateway/channel integrations. The install hook is undesirable because it modifies a dependency at install time, but the inspected code is cosmetic branding only and does not establish malicious behavior.
Evidence
package.jsonbrigade.mjsscripts/brand-oauth-page.mjsscripts/run-brigade.mjsscripts/install-convex.mjsscripts/convex-dev.mjsscripts/convex-push.mjsdist/entry.jsdist/security/injection-patterns.jsdist/agents/org/pride-image.jsscripts/brand-oauth-page.mjs writes resolved @earendil-works/pi-ai utils/oauth/oauth-page.jsscripts/convex-dev.mjs writes .convex-data/* and .env.local when user runs convex devscripts/convex-push.mjs removes stray convex/*.js and convex/*.js.map when user runs convex push
Network endpoints6
github.com/get-convex/convex-backend/releases/download/127.0.0.1:3210127.0.0.1:6791openrouter.ai/api/v1/modelsdiscord.com/api/v10slack.com/api/auth.test

Decision evidence

public snapshot
AI called this Clean at 78.0% confidence as Benign with medium false-positive risk.
Evidence for block
  • package.json defines postinstall: node scripts/brand-oauth-page.mjs
  • scripts/brand-oauth-page.mjs writes a dependency OAuth callback page resolved via @earendil-works/pi-ai/oauth
  • scripts/install-convex.mjs can download Convex binaries from github.com when user runs convex install/dev
Evidence against
  • postinstall script only embeds shipped logo/favicon, changes title/style, catches errors, and has no network or secret reads
  • brigade.mjs only checks Node version, enables compile cache, filters warnings, then imports dist/entry.js
  • dist/entry.js dispatches CLI help/version/main; no install-time payload
  • dist/security/injection-patterns.js is a defensive scanner; invisible Unicode appears in regex ranges/comments, not hidden logic
  • runtime network endpoints are package-aligned: local Convex, Slack/Discord/Telegram/BlueBubbles, OpenRouter/Ollama integrations
  • child_process uses are user-invoked CLI/dev flows, not automatic credential harvesting or exfiltration
Behavioral surface
Source
ChildProcessCryptoDynamicRequireEnvironmentVarsEvalFilesystemNetworkShellWebSocket
Supply chain
HighEntropyStringsMinifiedObfuscatedTelemetryUrlStrings
ManifestNo manifest risk signals triggered.
scanned 671 file(s), 7.30 MB of source, external domains: 127.0.0.1, 192.168.1.5, accounts.google.com, aistudio.google.com, api-dashboard.search.brave.com, api.anthropic.com, api.cerebras.ai, api.deepgram.com, api.deepseek.com, api.dev.runwayml.com, api.duckduckgo.com, api.elevenlabs.io, api.exa.ai, api.firecrawl.dev, api.github.com, api.groq.com, api.minimax.io, api.mistral.ai, api.moonshot.ai, api.openai.com, api.perplexity.ai, api.sarvam.ai, api.search.brave.com, api.slack.com, api.tavily.com, api.telegram.org, api.together.xyz, api.x.ai, api.z.ai, app.tavily.com, ark.ap-southeast.bytepluses.com, bailian.console.alibabacloud.com, brave.com, brigade.spinabot.com, chatgpt.com, claude.ai, cloud.cerebras.ai, console.anthropic.com, console.groq.com, console.mistral.ai, console.x.ai, core.telegram.org, dashscope-intl.aliyuncs.com, discord.com, docs.exa.ai, docs.firecrawl.dev, docs.github.com, docs.ollama.com, docs.perplexity.ai, docs.searxng.org
Oversized source lightweight scan
dist/ui/brand-frames-cli.js2.36 MB file, sampled 256 KB
Minified

Source & flagged code

21 flagged · loading source
package.jsonView file
scripts.postinstall = node scripts/brand-oauth-page.mjs
High
Install Time Lifecycle Scripts

Package defines install-time lifecycle scripts.

package.jsonView on unpkg
dist/ui/onboarding.jsView file
14*/ L15: import { spawn } from "node:child_process"; L16: import { getModels } from "@earendil-works/pi-ai";
High
Child Process

Package source references child process execution.

dist/ui/onboarding.jsView on unpkg · L14
dist/core/daemon/systemd.jsView file
21.join("\n"); L22: const execArgs = [ctx.nodePath, ctx.brigadeBin, "gateway", "run"] L23: .map((s) => (s.includes(" ") ? `"${s.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"` : s))
High
Shell

Package source references shell execution.

dist/core/daemon/systemd.jsView on unpkg · L21
8*/ L9: import { spawn } from "node:child_process"; L10: import { existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync } from "node:fs"; ... L14: function unitPath() { L15: return path.join(os.homedir(), ".config", "systemd", "user", SERVICE_UNIT_NAME); L16: } ... L36: "RestartSec=2", L37: `StandardOutput=append:${ctx.stdoutPath}`, L38: `StandardError=append:${ctx.stderrPath}`, ... L74: if (r.code !== 0) { L75: return { ok: false, message: `systemctl enable failed: ${r.stderr.trim()}`, unitPath: file }; L76: }
Medium
Install Persistence

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

dist/core/daemon/systemd.jsView on unpkg · L8
dist/agents/org/pride-image.jsView file
90// consistent with how Brigade lazy-loads other heavy modules.) L91: const importer = new Function("s", "return import(s)"); L92: const mod = (await importer("playwright-core"));
Low
Eval

Package source references a known benign dynamic code generation pattern.

dist/agents/org/pride-image.jsView on unpkg · L90
brigade.mjsView file
54try { L55: const mod = await import("node:module"); L56: if (typeof mod.enableCompileCache === "function" && !process.env.NODE_DISABLE_COMPILE_CACHE) {
Medium
Dynamic Require

Package source references dynamic require/import behavior.

brigade.mjsView on unpkg · L54
dist/agents/tool-loop-detector.jsView file
1/** L2: * Tool-loop detector — catches the model when it's stuck calling the same
Low
Weak Crypto

Package source references weak cryptographic algorithms.

dist/agents/tool-loop-detector.jsView on unpkg · L1
scripts/convex-dev.mjsView file
16L17: import { spawn } from "node:child_process"; L18: import { mkdirSync, existsSync, writeFileSync, readFileSync, unlinkSync } from "node:fs"; L19: import { randomBytes } from "node:crypto"; L20: import { createServer } from "node:http"; L21: import { readFile, stat } from "node:fs/promises"; ... L30: // or `npm run convex:dev` from a checkout (→ <root>/.convex-data, the default). L31: const DATA_DIR = process.env.BRIGADE_CONVEX_DATA_DIR?.trim() || join(ROOT, ".convex-data"); L32: const DASHBOARD_DIR = join(BIN_DIR, "dashboard");
High
Same File Env Network Execution

A single source file combines environment access, network access, and code or shell execution; review context before blocking.

scripts/convex-dev.mjsView on unpkg · L16
dist/infra/net/fetch-guard.jsView file
4* Why this exists: Brigade runs LLM-controllable URLs through `fetch`. L5: * Without a guard, a model can be tricked into hitting `http://169.254.169.254/` L6: * (cloud metadata) or `http://localhost:1234/` (developer service) and ... L20: import { isIP, isIPv4, isIPv6 } from "node:net"; L21: import { promises as dnsPromises } from "node:dns"; L22: import { DEFAULT_TIMEOUT_SECONDS } from "../../agents/tools/web-shared.js"; ... L28: * Cloud-metadata + forbidden-literal hosts that stay blocked EVEN WHEN L29: * `allowPrivateNetwork` is set — these are never a legitimate LAN target and are L30: * the highest-value SSRF destinations. ... L364: headers: currentHeaders, L365: body: currentBody ?? undefined, L366: redirect: "manual",
High
Cloud Metadata Access

Source reaches cloud instance metadata or link-local credential endpoints.

dist/infra/net/fetch-guard.jsView on unpkg · L4
dist/security/injection-patterns.jsView file
58contains invisible/control Unicode U+200B (zero width space) const INVISIBLE_CODEPOINTS = /[<U+200B>-<U+200D><U+2060>⁢-⁤<U+FEFF><U+202A>-<U+202E><U+2066>-<U+2069>]/;
Critical
Trojan Source Unicode

Source contains bidi control or invisible Unicode characters associated with Trojan Source attacks.

dist/security/injection-patterns.jsView on unpkg · L58
scripts/convex-push.mjsView file
53console.log(`▌ Pushing convex/ functions → ${url}`); L54: const res = spawnSync("npx", ["convex", "deploy", "--yes"], { L55: cwd: ROOT,
High
Runtime Package Install

Package source invokes a package manager install command at runtime.

scripts/convex-push.mjsView on unpkg · L53
skills/video-frames/scripts/frame.shView file
path = skills/video-frames/scripts/frame.sh kind = build_helper sizeBytes = 1347 magicHex = [redacted]
Medium
Ships Build Helper

Package ships non-JavaScript build or shell helper files.

skills/video-frames/scripts/frame.shView on unpkg
scripts/assets/brigade-favicon.icoView file
path = scripts/assets/brigade-favicon.ico kind = high_entropy_blob sizeBytes = 19371 magicHex = [redacted]
High
Ships High Entropy Blob

Package ships high-entropy non-source blobs.

scripts/assets/brigade-favicon.icoView on unpkg
dist/ui/brand-frames-cli.jsView file
path = dist/ui/brand-frames-cli.js kind = oversized_source_file sizeBytes = 2475115 magicHex = [redacted]
High
Oversized Source File

Package contains source files above the static scanner size ceiling.

dist/ui/brand-frames-cli.jsView on unpkg
path = dist/ui/brand-frames-cli.js kind = oversized_cli_entrypoint sizeBytes = 2475115 magicHex = [redacted]
Medium
Oversized Cli Entrypoint

Package contains an oversized executable-looking CLI entrypoint.

dist/ui/brand-frames-cli.jsView on unpkg
dist/agents/channels/bluebubbles/account-config.d.tsView file
28patternName = generic_password severity = medium line = 28 matchedText = * ch...}" }
Medium
Secret Pattern

Hardcoded password in dist/agents/channels/bluebubbles/account-config.d.ts

dist/agents/channels/bluebubbles/account-config.d.tsView on unpkg · L28
34patternName = generic_password severity = medium line = 34 matchedText = * ..." },
Medium
Secret Pattern

Hardcoded password in dist/agents/channels/bluebubbles/account-config.d.ts

dist/agents/channels/bluebubbles/account-config.d.tsView on unpkg · L34
35patternName = generic_password severity = medium line = 35 matchedText = * ..." },
Medium
Secret Pattern

Hardcoded password in dist/agents/channels/bluebubbles/account-config.d.ts

dist/agents/channels/bluebubbles/account-config.d.tsView on unpkg · L35
dist/agents/channels/bluebubbles/account-config.jsView file
28patternName = generic_password severity = medium line = 28 matchedText = * ch...}" }
Medium
Secret Pattern

Hardcoded password in dist/agents/channels/bluebubbles/account-config.js

dist/agents/channels/bluebubbles/account-config.jsView on unpkg · L28
34patternName = generic_password severity = medium line = 34 matchedText = * ..." },
Medium
Secret Pattern

Hardcoded password in dist/agents/channels/bluebubbles/account-config.js

dist/agents/channels/bluebubbles/account-config.jsView on unpkg · L34
35patternName = generic_password severity = medium line = 35 matchedText = * ..." },
Medium
Secret Pattern

Hardcoded password in dist/agents/channels/bluebubbles/account-config.js

dist/agents/channels/bluebubbles/account-config.jsView on unpkg · L35

Findings

1 Critical8 High13 Medium8 Low
CriticalTrojan Source Unicodedist/security/injection-patterns.js
HighInstall Time Lifecycle Scriptspackage.json
HighChild Processdist/ui/onboarding.js
HighShelldist/core/daemon/systemd.js
HighSame File Env Network Executionscripts/convex-dev.mjs
HighCloud Metadata Accessdist/infra/net/fetch-guard.js
HighRuntime Package Installscripts/convex-push.mjs
HighShips High Entropy Blobscripts/assets/brigade-favicon.ico
HighOversized Source Filedist/ui/brand-frames-cli.js
MediumDynamic Requirebrigade.mjs
MediumNetwork
MediumEnvironment Vars
MediumInstall Persistencedist/core/daemon/systemd.js
MediumShips Build Helperskills/video-frames/scripts/frame.sh
MediumOversized Cli Entrypointdist/ui/brand-frames-cli.js
MediumStructural Risk Force Deep Review
MediumSecret Patterndist/agents/channels/bluebubbles/account-config.d.ts
MediumSecret Patterndist/agents/channels/bluebubbles/account-config.d.ts
MediumSecret Patterndist/agents/channels/bluebubbles/account-config.d.ts
MediumSecret Patterndist/agents/channels/bluebubbles/account-config.js
MediumSecret Patterndist/agents/channels/bluebubbles/account-config.js
MediumSecret Patterndist/agents/channels/bluebubbles/account-config.js
LowScripts Present
LowEvaldist/agents/org/pride-image.js
LowWeak Cryptodist/agents/tool-loop-detector.js
LowFilesystem
LowObfuscated
LowHigh Entropy Strings
LowTelemetry
LowUrl Strings