Skip to main content
hook official · GitHub

secrets-scanner — GitHub Copilot hook: catch leaked secrets

Scans the files a Copilot coding agent touched during a session for leaked keys and credentials before they get committed. Useful when the agent edits code fast.

Install into Claude Code · Manually: put the files in place All methods and platforms ↓
.claude/settings.json
Open on GitHub

What secrets-scanner does

The hook fires on sessionEnd, at the close of a GitHub Copilot coding agent session. It collects modified files with git diff, drops binaries and lock files, then runs each line against patterns for known secrets: AWS, GCP and Azure credentials, GitHub, npm, Slack and Stripe tokens, RSA and OpenSSH private keys, connection strings for PostgreSQL, MongoDB, MySQL, Redis and MSSQL, JWTs, and internal IPs with ports. That covers more than twenty categories.

SCAN_MODE picks the behaviour. warn only logs findings, while block exits non-zero so the agent stops before committing. SCAN_SCOPE chooses between diff and staged. Values that look like placeholders such as example, changeme or your_ are skipped, and known false positives go into SECRETS_ALLOWLIST. Scan events land in logs/copilot/secrets/scan.log as JSON Lines, with matches truncated so the log does not re-expose the secret.

No dependencies: the script leans on grep, file and git. Setup is manual — copy the folder into .github/hooks/, make the script executable, create the log directory and add it to .gitignore. If you pair it with the Session Auto-Commit hook, order matters: the scanner has to run first, otherwise the commit happens before the check. In that pairing you need SCAN_MODE=block for the block to mean anything.

What it helps with

  • catch an AWS key that slipped into a modified file
  • stop a commit while a GitHub token sits in the code
  • filter out placeholders so false positives do not pile up
  • keep an audit trail of findings in JSON Lines
  • prevent auto-commit when a secret is detected

Example prompts for the agent

  • Turn on secrets-scanner in block mode so the agent cannot commit secrets
  • Set SCAN_SCOPE=staged and scan only the files in the index
  • Add test_key_123 to SECRETS_ALLOWLIST, that one is a false positive

How to install secrets-scanner

Manually: put the files in place

.claude/settings.json

The hooks block: event (PreToolUse, PostToolUse, Stop…) → command. Personal ones go to ~/.claude/settings.json

Step by step, with commands for each platform: Claude Code hooks: what they are, where to configure them, how to block a risky command

Questions about secrets-scanner

How do I install secrets-scanner in GitHub Copilot?

Copy the hook folder into your repository with cp -r hooks/secrets-scanner .github/hooks/, then make the script executable: chmod +x .github/hooks/secrets-scanner/scan-secrets.sh. Create the log directory and add it to .gitignore with mkdir -p logs/copilot/secrets and echo "logs/" >> .gitignore. Finally commit the hook configuration to your default branch.

What does secrets-scanner do?

At the end of an agent session it scans modified files for leaked secrets: cloud credentials, platform tokens, private keys, connection strings and JWTs. Findings go to a log, and in block mode the session exits non-zero before committing.

What is the difference between warn and block?

warn logs findings and stops nothing. block exits non-zero, so the agent does not commit. You pick the mode with SCAN_MODE.

Source text

secrets-scanner · MIT
---
name: 'Secrets Scanner'
description: 'Scans files modified during a Copilot coding agent session for leaked secrets, credentials, and sensitive data'
tags: ['security', 'secrets', 'scanning', 'session-end']
---

# Secrets Scanner Hook

Scans files modified during a GitHub Copilot coding agent session for accidentally leaked secrets, credentials, API keys, and other sensitive data before they are committed.

## Overview

AI coding agents generate and modify code rapidly, which increases the risk of hardcoded secrets slipping into the codebase. This hook acts as a safety net by scanning all modified files at session end for 20+ categories of secret patterns, including:

- **Cloud credentials**: AWS access keys, GCP service account keys, Azure client secrets
- **Platform tokens**: GitHub PATs, npm tokens, Slack tokens, Stripe keys
- **Private keys**: RSA, EC, OpenSSH, PGP, DSA private key blocks
- **Connection strings**: Database URIs (PostgreSQL, MongoDB, MySQL, Redis, MSSQL)
- **Generic secrets**: API keys, passwords, bearer tokens, JWTs
- **Internal infrastructure**: Private IP addresses with ports

## Features

