registry  /  @spinabot/brigade  /  1.22.0

@spinabot/brigade@1.22.0

Brigade — your personal AI crew

AI Security Review

scanned 3d ago · by lpm-firewall-ai

No confirmed malicious attack surface was established. The notable behavior is an install-time cosmetic patch to a dependency's OAuth callback page, plus user-invoked CLI/network features expected for a personal AI agent tool.

Static reason
High-risk behavior combination matched malicious policy.
Trigger
npm install runs postinstall; CLI scripts run only when invoked by the user
Impact
No credential harvesting, covert exfiltration, persistence, or destructive install-time behavior found
Mechanism
package-aligned CLI dispatch and OAuth branding patch
Rationale
Source inspection found suspicious primitives, especially a postinstall file rewrite, but the implementation is transparent, package-aligned branding with local assets and no exfiltration or hidden payload. Runtime child processes, network access, and agent workspace writes are explicit CLI features rather than covert install/import-time behavior.
Evidence
package.jsonbrigade.mjsscripts/brand-oauth-page.mjsscripts/run-brigade.mjsscripts/convex-push.mjsdist/entry.jsdist/security/injection-patterns.jstemplates/workspace/AGENTS.mdnode_modules/@earendil-works/pi-ai/.../utils/oauth/oauth-page.js

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 rewrites a resolved @earendil-works/pi-ai OAuth callback JS file with local logo/favicon data URIs
  • scripts/convex-push.mjs can run npx convex deploy, but only via explicit npm script
Evidence against
  • brigade.mjs only checks Node version, filters warnings, and imports dist/entry.js
  • dist/entry.js dispatches CLI commands; no install/import-time exfiltration found
  • postinstall script performs no network calls and catches failures
  • dist/security/injection-patterns.js contains defensive regexes for prompt-injection detection; Trojan Source hint is from regex unicode ranges
  • Network endpoints found are aligned with OAuth, model providers, Convex, local services, or shipped skill docs
Behavioral surface
Source
ChildProcessCryptoDynamicRequireEnvironmentVarsEvalFilesystemNetworkShellWebSocket
Supply chain
HighEntropyStringsMinifiedObfuscatedTelemetryUrlStrings
ManifestNo manifest risk signals triggered.
scanned 675 file(s), 7.40 MB of source, external domains: 127.0.0.1, 192.168.1.5, accounts.google.com, aistudio.google.com, antigravity.google, 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, build.nvidia.com, chatgpt.com, claude.ai, cloud.cerebras.ai, cloudcode-pa.googleapis.com, 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
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
75console.log(`▌ Pushing convex/ functions → ${target}`); L76: const res = spawnSync("npx", ["convex", "deploy", "--yes"], { L77: cwd: ROOT,
High
Runtime Package Install

Package source invokes a package manager install command at runtime.

scripts/convex-push.mjsView on unpkg · L75
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