Back to skills
SkillHub ClubShip Full StackFull Stack

secret-detection

Git hook to detect secrets before commit.

Packaged view

This page reorganizes the original catalog entry around fit, installability, and workflow context first. The original raw source lives below.

Stars
3,084
Hot score
99
Updated
March 20, 2026
Overall rating
C4.0
Composite score
4.0
Best-practice grade
B78.7

Install command

npx @skill-hub/cli install openclaw-skills-secret-detection

Repository

openclaw/skills

Skill path: skills/derick001/secret-detection

Git hook to detect secrets before commit.

Open repository

Best for

Primary workflow: Ship Full Stack.

Technical facets: Full Stack.

Target audience: everyone.

License: Unknown.

Original source

Catalog source: SkillHub Club.

Repository owner: openclaw.

This is still a mirrored public skill entry. Review the repository before installing into production workflows.

What it helps with

  • Install secret-detection into Claude Code, Codex CLI, Gemini CLI, or OpenCode workflows
  • Review https://github.com/openclaw/skills before adding secret-detection to shared team environments
  • Use secret-detection for development workflows

Works across

Claude CodeCodex CLIGemini CLIOpenCode

Favorites: 0.

Sub-skills: 0.

Aggregator: No.

Original source / Raw SKILL.md

---
name: secret-detection
description: Git hook to detect secrets before commit.
version: 1.0.0
author: skill-factory
metadata:
  openclaw:
    requires:
      env: []
      bins: ["git", "python3"]
---

# Secret Detection

## What This Does

This skill provides a git pre‑commit hook that scans staged files for common secret patterns (API keys, passwords, tokens) and blocks the commit if any are found. It helps prevent accidental leakage of secrets to public repositories.

Inputs: Git staged files (automatically scanned by the hook) or manual file paths.  
Outputs: Detection report with line numbers; non‑zero exit code if secrets found.

## When To Use

Use this skill when:
- You work with repositories that may contain sensitive credentials
- You want to prevent accidental commits of secrets
- You need a lightweight, local secret scanner for git workflows
- You want to enforce security checks before pushing to remote

## Usage

### Installation
```bash
# Install the hook in your git repository
./scripts/main.py install
```

### Manual Scan
```bash
# Scan specific files
./scripts/main.py scan --file path/to/file

# Scan all staged files (like the hook does)
./scripts/main.py scan --staged
```

### Hook Behavior
- The hook runs automatically on `git commit`
- If secrets are detected, the commit is blocked
- The script prints the detected secrets with file names and line numbers
- Exit code 0 = no secrets found; exit code 1 = secrets found

## Examples

### Example 1: Installing the Hook
```bash
$ ./scripts/main.py install
✓ Pre-commit hook installed at .git/hooks/pre-commit
✓ Hook will scan for secrets on every commit
```

### Example 2: Secret Detection Blocking a Commit
```bash
$ git commit -m "Add config"
⚠️  Secret detected in config.yaml line 12: AWS_ACCESS_KEY_ID=AKIA...
⚠️  Secret detected in .env line 3: PASSWORD=secret123
✗ Commit blocked: 2 secrets found
```

### Example 3: Manual Scan
```bash
$ ./scripts/main.py scan --staged
Scanning 3 staged files...
✓ config.yaml: clean
✓ .env: clean  
✓ src/main.py: clean
✓ No secrets found
```

## Requirements

- Git (for hook installation)
- Python 3.6+ (for the scanner)
- No external API keys or services needed

## Limitations

