Back to skill

Security audit

Swarm Sprint

Security checks for vulnerabilities and agentic risk

Overview

This skill has a legitimate multi-agent coding workflow, but its cleanup script has under-scoped destructive behavior and command-execution risks from task metadata.

Review this skill before installing. It should only be used with task files and cleanup package files you fully trust, and cleanup should be run carefully because malformed metadata could delete local directories or execute unintended shell commands. Safer versions should avoid bash -c, validate task IDs and cleanup package paths, remove the rm -rf fallback, and keep logs in a clearly non-memory repo-local location.

Vulnerability Patterns
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
Findings (3)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/swarm.js:154
Finding

Arbitrary Command Execution Through Unsanitized Task and Cleanup Metadata

Content
View full analysis
r.taskId === wt.task.id); if (!result || result.status === 'MERGED' || result.status === 'REJECTED') { tryRun(`git branch -D "${wt.branchName}"`, repoPath); log(`✓ Deleted branch: ${wt.branchName}`); } ``` ### Technical Analysis The script builds command strings by interpolating values derived from task files and cleanup package files, then passes those strings to `bash -c`. The affected values include: - `task.id` - `wt.worktreePath` - `wt.branchName` These fields are not validated against a safe ch ...[truncated 1745 chars]
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/swarm.js:253
Finding

Arbitrary Recursive Directory Deletion Through Untrusted Cleanup Packages

Content
View full analysis
r.taskId === wt.task.id); if (!result || result.status === 'MERGED' || result.status === 'REJECTED') { tryRun(`git branch -D "${wt.branchName}"`, repoPath); log(`✓ Deleted branch: ${wt.branchName}`); } } // Prune stale worktree references tryRun('git worktree prune', repoPath); } ``` The paths are loaded directly from a caller-selected JSON file: ```javascript if (args.includes('--cleanup')) { const packagesFile = args[args.indexOf('--cleanup') + 1]; if (!packagesFile || !fs.existsSync(packagesFile)) die('--cleanup requires a valid swarm-packages.json path'); const loadedPackages = JSON.parse(fs.readFileSync(packagesFile, 'utf8')); const wts = loadedPackages.map(p => ({ task: p.task, branchName: p.branchName, worktreePath: p.worktreePath, created: fs.existsSync(p.worktreePath) })); cleanup(wts, repoPath, []); writeSprintLog(loadedPackages.map(p => p.task), [], repoPath); if (!dryRun) fs.unl ...[truncated 2270 chars]
Remediation
View remediation
-` namespace. 7. Present the final canonical deletion list to the coordinator and require confirmation before destructive cleanup. ]]>

T02 · Agent Memory Poisoning

Error
Location
scripts/swarm.js:284
Finding

Persistent Agent Memory Poisoning Through Unescaped Sprint Log Fields

Content
View full analysis
({ taskId: t.id, status: dryRun ? 'DRY_RUN' : 'PENDING' }))).map(r => ` - ${r.taskId}: ${r.status}${r.summary ? ' — ' + r.summary : ''}` ).join('\n')} `; if (!dryRun) { fs.mkdirSync(logDir, { recursive: true }); fs.appendFileSync(logFile, entry); } log(`Sprint log written to memory/swarm-log.md`); } ``` Cleanup passes task data loaded from the caller-selected package into the logging function: ```javascript const loadedPackages = JSON.parse(fs.readFileSync(packagesFile, 'utf8')); const wts = loadedPackages.map(p => ({ task: p.task, branchName: p.branchName, worktreePath: p.worktreePath, created: fs.existsSync(p.worktreePath) })); cleanup(wts, repoPath, []); writeSprintLog(loadedPackages.map(p => p.task), [], repoPath); ``` ### Technical Analysis The script creates and appends to a file explicitly placed in a sibling `memory` directory. Task IDs from an externally supplied cleanup package are inserted directly into Markdown without validation or escaping. A task ID can contain newline characters and arbitrary Markdown. This permits an attacker to create additional headings, list entries, or instruction-like content that appears to be trusted historical memory rather than untrusted task data. The persistence risk arises if the Agent environment ingests `memory/swarm-log.md` in later sessions. In that situation, ...[truncated 1489 chars]
Remediation
View remediation
({ taskId: result.taskId, status: result.status, summary: result.summary })) }; fs.appendFileSync(logFile, `${JSON.stringify(safeEntry)}\n`); ``` 3. Apply strict validation to task IDs, statuses, and summaries. Task IDs should use a small safe character set and fixed maximum length. 4. If Markdown output remains necessary, escape line breaks, control characters, heading markers, HTML, and other formatting syntax in all untrusted fields. 5. Clearly label all task-derived content as untrusted data and ensure any future Agent context loader treats the file as records, not instructions. 6. Apply file-size limits, record-count limits, and safe rotation to prevent unbounded persistent log growth. 7. Add tests proving that newline-containing and Markdown-containing fields cannot create new headings, instructions, or records. ]]>
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (3)

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The top-level documentation says 'Worktrees always cleaned up after,' implying automatic cleanup as part of the script's behavior. In practice, the main flow creates worktrees and exits after writing swarm-packages.json, while cleanup only occurs in a separate --cleanup invocation later in the file, so the comment overstates what this run actually does.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The cleanup routine performs destructive actions including forced git worktree removal, branch deletion, and fallback rm -rf without an interactive confirmation or a safer validation gate. In an agentic or automated environment, a malformed package file, incorrect repoPath, or operator mistake could cause unintended deletion of local data and branches, making recovery difficult.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
87% confidence
Finding

The script creates and appends to memory/swarm-log.md in the parent directory of the repository, which may affect user files outside the repo being operated on. While the script logs after writing, there is no upfront warning in usage/help text or a confirmation that files will be created outside the repository root.

Content

No source excerpt is available for this finding.

Static analysis

Detected: suspicious.dangerous_exec

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
scripts/swarm.js:38