Skip to main content

detecting-secrets

This skill should be used when the user asks to "find hardcoded secrets", "audit for credential leaks", "check for API keys in code", "review secret scanning alerts", "rotate a leaked secret", or needs to detect hardcoded credentials, review secret handling patterns, or remediate exposed secrets.

Source facts

Repository
bitwarden/ai-plugins
Last source activity
February 13, 2026 at 15:48
Detected SKILL.md language
English
Stars
163
Forks
24

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
detecting-secrets
description
This skill should be used when the user asks to "find hardcoded secrets", "audit for credential leaks", "check for API keys in code", "review secret scanning alerts", "rotate a leaked secret", or needs to detect hardcoded credentials, review secret handling patterns, or remediate exposed secrets.
## Secret Patterns Look for these categories of hardcoded secrets in code: ### High-Confidence Patterns | Type | Example Patterns | | ------------------ | ----------------------------------------------------------------------------------------------------------------------- | | API Keys | `AKIA[0-9A-Z]{16}` (AWS), `AIza[0-9A-Za-z_-]{35}` (Google), strings assigned to variables named `*apiKey*`, `*api_key*` | | Connection Strings | `Server=...;Password=...`, `mongodb://user:pass@host`, `postgres://user:pass@host` | | Private Keys | `-----BEGIN RSA PRIVATE KEY-----`, `-----BEGIN OPENSSH PRIVATE KEY-----` | | Tokens | `ghp_[A-Za-z0-9]{36}` (GitHub PAT), `xoxb-` (Slack bot), `sk-` (OpenAI) | | Passwords | Values assigned to variables named `*password*`, `*passwd*`, `*secret*`, `*credential*` | | Certificates | PFX/P12 files with embedded passwords, PEM files with private keys | ### Lower-Confidence Patterns (Require Context) - Base64-encoded strings in configuration (may be encrypted or may be cleartext secrets) - JWT tokens (may be test tokens or production tokens) - Hex strings of 32+ characters (may be encryption keys or hashes) - URLs with embedded credentials (`https://user:pass@host`) ## Context-Aware Detection Distinguish real secrets from false positives. Not every pattern match indicates an actual secret — consider context: ### Test Fixtures and Mock Data ```csharp // NOT a real secret — test fixture with obvious fake value var testApiKey = "test-api-key-not-real-12345"; var mockPassword = "P@ssword123"; // Used only in unit tests // REAL secret — production-looking value in non-test code var apiKey = "sk-proj-abc123def456ghi789jkl012mno345pqr678stu901vwx"; ``` **Decision criteria:** - Is it in a test directory (`**/test/**`, `**/tests/**`, `**/*.Test/**`)? - Does the value contain obvious placeholder text ("test", "fake", "mock", "example", "placeholder")? - Is the value used in assertions or mock setups? ### Example and Placeholder Values ```json // NOT a real secret — documented example { "apiKey": "YOUR_API_KEY_HERE" } // REAL secret — actual value in config { "apiKey": "sk-proj-abc123def456ghi789jkl012mno345pqr678stu901vwx" } ``` ### Encrypted or Hashed Values - Hashed passwords (bcrypt `$2b$`, argon2 `$argon2id$`) are NOT secrets — they're properly stored - Encrypted values with proper key management are NOT secrets in the same way - But the encryption KEY itself, if hardcoded, IS a secret ## Common Hiding Spots Search these locations when auditing for secrets: | Location | What to Look For | | --------------------------------------------------- | ---------------------------------------------------------- | | `appsettings.json` / `appsettings.Development.json` | Connection strings, API keys, service credentials | | `.env` / `.env.local` | Environment variable definitions with real values | | `web.config` / `app.config` | Machine keys, connection strings | | `docker-compose.yml` / `Dockerfile` | `ENV` directives with credentials, build args with secrets | | CI/CD files (`.github/workflows/*.yml`) | Inline secrets instead of `${{ secrets.* }}` references | | Test seed scripts / migration files | Database passwords, service account credentials | | Comments and TODO notes | "Temporary" credentials left in comments | | Default parameter values | `function connect(password = "admin123")` | | Constants files | Centralized credential definitions | ## GitHub Secret Scanning Integration ```bash # List all secret scanning alerts gh api /repos/{owner}/{repo}/secret-scanning/alerts --jq '.[] | {number, state, secret_type, secret_type_display_name, created_at, push_protection_bypassed}' # Get details for a specific alert gh api /repos/{owner}/{repo}/secret-scanning/alerts/{alert_number} # List alerts that bypassed push protection gh api "/repos/{owner}/{repo}/secret-scanning/alerts?state=open" --jq '.[] | select(.push_protection_bypassed == true)' ``` **Push protection** prevents commits containing detected secrets from being pushed. When someone bypasses push protection, the alert is flagged — review these with extra scrutiny. ## Remediation Workflow When a secret is found in code, follow this sequence: ### 1. Rotate Immediately Assume any committed secret is compromised. Even if the repo is private, the secret may have been cached, logged, or accessed by CI/CD systems. - Revoke the existing credential - Generate a new credential - Update the credential wherever it's used (services, deployments) ### 2. Remove from Code Replace the hardcoded secret with a secure reference: ```csharp // WRONG — hardcoded secret var connectionString = "Server=prod.db;Password=s3cr3t!"; // CORRECT — environment variable var connectionString = Environment.GetEnvironmentVariable("DB_CONNECTION_STRING"); // CORRECT — Azure Key Vault (Bitwarden's approach) var connectionString = await keyVaultClient.GetSecretAsync("db-connection-string"); ``` ### 3. Remove from Git History (If Needed) If the secret was committed to a public repo or a repo that will become public: ```bash # Using git filter-repo (preferred over filter-branch) git filter-repo --path-glob '*.json' --replace-text expressions.txt # expressions.txt format: # literal:the-secret-value==>REDACTED ``` **Warning:** Rewriting git history is destructive and affects all collaborators. Only do this when the secret was exposed in a public or soon-to-be-public repository. ### 4. Prevent Recurrence - Add patterns to `.gitignore` for files that should never be committed (`.env`, `*.pfx`, `appsettings.Development.json`) - Enable GitHub push protection for the repository - Use secret scanning custom patterns for organization-specific secret formats ## Secure Alternatives Bitwarden uses Azure Key Vault for secrets management, provisioned by the BRE team: | Instead Of | Use | | ------------------------------- | ---------------------------------------------- | | Hardcoded connection strings | Azure Key Vault secrets | | API keys in config files | Environment variables set at deployment | | Certificates in source | Azure Key Vault certificates | | Shared team credentials in code | Managed identities (Azure) | | Secrets in CI/CD workflow files | GitHub Actions secrets (`${{ secrets.NAME }}`) | For local development, use user-secrets or `.env` files that are `.gitignore`d — never commit them. ## Critical Rules - **Assume any committed secret is compromised.** Always rotate, even if the repo is private. No exceptions. - **Never suppress secret scanning alerts without rotation.** Dismissing an alert doesn't make the exposure go away. - **Validation, not just detection.** When a potential secret is found, verify it's real before raising an alarm. Check if it's a test value, placeholder, or encrypted content. - **Check the full commit history.** A secret removed in the latest commit may still exist in git history. Use `git log -p -S "secret-pattern"` to search history. - **Bitwarden uses Azure Key Vault** for secrets management. If a new secret needs to be stored, work with BRE to provision vault access for the repository.
View on GitHub