API keys, database passwords, webhook tokens, and private keys are often treated like ordinary configuration details. However, anyone who possesses them may be able to send emails on behalf of the application, read customer data, access servers, or disable certain services.
The problem is that leaks do not always occur due to sophisticated attacks. Often, the source is simpler: credentials written in PHP files, included in Git, printed in logs, sent via screenshots, or stored in backups that are never checked. Therefore, the security of application secrets is not just a developer's concern. Website owners, server admins, and operational teams also need to have the right habits.
Application secrets are not just text that needs to be hidden
In the context of security, a secret is information that can grant access rights. Examples include database passwords, API tokens, SMTP credentials, encryption keys, session cookies, and deployment credentials.
A common mistake is to assume a token is safe as long as the repository is private. While private repositories do reduce the risk of public exposure, they do not eliminate the risk. Developer access, CI/CD logs, internal forks, backups, and infected laptops can still be leak paths.
The simple principle is: secrets should only be available to the processes and people who truly need them, for as long as necessary.
Do not place credentials directly in source code
Examples to avoid:
$dbPassword = 'your-production-password';
$apiKey = 'sk_live_xxxxxxxxx';The issue with such code is not just that the values are visible to anyone opening the file. Those values can also be copied to Git, included in build results, appear in error reports, or remain in commit history even after the lines have been deleted.
Use environment configuration or a secret manager instead. For simple PHP applications, the following pattern is better:
$apiKey = getenv('PAYMENT_API_KEY');
$dbPassword = getenv('DB_PASSWORD');However, moving values to a .env file does not mean the problem is solved. That file should still be outside the document root if possible, must not be committed, and should have limited read permissions. Ensure the web server cannot serve it as a downloadable file.
WordPress: protect wp-config.php and security keys
In a WordPress installation, the wp-config.php file contains sensitive information such as database credentials and security keys. WordPress documentation recommends that this file should only be readable by those who need it. In certain configurations, this file can also be placed one level above the WordPress installation directory, provided the server configuration is done correctly.
Security keys and salts help WordPress create cookies and nonces that are harder to guess. Their values should be long, random, and unique for each site. WordPress also explains that changing keys can invalidate active cookies, requiring users to log in again.
This is useful when there is suspicion that authentication cookies have leaked. Remember, changing keys is not a substitute for investigation. If the source of the leak has not been found, other related tokens or passwords may still be misused.
Nonces are not a substitute for authorization
In WordPress plugins or themes, nonces are often used to ensure a request comes from the expected flow. This helps combat forged requests from the user's browser, but nonces are not passwords and are not an authorization mechanism.
This means that functions that modify data must still check the user's capabilities with current_user_can(). Do not create admin endpoints that only check nonces and assume anyone with a nonce is automatically allowed to perform that action.
check_ajax_referer('delete-comment', 'nonce');
if ( ! current_user_can('moderate_comments') ) {
wp_die('Access denied');
}This pattern separates two important questions: whether the request has protection against forgery, and whether the user is indeed authorized to perform that action.
Reduce impact if a secret leaks
A secure secret is not just one that is hard to find. It should also have limited access scope and be revocable.
- Use different API keys for development, staging, and production.
- Limit token permissions only to the necessary endpoints or services.
- Avoid using a single password across multiple applications.
- Set token expiration if the service supports it.
- Keep track of who can view or change those secrets.
- Rotate credentials regularly and after incidents.
OWASP emphasizes the importance of least privilege, rotation, revocation, auditing, and prohibiting secrets from being printed in logs. In practice, payment tokens should not have permissions to change server configurations, and backup credentials should not be used as daily login passwords.
Add checks before secrets enter the repository
Do not rely solely on the developer's memory. Add automated checks to the Git workflow. Secret scanning can search for common token patterns, while push protection can prevent certain commits from entering the repository.
Such tools are helpful, but they are not a complete guarantee. Internal patterns, custom tokens, or obfuscated secrets can still slip through. Therefore, basic rules such as prohibiting commits of .env files, reviewing configuration changes, and using a .env.example template remain necessary.
Example contents of .gitignore:
.env
.env.*
!.env.example
*.pem
backup/
The .env.example file may contain variable names without secret values:
DB_HOST=localhost
DB_NAME=database_name
DB_USER=username
DB_PASSWORD=
PAYMENT_API_KEY=If secrets have already leaked
Do not stop at deleting lines of code or making a new commit. Old values may still exist in Git history, CI/CD caches, backups, logs, or local copies.
- Revoke or disable the leaked token as soon as possible.
- Create replacement credentials with more limited permissions.
- Check usage logs for any unusual activity.
- Identify all places where the value has been stored or copied.
- Clean up the repository and unnecessary artifacts.
- Document the cause and fixes to prevent recurrence.
The order is important. Deleting secrets from Git without revoking tokens does not stop misuse. Conversely, replacing tokens without finding the source of the leak can cause new credentials to spread again.
What can be done now
- Search for words like
password,api_key,secret, andtokenin the source code and configuration files. - Ensure
.env, database backups, and private keys are not accessible from public URLs. - Check application logs to ensure they do not print Authorization headers, cookies, or sensitive queries.
- Replace credentials that have been shared via chat, email, or screenshots.
- Enable secret scanning or similar checks in the repository.
- Make a simple note: what secrets exist, which services use them, who owns them, and how to rotate them.
Securing secrets does not require an expensive system to start improving. The most important thing is to treat API keys and credentials as access, not as ordinary configuration text. Once this perspective changes, technical decisions such as permission restrictions, rotation, auditing, and incident response become much more sensible.
Official references: OWASP Secrets Management Cheat Sheet, WordPress Hardening, WordPress wp-config.php, and GitHub Security Features.
Sources & further reading
- OWASP Secrets Management Cheat Sheet
- WordPress Hardening
- WordPress wp-config.php
- WordPress Nonces
- GitHub Security Features
– Rio Yotto @rioyotto
