ZaxbyHub/opencode-swarm/.opencode/skills/generated/guardrail-patterns/SKILL.md
guardrail-patterns
Guardrail patterns for opencode-swarm — pattern structure, bypass surfaces, regex anti-patterns, and test conventions for checkDestructiveCommand()
- Source repository stars
- 451
- Declared platforms
- 0
- Static risk flags
- 1
- Last source update
- 2026-08-25
- Source checked
- 2026-08-25
Decision brief
What it does: where it fits
Source knowledge: 098926ef, 2c1e4689, 54c33fa4, 4f51d11a
Not for
- Anti-pattern 1: [^-] consuming path characters
- Anti-pattern 2: Negative lookahead too broad ((?!-\S))
Compatibility matrix
Platform support, with evidence labels
| Platform | Status | Evidence | What to check |
|---|---|---|---|
| Codex | Not declared | No explicit evidence | Portability before use |
| Claude Code | Not declared | No explicit evidence | Portability before use |
| Cursor | Not declared | No explicit evidence | Portability before use |
| Gemini CLI | Not declared | No explicit evidence | Portability before use |
Installation
Inspect first. Install second.
The source command is displayed only when detected. A safe inspection prompt is always available so your agent can explain every action before execution.
npx skills add https://github.com/ZaxbyHub/opencode-swarm --skill ".opencode/skills/generated/guardrail-patterns"Inspect the Agent Skill "guardrail-patterns" from https://github.com/ZaxbyHub/opencode-swarm/blob/97dc624b391c8e2e80ed42f4bfa37876554c24cb/.opencode/skills/generated/guardrail-patterns/SKILL.md at commit 97dc624b391c8e2e80ed42f4bfa37876554c24cb. List every install step, command, network request, credential, file read/write, external action, and rollback step. Explain whether it fits my task. Do not install or execute anything until I approve.
Workflow
What the source asks the agent to do
- 01
Step 1 — Determine the pattern placement
Inside checkDestructiveCommand(), the per-segment for loop evaluates each segment against sections 1–22. A new section should be added after the last existing section and before the closing } of the for loop (currently after Section 22 at approximately line 1733).
Inside checkDestructiveCommand(), the per-segment for loop evaluates each segment against sections 1–22. A new section should be added after the last existing section and before the closing } of the for loop (currently… - 02
Step 2 — Choose the regex pattern structure
There are three patterns used in the codebase:
There are three patterns used in the codebase:Pattern A — Simple inline regex (single condition):Pattern B — Multi-condition (flag check + path check): - 03
Step 3 — Handle all platform variants
POSIX, Windows cmd.exe, and PowerShell often use different commands for the same operation. All three must be covered:
POSIX, Windows cmd.exe, and PowerShell often use different commands for the same operation. All three must be covered: - 04
Step 4 — Handle the .swarm path separator
Always use \x5c (backslash) for cross-platform path matching — \ alone is the regex escape character.
Always use \x5c (backslash) for cross-platform path matching — \ alone is the regex escape character. - 05
Step 5 — Handle backslash-prefixed command evasion
Commands prefixed with \ (e.g., \mv) bypass simple ^command\s anchors. Always add \\?:
Commands prefixed with \ (e.g., \mv) bypass simple ^command\s anchors. Always add \\?:
Permission review
Static risk signals and limitations
Runs scripts
The documentation asks the agent to run terminal commands or scripts.
`dcStripOneWrapper()` (line ~664) — detects and strips individual shell wrappers: `bash`, `sh`, `zsh`, `dash`, `fish`, `pwsh`, `powershell`, `cmd` (with `-c`/`-Command`), `sudo`, `nohup`, `time`, `nice`, `env VAR=val`, `call` (batch), `InvoEvidence record
Why each signal appears
| Signal | Value | Evidence type | Meaning |
|---|---|---|---|
| Quality score | 90/100 | Computed | Documentation, specificity, maintenance, and trust rules |
| Repository stars | 451 | Source | Repository attention, not individual Skill quality |
| Compatibility | 0 platforms | Source | Declared in the catalog source record |
| Usage guide | automated source guide | Editorial | Generated or reviewed according to the visible evidence level |
Pinned source
Provenance and original SKILL.md
- Repository
- ZaxbyHub/opencode-swarm
- Skill path
- .opencode/skills/generated/guardrail-patterns/SKILL.md
- Commit
- 97dc624b391c8e2e80ed42f4bfa37876554c24cb
- License
- MIT
- Collected
- 2026-08-25
- Default branch
- main
View the original SKILL.md
Skill: Guardrail Patterns for opencode-swarm
Source knowledge: 098926ef, 2c1e4689, 54c33fa4, 4f51d11a
Load this skill before modifying src/hooks/guardrails.ts — adding, removing, or changing guardrail blocks in checkDestructiveCommand(). It documents the pattern structure, known bypass surfaces, regex anti-patterns, and test conventions used across 41 guardrail test files and the ~3900-line guardrails.ts file.
When to load this skill
Load before any change to:
src/hooks/guardrails.ts— especiallycheckDestructiveCommand()ordcNormalizeCommand()tests/unit/hooks/guardrails*.test.ts— any guardrail test file- Adding a new section (currently Sections 1–22) to
checkDestructiveCommand() - Adding regex patterns for shell command blocking
Architecture overview
checkDestructiveCommand() — the shell command guard
Located at src/hooks/guardrails.ts (line 1304). This is the only function that blocks destructive shell commands. It is invoked by the toolBefore hook in guardrails.ts before every bash or shell tool call.
Pipeline (in order):
dcNormalizeCommand()(line ~627) — NFKC normalization + evasion collapse: collapses""(doubled double-quotes) and''(doubled single-quotes). Single-quote splice likem'v'remains OPEN.dcStripOneWrapper()(line ~664) — detects and strips individual shell wrappers:bash,sh,zsh,dash,fish,pwsh,powershell,cmd(with-c/-Command),sudo,nohup,time,nice,env VAR=val,call(batch),Invoke-Command -ScriptBlock,& { }script blocks,wsl,iexdcUnwrapWrappers()(line ~737) — loopsdcStripOneWrapperuntil no more wrappers remain (max depth 10)dcSplitSegments()(line ~753) — splits compound commands on&&,;,|, newlines- Per-segment loop — each segment evaluated against 22+ guardrail sections
dcValidateTargets()— runtimelstat-ancestor walk on destructive targets
Key normalization functions
| Function | Line | What it normalizes |
|---|---|---|
dcNormalizeCommand | ~627 | NFKC, caret escapes (^), backtick escapes, collapsed "" and '' |
dcStripOneWrapper | ~664 | Detects/strips a single shell wrapper (bash/sh/zsh/pwsh/cmd/powershell/wsl etc) |
dcUnwrapWrappers | ~737 | Loops dcStripOneWrapper until no more wrappers (max depth 10) |
dcSplitSegments | ~753 | Splits on &&, ;, ` |
Known wrapper unwrapping limitation: sh -c and bash -c with single-quoted inner commands (sh -c 'mv ...') are NOT unwrapped because dcStripOneWrapper uses "? (optional double-quote). Only double-quoted inner commands are properly stripped.
Adding a new guardrail block
Step 1 — Determine the pattern placement
Inside checkDestructiveCommand(), the per-segment for loop evaluates each segment against sections 1–22. A new section should be added after the last existing section and before the closing } of the for loop (currently after Section 22 at approximately line 1733).
Step 2 — Choose the regex pattern structure
There are three patterns used in the codebase:
Pattern A — Simple inline regex (single condition):
// Good for: single-command blocking with no complex extraction
if (/^blockedcommand\b.*\.swarm[\x5c/\s]?/i.test(seg)) {
throw new Error(`BLOCKED: "blockedcommand" targeting .swarm/ detected — ...`);
}
Pattern B — Multi-condition (flag check + path check):
// Good for: archive tools with flags + .swarm/ path (prevents argument-order bypass)
if (
/^toolname\b.*--dangerous-flag\b/i.test(seg) &&
/\.swarm(?:[\x5c/\s]|$)/i.test(seg)
) {
This is recommended because it handles both tool --flag .swarm/path and tool .swarm/path --flag argument orders.
Pattern C — Argument extraction + stripped check:
// Good for: commands where you need argument isolation (e.g., `mv` with arg capture)
if (/^\\?command\s/i.test(seg)) {
const match = seg.match(/^\\?command\s+(.+)$/i);
if (match) {
const argsStr = match[1].replace(/["']/g, '');
if (/\.swarm(?:[\x5c/\s]|$)/.test(argsStr)) {
throw new Error(`BLOCKED: ...`);
}
}
}
Step 3 — Handle all platform variants
POSIX, Windows cmd.exe, and PowerShell often use different commands for the same operation. All three must be covered:
// POSIX section
if (/^\\?posix-cmd\s/i.test(seg) && /\.swarm/i.test(strippedArgs)) { ... }
// Windows cmd section (case-insensitive, optional .exe)
if (/^\\?(?:cmd-cmd|cmd-cmd-alias)(?:\.exe)?\s/i.test(seg) && /\.swarm/i.test(argsStr)) { ... }
// PowerShell section (case-insensitive, all aliases)
if (/^\\?(?:PowerShell-Cmdlet|alias1|alias2)\b.*\.swarm/i.test(seg)) { ... }
Step 4 — Handle the .swarm path separator
Always use \x5c (backslash) for cross-platform path matching — \ alone is the regex escape character.
// Correct: matches both / and \
/\.swarm[\x5c/]/
// More complete: also matches .swarm followed by whitespace or end-of-string
// (catches whole-directory targeting like `mv .swarm /tmp/`)
/\.swarm(?:[\x5c/\s]|$)/
Step 5 — Handle backslash-prefixed command evasion
Commands prefixed with \ (e.g., \mv) bypass simple ^command\s anchors. Always add \\?:
// Correct: catches both mv and \mv
if (/^\\?mv\s/i.test(seg)) { ... }
// Correct for rm (uses \b instead of \s)
if (/^\\?rm\b/i.test(seg)) { ... }
Known bypass surfaces (must document in adversarial tests)
These are documented bypass vectors that the current regex-based approach cannot fully close. Every new guardrail section should include adversarial tests for these patterns:
| Evasion | Example | Status | Mitigation |
|---|---|---|---|
| Backslash prefix | \mv .swarm/file | CLOSED | Add ^\\? to command anchor |
| Quote splicing | m'v' .swarm/file | OPEN | Requires NFKC normalization change |
| Quoted command name | "mv" .swarm/file | OPEN | Requires NFKC normalization change |
| Shell wrapper (double-quoted) | sh -c "mv .swarm/file" | CLOSED | dcUnwrapWrappers handles " |
| Shell wrapper (single-quoted) | sh -c 'mv .swarm/file' | OPEN | dcUnwrapWrappers regex uses "? |
| Relative path prefix | mv ./swarm/file | OPEN | Requires path normalization |
| Env var expansion | mv $SWARM_DIR/file | OPEN | Requires variable resolution |
| Unicode fullwidth | mv .swarm/file | OPEN | Requires NFKC normalization |
Regex anti-patterns (from prior bugs)
Anti-pattern 1: [^-] consuming path characters
// WRONG — [^-] consumes the first character of the path
if (/^rm\s+(?!\s*-)(?!-)[^-].*\.swarm/i.test(seg)) {
// "rm .swarm/file" → [^-] consumes '.' → "swarm/file" doesn't match "\.swarm"
}
// CORRECT — use negative lookahead for flag exclusion
if (
/^rm\b/i.test(seg) &&
!/^rm\s+(?:-[a-zA-Z]*[rR][a-zA-Z]*|--recursive)\b/i.test(seg) &&
/\.swarm(?:[\x5c/\s]|$)/i.test(seg)
) {
// "rm .swarm/file" → BLOCKED ✓
// "rm -rf .swarm/" → Section 3 handles ✓
// "rm -v .swarm/file" → BLOCKED ✓
}
Anti-pattern 2: Negative lookahead too broad ((?!-\S))
// WRONG — (?!-\S) excludes ALL flag-prefixed rm commands,
// but Section 3 only catches recursive/force flags
if (/^rm\s+(?!-\S).*\.swarm/i.test(seg)) {
// "rm -v .swarm/file" → NOT blocked by S19 (excluded by lookahead)
// "rm -v .swarm/file" → NOT blocked by S3 (no -r/-f flags)
}
// CORRECT — use three-part condition
Anti-pattern 3: .exec() confused by SAST
// WRONG — SAST confuses RegExp.prototype.exec() with child_process.exec()
const match = /^command\s+(.+)$/i.exec(seg); // SAST false positive
// CORRECT — use String.prototype.match()
const match = seg.match(/^command\s+(.+)$/i); // No SAST false positive
Anti-pattern 4: Argument-order dependent patterns
// WRONG — .swarm/ must appear AFTER the flag in the command string
if (/^tool\b.*--flag\b.*\.swarm/i.test(seg)) {
// "tool --flag .swarm/" → BLOCKED ✓
// "tool .swarm/ --flag" → NOT BLOCKED ✗
}
// CORRECT — split flag check and path check
if (/^tool\b.*--flag\b/i.test(seg) && /\.swarm(?:[\x5c/\s]|$)/i.test(seg)) {
// Both argument orders BLOCKED ✓
}
Test conventions
Test file structure
// Positive tests: "command → BLOCKED"
test('mv .swarm/evidence/file.json /tmp/ → BLOCKED', async () => { ... });
// Negative tests: "command → ALLOWED (reason)"
test('ls .swarm/evidence/ → ALLOWED (read-only)', async () => { ... });
// Bypass when feature is disabled
test('mv .swarm/file /tmp/ → ALLOWED when block_destructive_commands=false', async () => { ... });
Test infrastructure pattern
import { mkdtempSync, realpathSync } from 'node:fs';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
import { createGuardrailsHooks } from '../../../src/hooks/guardrails';
import { resetSwarmState, startAgentSession } from '../../../src/state';
const TEST_DIR = realpathSync(mkdtempSync(join(tmpdir(), 'guardrail-pattern-')));
function defaultConfig(overrides?: Partial<GuardrailsConfig>): GuardrailsConfig {
return {
enabled: true,
max_tool_calls: 200,
max_duration_minutes: 30,
idle_timeout_minutes: 60,
max_repetitions: 10,
max_consecutive_errors: 5,
warning_threshold: 0.75,
profiles: undefined,
block_destructive_commands: true,
...overrides,
};
}
function makeBashInput(sessionID = 'test-session', command: string) {
// Note: command is accepted but passed to makeBashOutput, not makeBashInput
return { tool: 'bash', sessionID, callID: 'call-1' };
}
function makeBashOutput(command: string) {
return { args: { command } };
}
Required test categories
Every new guardrail section MUST have tests for:
- Positive — command targeting
.swarm/is blocked - Negative — same command with non-
.swarm/path is allowed - Read-only — read-only commands (ls, cat, find) are not blocked
- Config bypass — verified unblocked when
block_destructive_commands: false - Platform variants — POSIX, Windows cmd, PowerShell forms where applicable
- Adversarial — documented bypass surfaces (one test per known evasion type)
Key testing rules
- Use
bun:testonly (no Jest/Vitest) - Use
rejects.toThrow(/BLOCKED/)for positive assertions - Use
resolves.toBeUndefined()for negative assertions - No hardcoded
/tmp— useos.tmpdir()+mkdtempSync - No hardcoded
C:\strings - Wrap
mkdtempSyncinrealpathSyncfor macOS compatibility
Section pattern reference (current guardrail sections 1–22)
| Section | Line | Commands blocked | Notes |
|---|---|---|---|---|
| 2 | ~1347 | Junction/symlink CREATION out-of-cwd | dcCheckJunctionCreation — creation of junctions/symlinks targeting outside cwd |
| 3 | ~1353 | rm -r[Ff]*, rm -f -r, etc | Recursive + force only ([rRfF]+ flag set) |
| 4 | ~1378 | rmdir /s, rd /s | Windows cmd, recursive |
| 5 | ~1400 | del /s | Windows cmd |
| 6–7 | ~1418 | Remove-Item -Recurse + pipeline form | PowerShell |
| 8 | ~1457 | Ransomware-grade | vssadmin, wbadmin, diskpart, bcdedit, sdelete, fsutil, takeown, cipher, format, robocopy /MIR |
| 9 | ~1510 | chmod -R 000, chattr +i, icacls /deny | Permission denial-of-service |
| 10 | ~1529 | dd with /dev/zero/null/urandom | Data wipe |
| 11 | ~1538 | Git destructive | push --force, reset --hard, reset --mixed, clean -fd, worktree remove --force |
| 12 | ~1567 | rsync --delete(-before/-after/-during/-delay) | Mirror/sync with delete |
| 13 | ~1576 | kubectl delete, docker system prune | Cluster/container |
| 14 | ~1590 | DROP TABLE/DATABASE/SCHEMA, TRUNCATE TABLE | SQL DDL |
| 15 | ~1604 | mkfs | Disk format |
| 16 | ~1615 | mv | POSIX — blocked on .swarm/ |
| 17 | ~1635 | move, ren | Windows cmd — blocked on .swarm\ |
| 18 | ~1652 | Move-Item, Rename-Item, aliases | PowerShell — blocked on .swarm/ |
| 19 | ~1667 | rm (non-recursive) | Blocked on .swarm/ (recursive → Section 3) |
| 20 | ~1682 | cp + rm chain | Secondary defense (rm guard is primary) |
| 21 | ~1697 | rsync --remove-source-files, tar --remove-files, zip -m, 7z -sdel | Archive tools with delete-source flags |
| 22 | ~1728 | git clean -fd, git worktree remove --force | Verified existing patterns cover .swarm/ |
Task checklist for adding a new guardrail block
- Pattern chosen (A/B/C) and placed in correct section order
- Command anchor includes
^\\?(backslash prefix) -
.swarmpath check uses(?:[\x5c/\s]|$)(whole-root + subpath) - Argument-order independent (split flag check from path check)
- Platform variants covered (POSIX + cmd + PowerShell)
-
.exec()→.match()to avoid SAST false positives - Positive test:
.swarm/path blocked - Negative test: non-
.swarm/path allowed - Read-only test: read commands not blocked
- Config bypass test:
block_destructive_commands: false - Adversarial tests: document known bypasses
-
bun run buildsucceeds -
bunx biome ci .clean - All guardrail test suites pass
Frequently asked questions
What to verify before installation and use
What does the guardrail-patterns source document cover?
Source knowledge: 098926ef, 2c1e4689, 54c33fa4, 4f51d11a
How do I install guardrail-patterns?
The source record exposes this install command: npx skills add https://github.com/ZaxbyHub/opencode-swarm --skill ".opencode/skills/generated/guardrail-patterns". Inspect the command and pinned source before running it.
Which permission-related actions were detected?
Static rules flagged exec-script in the source; the page lists the matching lines and excerpts.
Alternatives
Compare before choosing
coreyhaines31/marketingskills
ab-testing
When the user wants to plan, design, or implement an A/B test or experiment, or build a growth experimentation program. Also use when the user mentions "A/B test," "split test," "experiment," "test this change," "variant copy," "multivariate test," "hypothesis," "should I test this," "which version is better," "test two versions," "statistical significance," "how long should I run this test," "growth experiments," "experiment velocity," "experiment backlog," "ICE score," "experimentation program
garrytan/gbrain
bulk-ingestion
End-to-end discipline for turning any large data source (audio libraries, email takeouts, document corpora, chat exports, API dumps) into brain pages at scale. The lifecycle spine: SCHEMA → ACCESS → TRIAL → EVALUATE → IMPROVE → CODIFY → TEST → SKILLIFY → BULK → MONITOR. State is tracked in a durable JSON manifest (see MANIFEST-PATTERN.md) so any crash, session boundary, or subagent fan-out resumes from ground truth instead of memory.
alirezarezvani/claude-skills
app-store-optimization
App Store Optimization (ASO) toolkit for researching keywords, analyzing competitor rankings, generating metadata suggestions, and improving app visibility on Apple App Store and Google Play Store. Use when the user asks about ASO, app store rankings, app metadata, app titles and descriptions, app store listings, app visibility, or mobile app marketing on iOS or Android. Supports keyword research and scoring, competitor keyword analysis, metadata optimization, A/B test planning, launch checklist
dotnet/skills
migrate-vstest-to-mtp
Migrates .NET test projects from VSTest to Microsoft.Testing.Platform (MTP). Use when user asks to "migrate to MTP", "switch from VSTest", "enable Microsoft.Testing.Platform", "use MTP runner", set OutputType=Exe only for test projects in Directory.Build.props, or mentions EnableMSTestRunner, EnableNUnitRunner, or UseMicrosoftTestingPlatformRunner. USE FOR: MTP behavioral differences vs VSTest (exit code 8, zero tests discovered, --ignore-exit-code, TESTINGPLATFORM_EXITCODE_IGNORE); centralizing