- **Two scan modes**: `warn` (log only) or `block` (exit non-zero to prevent commit)
- **Two scan scopes**: `diff` (modified files vs HEAD) or `staged` (git-staged files only)
- **Smart filtering**: Skips binary files, lock files, and placeholder/example values
- **Allowlist support**: Exclude known false positives via `SECRETS_ALLOWLIST`
- **Structured logging**: JSON Lines output for integration with monitoring tools
- **Redacted output**: Findings are truncated in logs to avoid re-exposing secrets
- **Zero dependencies**: Uses only standard Unix tools (`grep`, `file`, `git`)

## Installation

1. Copy the hook folder to your repository:

   ```bash
   cp -r hooks/secrets-scanner .github/hooks/
   ```

2. Ensure the script is executable:

   ```bash
   chmod +x .github/hooks/secrets-scanner/scan-secrets.sh
   ```

3. Create the logs directory and add it to `.gitignore`:

   ```bash
   mkdir -p logs/copilot/secrets
   echo "logs/" >> .gitignore
   ```

4. Commit the hook configuration to your repository's default branch.

## Configuration

The hook is configured in `hooks.json` to run on the `sessionEnd` event:

```json
{
  "version": 1,
  "hooks": {
    "sessionEnd": [
      {
        "type": "command",
        "bash": ".github/hooks/secrets-scanner/scan-secrets.sh",
        "cwd": ".",
        "env": {
          "SCAN_MODE": "warn",
          "SCAN_SCOPE": "diff"
        },
        "timeoutSec": 30
      }
    ]
  }
}
```

### Environment Variables

| Variable | Values | Default | Description |
|----------|--------|---------|-------------|
| `SCAN_MODE` | `warn`, `block` | `warn` | `warn` logs findings only; `block` exits non-zero to prevent auto-commit |
| `SCAN_SCOPE` | `diff`, `staged` | `diff` | `diff` scans uncommitted changes vs HEAD; `staged` scans only staged files |
| `SKIP_SECRETS_SCAN` | `true` | unset | Disable the scanner entirely |
| `SECRETS_LOG_DIR` | path | `logs/copilot/secrets` | Directory where scan logs are written |
| `SECRETS_ALLOWLIST` | comma-separated | unset | Patterns to ignore (e.g., `test_key_123,example.com`) |

## How It Works

1. When a Copilot coding agent session ends, the hook executes
2. Collects all modified files using `git diff` (respects the configured scope)
3. Filters out binary files and lock files
4. Scans each text file line-by-line against 20+ regex patterns for known secret formats
5. Skips matches that look like placeholders (e.g., values containing `example`, `changeme`, `your_`)
6. Checks matches against the allowlist if configured
7. Reports findings with file path, line number, pattern name, and severity
8. Writes a structured JSON log entry for audit purposes
9. In `block` mode, exits non-zero to signal the agent to stop before committing

## Detected Secret Patterns

| Pattern | Severity | Example Match |
|---------|----------|---------------|
| `AWS_ACCESS_KEY` | critical | `AKIAIOSFODNN7EXAMPLE` |
| `AWS_SECRET_KEY` | critical | `aws_secret_access_key = wJalr...` |
| `GCP_SERVICE_ACCOUNT` | critical | `"type": "service_account"` |
| `GCP_API_KEY` | high | `AIzaSyC...` |
| `AZURE_CLIENT_SECRET` | critical | `azure_client_secret = ...` |
| `GITHUB_PAT` | critical | `ghp_xxxxxxxxxxxx...` |
| `GITHUB_FINE_GRAINED_PAT` | critical | `github_pat_...` |
| `PRIVATE_KEY` | critical | `-----BEGIN RSA PRIVATE KEY-----` |
| `GENERIC_SECRET` | high | `api_key = "sk-..."` |
| `CONNECTION_STRING` | high | `postgresql://user:pass@host/db` |
| `SLACK_TOKEN` | high | `xoxb-...` |
| `STRIPE_SECRET_KEY` | critical | `sk_live_...` |
| `NPM_TOKEN` | high | `npm_...` |
| `JWT_TOKEN` | medium | `eyJhbGci...` |
| `INTERNAL_IP_PORT` | medium | `192.168.1.1:8080` |

See the full list in `scan-secrets.sh`.

## Example Output

### Clean scan

```
🔍 Scanning 5 modified file(s) for secrets...
✅ No secrets detected in 5 scanned file(s)
```

### Findings detected (warn mode)

```
🔍 Scanning 3 modified file(s) for secrets...

⚠️  Found 2 potential secret(s) in modified files:

  FILE                                     LINE   PATTERN                      SEVERITY
  ----                                     ----   -------                      --------
  src/config.ts                            12     GITHUB_PAT                   critical
  .env.local                               3      CONNECTION_STRING            high

💡 Review the findings above. Set SCAN_MODE=block to prevent commits with secrets.
```

