Agent skill
secrets-tools
Publish gate secrets scanning. Use for: safe_to_publish, scan for secrets, redact in-place. Determines publish gate status. Scan files for secrets (locations only - NEVER prints secret content). GitHub tokens, AWS keys, private keys, bearer tokens. Use ONLY in secrets-sanitizer. Invoke via bash .claude/scripts/demoswarm.sh secrets scan|redact.
Install this agent skill to your Project
npx add-skill https://github.com/majiayu000/claude-skill-registry/tree/main/skills/development/secrets-tools
SKILL.md
Secrets Tools Skill
Secrets scanning and redaction for publish gates. High-risk surface with strict output contract.
Invocation
Always invoke via the shim:
bash .claude/scripts/demoswarm.sh secrets <command> [options]
Do not set PATH or call helpers directly. The shim handles resolution.
CRITICAL: Never Print Secret Content
This skill has a strict output contract:
- NEVER print matched secret values to stdout, stderr, or any file
- NEVER store raw secret values in JSON or any artifact
- Only output: file path, line number, secret type, redacted snippet (first/last 4 chars)
- Redacted format:
<prefix>...<suffix>(e.g.,ghp_...abcd)
Violations of this contract are security incidents.
Operating Invariants
Repo root only
- Assume working directory is repo root.
- All paths are repo-root-relative.
Scan scope
- Only scan the publish surface (current flow directory + staged files)
- Never scan the entire repository
No git / no GitHub
This skill does not run git or gh. File lists are passed as arguments.
Allowed Users
Primary:
secrets-sanitizer(the publish gate agent)
Secondary (read-only scan):
repo-operator(for hygiene checks)
Not allowed:
- Cleanup agents (they read receipts, not scan for secrets)
- Author agents
- Critic agents
Command Reference
| Command | Purpose |
|---|---|
secrets scan |
Scan files for secrets (locations only) |
secrets redact |
Redact specific secret type in file |
Quick Examples
Scan for secrets
# Scan a file or directory
bash .claude/scripts/demoswarm.sh secrets scan \
--path ".runs/feat-auth/signal" \
--output ".runs/feat-auth/signal/secrets_scan.json"
# stdout: CLEAN | SECRETS_FOUND | SCAN_PATH_MISSING | PATTERN_ERROR
# JSON findings written to --output file
Output JSON format:
{
"status": "SECRETS_FOUND",
"findings": [
{
"file": ".runs/feat-auth/signal/github_research.md",
"type": "github-token",
"lines": "42,87"
}
],
"skipped_count": 0
}
The skipped_count field indicates how many files/directories were skipped due to I/O errors (permission denied, etc.).
Scan with verbose output
# Scan with verbose mode to see skipped paths
bash .claude/scripts/demoswarm.sh secrets scan \
--path ".runs/feat-auth/signal" \
--output ".runs/feat-auth/signal/secrets_scan.json" \
--verbose
# stderr: Warning: skipped /path/to/file: failed to read file: Permission denied
# stdout: CLEAN
When --verbose (or -v) is enabled, skipped paths and reasons are logged to stderr.
Scan with custom patterns
# Scan using additional patterns from a config file
bash .claude/scripts/demoswarm.sh secrets scan \
--path ".runs/feat-auth/signal" \
--output ".runs/feat-auth/signal/secrets_scan.json" \
--patterns-file "secret-patterns.json"
Scan a single file
bash .claude/scripts/demoswarm.sh secrets scan \
--path ".runs/feat-auth/signal/github_research.md" \
--output ".runs/feat-auth/signal/secrets_scan.json"
# stdout: CLEAN (if no secrets found)
Redact a specific type
# Redact GitHub tokens in a file
bash .claude/scripts/demoswarm.sh secrets redact \
--file ".runs/feat-auth/signal/github_research.md" \
--type "github-token"
# stdout: ok | FILE_NOT_FOUND | null
# File is modified in-place
Redact a custom type
# Redact a custom secret type defined in patterns file
bash .claude/scripts/demoswarm.sh secrets redact \
--file ".runs/feat-auth/signal/config.md" \
--type "custom-api-key" \
--patterns-file "secret-patterns.json"
Custom Patterns File
You can extend the built-in patterns by providing a JSON or YAML configuration file.
JSON Format
{
"patterns": [
{
"pattern": "xoxb-[0-9]{10,13}-[0-9]{10,13}-[a-zA-Z0-9]{24}",
"type": "slack-bot-token"
},
{
"pattern": "sq0atp-[0-9A-Za-z\\-_]{22}",
"type": "square-access-token"
}
]
}
YAML Format
patterns:
- pattern: "xoxb-[0-9]{10,13}-[0-9]{10,13}-[a-zA-Z0-9]{24}"
type: slack-bot-token
- pattern: "sq0atp-[0-9A-Za-z\\-_]{22}"
type: square-access-token
Pattern Merging
When --patterns-file is provided:
- Built-in patterns are applied first
- Custom patterns from the config file are applied second
- If a file matches multiple patterns, all matches are reported
Regex Validation
All custom patterns are validated at load time. If any pattern has invalid regex syntax, the scan will fail with PATTERN_ERROR status and an error message in the output JSON.
Built-in Secret Types
| Type | Pattern | Replacement |
|---|---|---|
github-token |
gh[pousr]_[A-Za-z0-9_]{36,} |
[REDACTED:github-token] |
aws-access-key |
AKIA[0-9A-Z]{16} |
[REDACTED:aws-access-key] |
stripe-key |
sk_live_[0-9a-zA-Z]{24,} |
[REDACTED:stripe-key] |
private-key |
-----BEGIN .*PRIVATE KEY----- |
[REDACTED:private-key] |
jwt-token |
eyJ[A-Za-z0-9_-]*\.[A-Za-z0-9_-]*\.[A-Za-z0-9_-]* |
[REDACTED:jwt-token] |
Contract Rules
- stdout scan: Status string (
CLEAN|SECRETS_FOUND|SCAN_PATH_MISSING|PATTERN_ERROR) - stdout redact: Status string (
ok|FILE_NOT_FOUND|null) - JSON output: Written to
--outputfile path, not stdout - exit code:
0always (errors expressed in output, not exit code). In CI or human scripts, fail-fast via exit code is appropriate; agents should recordPATTERN_ERRORin the JSON and hand off to the orchestrator rather than exiting abruptly. - No secrets in output: Any output containing secret values is a bug
Error Handling
Missing scan path
# stdout: SCAN_PATH_MISSING
{
"status": "SCAN_PATH_MISSING",
"findings": [],
"skipped_count": 0
}
Invalid patterns file
# stdout: PATTERN_ERROR
{
"status": "PATTERN_ERROR",
"error": "Invalid regex in patterns file at index 0: pattern='[invalid', type='bad-pattern'",
"findings": [],
"skipped_count": 0
}
File not found (redact)
# stdout: FILE_NOT_FOUND
Read error (redact)
# stdout: null
Unknown secret type (redact)
# stdout: null
# stderr: Unknown secret type: <type>
For Agent Authors
In secrets-sanitizer:
- Use
secrets-tools--bash .claude/scripts/demoswarm.sh secrets ... - Never grep for secrets manually -- the patterns are standardized here
- Check stdout status --
CLEAN,SECRETS_FOUND,SCAN_PATH_MISSING, orPATTERN_ERROR - Read JSON from file -- findings are in the
--outputfile, not stdout - Redact in-place -- use
secrets redactfor allowlist artifacts
Example pattern:
# Scan the publish surface
SCAN_OUTPUT=".runs/${RUN_ID}/${FLOW}/secrets_scan.json"
STATUS=$(bash .claude/scripts/demoswarm.sh secrets scan \
--path ".runs/${RUN_ID}/${FLOW}" \
--output "$SCAN_OUTPUT")
if [[ "$STATUS" == "SECRETS_FOUND" ]]; then
# Read findings from JSON file
FINDINGS=$(cat "$SCAN_OUTPUT" | jq -r '.findings[] | "\(.file) \(.type)"')
# Redact each finding type
bash .claude/scripts/demoswarm.sh secrets redact \
--file ".runs/${RUN_ID}/${FLOW}/github_research.md" \
--type "github-token"
fi
Using Custom Patterns
# Scan with organization-specific patterns
SCAN_OUTPUT=".runs/${RUN_ID}/${FLOW}/secrets_scan.json"
STATUS=$(bash .claude/scripts/demoswarm.sh secrets scan \
--path ".runs/${RUN_ID}/${FLOW}" \
--output "$SCAN_OUTPUT" \
--patterns-file ".config/secret-patterns.yaml")
# Handle PATTERN_ERROR status
if [[ "$STATUS" == "PATTERN_ERROR" ]]; then
ERROR=$(cat "$SCAN_OUTPUT" | jq -r '.error')
echo "Pattern configuration error: $ERROR"
exit 1
fi
Installation
The Rust implementation is preferred:
cargo install --path tools/demoswarm-runs-tools --root .demoswarm
The shim will automatically use the installed binary.
Didn't find tool you were looking for?