- Only detects common secret patterns (AWS keys, GitHub tokens, passwords, etc.)
- May produce false positives (e.g., long random strings that aren't actually secrets)
- Does not scan binary files
- Requires manual installation per repository
- Does not replace comprehensive secret‑management solutions
- Prints first 20 characters of detected secrets to console for identification purposes


---

## Referenced Files

> The following files are referenced in this skill and included for context.

### scripts/main.py

```python
#!/usr/bin/env python3
"""
Git secret detection hook.
Scans files for common secret patterns (API keys, passwords, tokens).
"""

import argparse
import json
import os
import re
import subprocess
import sys
from pathlib import Path

# Common secret patterns (simplified examples)
SECRET_PATTERNS = [
    (r'(?i)aws_access_key_id\s*=\s*["\']?(AKIA[0-9A-Z]{16})', "AWS Access Key ID"),
    (r'(?i)aws_secret_access_key\s*=\s*["\']?([0-9a-zA-Z/+]{40})', "AWS Secret Access Key"),
    (r'(?i)password\s*=\s*["\']?([^\s"\']{8,})', "Password"),
    (r'(?i)secret\s*=\s*["\']?([^\s"\']{8,})', "Secret"),
    (r'(?i)token\s*=\s*["\']?([^\s"\']{8,})', "Token"),
    (r'(?i)api_key\s*=\s*["\']?([^\s"\']{8,})', "API Key"),
    (r'(?i)ghp_[0-9a-zA-Z]{36}', "GitHub Personal Access Token"),
    (r'(?i)github_pat_[0-9a-zA-Z]{40}', "GitHub Fine‑Grained Token"),
    (r'(?i)sk-[0-9a-zA-Z]{48}', "OpenAI API Key"),
    (r'(?i)Bearer\s+([0-9a-zA-Z._-]{20,})', "Bearer Token"),
]

def scan_file(filepath, patterns=SECRET_PATTERNS):
    """Scan a single file for secret patterns."""
    findings = []
    try:
        with open(filepath, 'r', encoding='utf-8', errors='ignore') as f:
            lines = f.readlines()
    except (IOError, UnicodeDecodeError):
        # Skip binary or unreadable files
        return findings
    
    for i, line in enumerate(lines, start=1):
        for pattern, label in patterns:
            matches = re.findall(pattern, line)
            for match in matches:
                if isinstance(match, tuple):
                    match = match[0]
                findings.append({
                    'file': str(filepath),
                    'line': i,
                    'content': line.strip(),
                    'secret': match,
                    'label': label,
                })
    return findings

def scan_files(filepaths, patterns=SECRET_PATTERNS):
    """Scan multiple files."""
    all_findings = []
    for fp in filepaths:
        findings = scan_file(fp, patterns)
        all_findings.extend(findings)
    return all_findings

def get_staged_files():
    """Get list of staged files from git."""
    try:
        result = subprocess.run(
            ['git', 'diff', '--cached', '--name-only', '--diff-filter=ACM'],
            capture_output=True,
            text=True,
            check=False
        )
        if result.returncode != 0:
            return []
        files = [f.strip() for f in result.stdout.split('\n') if f.strip()]
        # Resolve relative paths
        return [f for f in files if os.path.exists(f)]
    except (subprocess.SubprocessError, FileNotFoundError):
        return []

def install_hook():
    """Install pre‑commit hook in current git repository."""
    hook_path = Path('.git/hooks/pre-commit')
    if not hook_path.parent.exists():
        return {'status': 'error', 'message': 'Not a git repository (no .git directory)'}
    
    script_path = Path(__file__).resolve()
    hook_content = f'''#!/bin/bash
# Git pre‑commit hook for secret detection
python3 "{script_path}" hook-run
'''
    
    try:
        hook_path.write_text(hook_content)
        hook_path.chmod(0o755)
        return {'status': 'success', 'hook_path': str(hook_path)}
    except IOError as e:
        return {'status': 'error', 'message': f'Failed to write hook: {e}'}

def run_scan(args):
    """Run scan based on arguments."""
    if args.staged:
        files = get_staged_files()
        if not files:
            return {'status': 'success', 'findings': [], 'message': 'No staged files'}
    elif args.file:
        files = args.file
    else:
        return {'status': 'error', 'message': 'No files specified'}
    
    findings = scan_files(files)
    return {
        'status': 'success',
        'findings': findings,
        'file_count': len(files),
        'secret_count': len(findings),
    }

def main():
    parser = argparse.ArgumentParser(description='Git secret detection')
    subparsers = parser.add_subparsers(dest='command', required=True)
    
    # install
    install_parser = subparsers.add_parser('install', help='Install git pre‑commit hook')
    
    # scan
    scan_parser = subparsers.add_parser('scan', help='Scan files for secrets')
    scan_group = scan_parser.add_mutually_exclusive_group(required=True)
    scan_group.add_argument('--staged', action='store_true', help='Scan staged git files')
    scan_group.add_argument('--file', action='append', help='File to scan (can be repeated)')
    
    # hook-run (internal, called by hook)
    subparsers.add_parser('hook-run', help='Internal: run from git hook')
    
    args = parser.parse_args()
    
    if args.command == 'install':
        result = install_hook()
        if result['status'] == 'success':
            print(f"✓ Pre‑commit hook installed at {result['hook_path']}")
        else:
            print(f"✗ {result['message']}")
        print(json.dumps(result, indent=2))
    
    elif args.command == 'scan':
        result = run_scan(args)
        if result['status'] == 'success':
            findings = result['findings']
            if findings:
                print(f"⚠️  Found {len(findings)} secret(s):")
                for f in findings:
                    print(f"  {f['file']}:{f['line']} [{f['label']}] {f['secret'][:20]}...")
                print("✗ Secrets detected")
            else:
                print(f"✓ No secrets found (scanned {result['file_count']} files)")
        else:
            print(f"✗ {result['message']}")
        print(json.dumps(result, indent=2))
        # Exit with appropriate code for hook usage
        if args.staged and findings:
            sys.exit(1)
    
    elif args.command == 'hook-run':
        # Called from git hook: scan staged files and exit with appropriate code
        result = run_scan(argparse.Namespace(staged=True, file=None))
        findings = result.get('findings', [])
        if findings:
            print("⚠️  Secret detection blocked commit:")
            for f in findings:
                print(f"  {f['file']}:{f['line']} [{f['label']}] {f['content'][:60]}...")
            sys.exit(1)
        else:
            sys.exit(0)
    
    else:
        parser.print_help()
        sys.exit(1)

if __name__ == '__main__':
    main()
```



---

## Skill Companion Files

> Additional files collected from the skill directory layout.

### README.md

```markdown
# Secret Detection Skill

A git pre‑commit hook that scans staged files for common secret patterns (API keys, passwords, tokens) and blocks commits if secrets are found.

## Quick Start

1. **Install the hook** (in your git repository):
   ```bash
   ./scripts/main.py install
   ```

2. **Test the scanner**:
   ```bash
   ./scripts/main.py scan --staged
   ```

3. **The hook will run automatically** on every `git commit`.

## What It Detects

- AWS Access Key IDs (`AKIA...`)
- AWS Secret Access Keys
- Passwords, secrets, tokens in variable assignments
- GitHub Personal Access Tokens (`ghp_...`)
- GitHub Fine‑Grained Tokens (`github_pat_...`)
- OpenAI API Keys (`sk-...`)
- Bearer tokens

## Manual Usage

### Scan Specific Files
```bash
./scripts/main.py scan --file config.yaml --file .env
```

### Scan All Staged Files
```bash
./scripts/main.py scan --staged
```

## How It Works

1. The `install` command creates a `.git/hooks/pre‑commit` script that calls this scanner.
2. On `git commit`, the hook scans all staged files using regex patterns.
3. If any secret pattern is matched, the commit is blocked and the secrets are displayed.
4. Clean commits proceed normally.

## Limitations

- Only common secret patterns are detected (custom patterns can be added by editing `SECRET_PATTERNS` in `scripts/main.py`).
- May produce false positives (e.g., long random strings that aren't secrets).
- Does not scan binary files.
- Requires manual installation per repository.

## For Developers

The skill is written in Python 3 and uses no external dependencies beyond the standard library.

To extend the detection patterns, edit the `SECRET_PATTERNS` list in `scripts/main.py`.
```

### _meta.json

```json
{
  "owner": "derick001",
  "slug": "secret-detection",
  "displayName": "Secret Detection",
  "latest": {
    "version": "1.0.0",
    "publishedAt": 1772028199895,
    "commit": "https://github.com/openclaw/skills/commit/54eced6495958b0c27fd7f66b818071797aec6bb"
  },
  "history": []
}

```

secret-detection | SkillHub