### Findings detected (block mode)

```
🔍 Scanning 3 modified file(s) for secrets...

⚠️  Found 1 potential secret(s) in modified files:

  FILE                                     LINE   PATTERN                      SEVERITY
  ----                                     ----   -------                      --------
  lib/auth.py                              45     AWS_ACCESS_KEY               critical

🚫 Session blocked: resolve the findings above before committing.
   Set SCAN_MODE=warn to log without blocking, or add patterns to SECRETS_ALLOWLIST.
```

## Log Format

Scan events are written to `logs/copilot/secrets/scan.log` in JSON Lines format:

```json
{"timestamp":"2026-03-13T10:30:00Z","event":"secrets_found","mode":"warn","scope":"diff","files_scanned":3,"finding_count":2,"findings":[{"file":"src/config.ts","line":12,"pattern":"GITHUB_PAT","severity":"critical","match":"ghp_...xyz1"}]}
```

```json
{"timestamp":"2026-03-13T10:30:00Z","event":"scan_complete","mode":"warn","scope":"diff","status":"clean","files_scanned":5}
```

## Pairing with Other Hooks

This hook pairs well with the **Session Auto-Commit** hook. When both are installed, order them so that `secrets-scanner` runs first:

1. Secrets scanner runs at `sessionEnd`, catches leaked secrets
2. Auto-commit runs at `sessionEnd`, only commits if all previous hooks pass

Set `SCAN_MODE=block` to prevent auto-commit when secrets are detected.

## Customization

- **Add custom patterns**: Edit the `PATTERNS` array in `scan-secrets.sh` to add project-specific secret formats
- **Adjust sensitivity**: Change severity levels or remove patterns that generate false positives
- **Allowlist known values**: Use `SECRETS_ALLOWLIST` for test fixtures or known safe patterns
- **Change log location**: Set `SECRETS_LOG_DIR` to route logs to your preferred directory

## Disabling

To temporarily disable the scanner:

- Set `SKIP_SECRETS_SCAN=true` in the hook environment
- Or remove the `sessionEnd` entry from `hooks.json`

## Limitations

- Pattern-based detection; does not perform entropy analysis or contextual validation
- May produce false positives for test fixtures or example code (use the allowlist to suppress these)
- Scans only text files; binary secrets (keystores, certificates in DER format) are not detected
- Requires `git` to be available in the execution environment


```json
{
  "version": 1,
  "hooks": {
    "sessionEnd": [
      {
        "type": "command",
        "bash": ".github/hooks/secrets-scanner/scan-secrets.sh",
        "cwd": ".",
        "env": {
          "SCAN_MODE": "warn",
          "SCAN_SCOPE": "diff"
        },
        "timeoutSec": 30
      }
    ]
  }
}

```

© github · MIT · github/awesome-copilot

Similar hooks

Everything for Security →

From the same set732

The whole set →
dataverse-python-modules The rule hands your agent a map of PowerPlatform.Dataverse: client, config, errors, OData and SQL. Useful whenever Python code talks to Dataverse. ★ 40,418repo stars dataverse-python-file-operations Guides Python file uploads to Microsoft Dataverse via the official SDK. Handles single PATCH uploads, 4 MB chunking for files over 128 MB, and retry loops. ★ 40,418repo stars dataverse-python-error-handling Guidance for handling Dataverse SDK for Python exceptions, inspecting response codes, and deciding which failed requests are worth retrying. ★ 40,418repo stars dataverse-python-best-practices A GitHub Copilot rule with working patterns for the Dataverse SDK for Python: auth, client setup, CRUD operations. ★ 40,418repo stars dependency-license-checker A GitHub Copilot hook that scans newly added dependencies at session end and flags copyleft licenses before they get committed. ★ 40,418repo stars WG Code Sentinel A GitHub Copilot subagent that reviews code and configs for vulnerabilities and hands you concrete fixes. Useful before a merge or a release. ★ 40,418repo stars Expert Vue.js Frontend Engineer GitHub Copilot subagent specialized in Vue 3, Composition API, TypeScript, and component architecture. Builds frontends, migrates from Vue 2, and optimizes rendering. ★ 40,418repo stars TypeScript MCP Server Expert Writes MCP servers in TypeScript: project layout, tools, transports, debugging. Useful when you want working code instead of generic advice. ★ 40,418repo stars

Project sponsors

Companies that keep this analytics open
Gold sponsor

Impressions, clicks and code copies — open statistics. We keep the numbers public for the same reason NeBlask itself is public. Become a sponsor