# 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.

- Skill: `majiayu000/secrets-tools-2` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add majiayu000/secrets-tools-2`
- Raw SKILL.md: https://api.skillmd.com/api/skills/majiayu000/secrets-tools-2/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: DevOps & Infra
- Author: majiayu000 (https://skillmd.com/u/majiayu000)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/majiayu000/secrets-tools-2

---


# Secrets Tools Skill

Secrets scanning and redaction for publish gates. High-risk surface with strict output contract.

## Invocation

**Always invoke via the shim:**

```bash
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:

1. **NEVER print matched secret values** to stdout, stderr, or any file
2. **NEVER store raw secret values** in JSON or any artifact
3. **Only output**: file path, line number, secret type, redacted snippet (first/last 4 chars)
4. **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

```bash
# 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
# JSON findings written to --output file
```

Output JSON format:
```json
{
  "status": "SECRETS_FOUND",
  "findings": [
    {
      "file": ".runs/feat-auth/signal/github_research.md",
      "type": "github-token",
      "lines": "42,87"
    }
  ]
}
```

### Scan a single file

```bash
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

```bash
# 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
```

---

## 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

1. **stdout scan**: Status string (`CLEAN` | `SECRETS_FOUND` | `SCAN_PATH_MISSING`)
2. **stdout redact**: Status string (`ok` | `FILE_NOT_FOUND` | `null`)
3. **JSON output**: Written to `--output` file path, not stdout
4. **exit code**: `0` always (errors expressed in output, not exit code)
5. **No secrets in output**: Any output containing secret values is a bug

---

## Error Handling

### Missing scan path
```bash
# stdout: SCAN_PATH_MISSING
```
```json
{
  "status": "SCAN_PATH_MISSING",
  "findings": []
}
```

### File not found (redact)
```bash
# stdout: FILE_NOT_FOUND
```

### Read error (redact)
```bash
# stdout: null
```

---

## For Agent Authors

In `secrets-sanitizer`:

1. **Use `secrets-tools`** — `bash .claude/scripts/demoswarm.sh secrets ...`
2. **Never grep for secrets manually** — the patterns are standardized here
3. **Check stdout status** — `CLEAN`, `SECRETS_FOUND`, or `SCAN_PATH_MISSING`
4. **Read JSON from file** — findings are in the `--output` file, not stdout
5. **Redact in-place** — use `secrets redact` for allowlist artifacts

Example pattern:

```bash
# 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
```

---

## Installation

The Rust implementation is preferred:

```bash
cargo install --path tools/demoswarm-runs-tools --root .demoswarm
```

The shim will automatically use the installed binary.

