Bitwarden Designer
Bitwarden Dev Ops Engineer
Bitwarden Product Analyst
Bitwarden Tech Lead
Bitwarden Testing Tools
Claude Config Validator
Claude Retrospective
59 chapters · 270 min
Bitwarden Security Engineer
Chapter 41 of 59
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…
3 minutes · 621 words · 16 sections
Look for these categories of hardcoded secrets in code:
| 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 |
https://user:pass@host)Distinguish real secrets from false positives. Not every pattern match indicates an actual secret — consider context:
// 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:
**/test/**, **/tests/**, **/*.Test/**)?// NOT a real secret — documented example
{
"apiKey": "YOUR_API_KEY_HERE"
}
// REAL secret — actual value in config
{
"apiKey": "sk-proj-abc123def456ghi789jkl012mno345pqr678stu901vwx"
}$2b$, argon2 $argon2id$) are NOT secrets — they’re properly storedSearch 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 |
# 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.
When a secret is found in code, follow this sequence:
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.
Replace the hardcoded secret with a secure reference:
// 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");If the secret was committed to a public repo or a repo that will become public:
# 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==>REDACTEDWarning: 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.
.gitignore for files that should never be committed (.env, *.pfx, appsettings.Development.json)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 .gitignored — never commit them.
git log -p -S "secret-pattern" to search history.Install this repository
npx skills add bitwarden/ai-plugins/plugin marketplace add bitwarden/ai-pluginsSkills install per repository, not per chapter — the CLI has no documented per-skill form, so we do not print one.
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.
The verbatim description from this skill’s front matter — the string an agent matches on to decide whether to load it.
main, last pushed 8 August 2026.SKILL.md, not by matching a directory convention. 13 distinct layouts observed: plugins/bitwarden-atlassian-tools/skills/*/SKILL.md, plugins/bitwarden-code-review/skills/*/SKILL.md, plugins/bitwarden-delivery-tools/skills/*/SKILL.md, plugins/bitwarden-design-tools/skills/*/SKILL.md, plugins/bitwarden-designer/skills/*/SKILL.md, plugins/bitwarden-devops-engineer/skills/*/SKILL.md, plugins/bitwarden-product-analyst/skills/*/SKILL.md, plugins/bitwarden-security-engineer/skills/*/SKILL.md, plugins/bitwarden-shepherd/skills/*/SKILL.md, plugins/bitwarden-tech-lead/skills/*/SKILL.md, plugins/bitwarden-testing-tools/skills/*/SKILL.md, plugins/claude-config-validator/skills/*/SKILL.md, plugins/claude-retrospective/skills/*/SKILL.md..claude-plugin/marketplace.json by Bitwarden, declaring 16 plugins. It is read for editorial metadata only — never as the skill index, which is always the repository tree./bitwarden/ai-plugins.md, and each chapter at its own .md URL.