How to Remove Hardcoded Credentials From Source Code

A password or API key written directly into source code is exposed to everyone with repo access - including every git clone, fork, and log entry forever. The fix is one line: read from os.environ instead of hardcoding the value.

Security Engineerpythonflaskcredentials

Why hardcoded credentials are a critical finding

When a secret is hardcoded in source code, it leaks on every surface:

The fix is to inject secrets at runtime through the environment and never write them into files that enter version control.

The pattern: os.environ reads

Before - credentials hardcoded in source:

# BAD: anyone who can read app.py has these credentials
DB_PASSWORD = "dev"
API_SECRET_KEY = "s3cr3t-k3y-f0r-t0k3ns"

After - values come from the runtime environment:

import os

DB_PASSWORD = os.environ["DB_PASSWORD"]
API_SECRET_KEY = os.environ["API_SECRET_KEY"]

os.environ["VAR_NAME"] raises KeyError at startup if the variable is missing - which is the right behavior. It makes a misconfigured deployment fail fast and loudly rather than running with a blank or wrong credential. Use os.environ.get("VAR_NAME", default) only when a missing value is genuinely acceptable.

How environment variables get set

In local development, set them in your shell or a .env file that is never committed (add .env to .gitignore):

export DB_PASSWORD="dev"
export API_SECRET_KEY="s3cr3t-k3y-f0r-t0k3ns"
python3 app.py

In production, secrets are injected by the runtime:

Adding a pre-commit guard

The longer-term protection is blocking the secret from ever reaching git. gitleaks and trufflehog both run as pre-commit hooks and match common credential patterns (API key prefixes, high-entropy strings, known service formats):

# install gitleaks and add a pre-commit hook
gitleaks detect --source . --verbose

A CI check that runs the same scan on every pull request catches anything a developer's local hook missed.

Rotating after a leak

If a secret was already committed, removal alone is not enough. The credential is in every clone. The required steps are: (1) revoke and rotate the credential immediately, (2) rewrite history with git filter-repo to scrub the value, and (3) force-push with a coordinated team heads-up. Assume every clone made before the rotation is compromised.

Want to try it hands-on? HeyDevJob gives you this exact setup in a live cloud workspace in your browser - edit it, run it, and see it work. Free, nothing to install.

Try it in a workspace →

What you'll practice

FAQ

How do I remove hardcoded credentials from Python source code?

Replace the hardcoded string with os.environ["VAR_NAME"]. This reads the value from the runtime environment at startup. Set the variable in your shell for local dev, and via your deployment platform (K8s Secret, AWS Secrets Manager, etc.) in production.

What's the difference between os.environ[] and os.environ.get()?

os.environ["KEY"] raises KeyError at startup if the variable is missing - good for required secrets because it fails fast. os.environ.get("KEY", default) returns the default if missing, which is appropriate only when a missing value is genuinely acceptable.

If I remove a hardcoded password from git, is it gone?

No. Every commit that contained it still has it in git history, and everyone who cloned the repo before the removal has it locally. You must rotate the credential immediately and optionally rewrite history with git filter-repo to purge the value from all commits.

Keep learning

Close a SQL Injection in a Search EndpointSecurity projectNeutralize a Stored XSS in CommentsSecurity projectHash Passwords Instead of Storing PlaintextSecurity projectSecurity roadmapStep by step to hiredSecurity interview questionsSTAR answersAll Security projectsProjects hub

Learn it by doing. Open this in a live cloud workspace, make the change yourself, and keep a record of the work you can share.

Open the workspace →