SC001: NoHardcodedSecrets

Overview

Property Value
ID SC001
Name NoHardcodedSecrets
Group security
Severity ERROR

Description

Scans Python source files for hardcoded secrets such as API keys, passwords, tokens, and private keys that should never be committed to version control.

Exposing secrets in source code is a critical security vulnerability that can lead to:

  • Unauthorized access to services and APIs
  • Data breaches
  • Financial loss
  • Compliance violations

What it checks

The check scans all .py files (excluding test files) for patterns matching:

  • OpenAI API keys: sk-... patterns
  • AWS Access Key IDs: AKIA... patterns
  • GitHub tokens: ghp_*, gho_*, ghu_*, ghs_*, ghr_* patterns
  • Private key markers: -----BEGIN RSA PRIVATE KEY-----
  • Password assignments: password = "..." or password: "..."
  • Secret assignments: secret = "..." or secret: "..."
  • API key assignments: api_key = "..." with long values

Result states

  • PASSED: No hardcoded secrets found
  • FAILED: One or more potential secrets detected

How to fix

Use environment variables

import os

# Bad: hardcoded secret
API_KEY = "sk-1234567890abcdef1234567890abcdef"

# Good: from environment
API_KEY = os.environ.get("OPENAI_API_KEY")

Use a secrets manager

from dotenv import load_dotenv
import os

load_dotenv()  # Load from .env file (not committed to git)
API_KEY = os.environ.get("API_KEY")

Use a configuration file

from pathlib import Path
import tomllib

# Load from user config (not in repo)
config_path = Path.home() / ".config" / "myapp" / "config.toml"
with open(config_path, "rb") as f:
    config = tomllib.load(f)
API_KEY = config["api_key"]

Add secrets to .gitignore

Ensure sensitive files are never committed:

# .gitignore
.env
*.pem
*.key
secrets.toml

Why ERROR severity?

This check is an ERROR because:

  • Hardcoded secrets pose immediate security risks
  • Once committed, secrets may be in git history forever
  • Credential leaks can have severe consequences

Configuration

Skip this check

[tool.pycmdcheck]
skip = ["SC001"]

CLI

pycmdcheck --skip SC001