Safe Secrets Management | Developer & AI Guide
A practical guide to secure secrets management on Windows and Linux, featuring env variables, strict file permissions, and safety tips for AI vibe coding.
Managing secrets securely is a fundamental practice in software engineering. Whether configuring local environments, deploying production servers, or building software with AI-assisted "vibe coding" workflows, a recurring challenge is keeping API keys, database passwords, and SSH keys protected from accidental exposure.
Hardcoding credentials directly into source code is the ultimate developer anti-pattern. Once committed, credentials can easily leak via GitHub, command histories, or (increasingly common) the context windows of AI coding assistants.
Separating code from configuration is the baseline for modern security. Below are the practical patterns for safeguarding secrets across different operating systems.
1. Secrets Management on Windows
On Windows, developers typically manage local secrets using environment variables. These variables are stored in the user environment registry and are readable by running processes.
Storing Variables with setx
To set a persistent user-level environment variable in Windows, use setx in PowerShell or Command Prompt:
setx OPENAI_API_KEY "sk-proj-xxxxxx..."
setx writes the key-value pair to the Windows Registry at: HKEY_CURRENT_USER\Environment
The Session Gotcha
A common frustration with setx is that variables set via this command do not propagate to the current active terminal session. If you run echo $env:OPENAI_API_KEY immediately after setx, it will print empty.
To make the variable immediately available in your active PowerShell window, you must set it in-memory for the current process:
$env:OPENAI_API_KEY = "sk-proj-xxxxxx..."
Any new terminal window opened after the setx command will load the persistent registry variable automatically.
Listing and Inspecting Environment Variables
To view variables inside PowerShell:
# Get a specific variable
Get-ChildItem Env:OPENAI_API_KEY
# List all current environment variables
dir Env:
[!WARNING] Environment variables stored via
setxare saved in plaintext within the registry. Any script or program running under your user account can read them. They protect you from source control leaks but do not isolate secrets from local malware.
2. Secrets Management on Linux
On Linux development machines and production servers, environment variables are set in shell configuration scripts (like ~/.bashrc or ~/.profile).
Appending to .bashrc
You can append variables to your configuration file directly from the CLI:
echo 'export APIC_KEY="your_api_key_here"' >> ~/.bashrc
source ~/.bashrc
The Terminal History Risk
Running the echo command above creates a major security risk: your secrets are written directly into your command history file (~/.bash_history).
history | tail -n 5
# Outputs: echo 'export APIC_KEY="your_api_key_here"' >> ~/.bashrc
If an attacker gains read-only access to your shell, or if you share terminal logs for troubleshooting, your API keys will be exposed.
Mitigations:
Use a leading space: If your shell has
HISTCONTROL=ignorespaceorHISTCONTROL=ignorebothconfigured, starting your command with a leading space prevents the shell from recording it in history:echo 'export APIC_KEY="your_api_key_here"' >> ~/.bashrcUse an interactive editor: Instead of
echo, open the file directly in an editor likenanoorvi:nano ~/.bashrcScroll to the bottom, type
export APIC_KEY="your_api_key_here", save, and exit.Clean up history: If you accidentally leak a key, delete it from the history list:
history -d <line_number>
3. Safe SSH Key Management
Using password authentication for remote systems is fragile and insecure. SSH keys provide a cryptographic alternative that is much harder to brute-force.
Generating Keys Securely
Always generate keys using modern, secure algorithms like Ed25519 rather than older RSA variants:
ssh-keygen -t ed25519 -C "your_email@example.com"
This generates two files in your user's home directory:
~/.ssh/id_ed25519(Your private key - NEVER share this)~/.ssh/id_ed25519.pub(Your public key - shared with target servers)
Applying Secure Permissions
SSH commands will refuse to run if your private keys are readable by other users on your local machine. Apply tight access permissions:
# Lock down the .ssh directory (Owner has read, write, execute)
chmod 700 ~/.ssh
# Lock down the private key file (Owner has read, write)
chmod 600 ~/.ssh/id_ed25519
# Lock down the public key (Optional but recommended)
chmod 644 ~/.ssh/id_ed25519.pub
Registering Keys on the Target Server
To authenticate, copy the contents of your public key (id_ed25519.pub) and append it to the remote server's authorized_keys file:
# Append to remote authorized_keys
cat ~/.ssh/id_ed25519.pub >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys
4. SSH Shortname Shortcuts (ssh [short_name])
Typing long connection strings (e.g., ssh -i ~/.ssh/id_ed25519 -p 65002 user@vps-target.example.com) every time you log in is tedious and prone to typos. You can simplify this using an SSH configuration file.
Configuring ~/.ssh/config
Create or edit the local config file:
nano ~/.ssh/config
Add your host parameters using a clean alias (short_name):
Host myvps
HostName vps-target.example.com
User root
Port 65002
IdentityFile ~/.ssh/id_ed25519
Apply strict permissions to this configuration file:
chmod 600 ~/.ssh/config
Running the Connection
With this config in place, you can connect to your remote host immediately using just the shortcut alias:
ssh myvps
The SSH agent reads your config file, maps myvps to the target host parameters, and executes the login using the configured private key.
5. The Credential File Pattern (Strict Permissions)
Sometimes environment variables or SSH keys are insufficient, such as when managing multiple systems, complex API tokens, or automated cron scripts. In these cases, developers use dedicated local credential files (e.g., .credential or .*_creds).
Securing the File Write
To create a hidden credentials file with multi-line variables, use a "Heredoc" block:
cat << 'EOF' > /root/.vps_ssh_creds
SSH_HOST="vps-target.example.com"
SSH_USER="u123456789"
SSH_PASS="your_vps_ssh_password"
SSH_PORT="65002"
EOF
[!TIP] Notice the single quotes around
'EOF'. Enclosing the tag in single quotes prevents the local shell from performing variable expansion inside the block. If you wrotecat << EOF(without quotes) and the block contained$VARIABLE, the shell would try to evaluate and replace$VARIABLEbefore writing it to the file.
Restricting Access
Once written, the file is vulnerable to any user on the system. You must immediately apply strict permissions using chmod:
chmod 600 /root/.vps_ssh_creds
To verify that the file is locked down, run ls -l:
ls -l /root/.vps_ssh_creds
# Outputs: -rw------- 1 root root 148 Jun 15 16:30 /root/.vps_ssh_creds
The prefix -rw------- guarantees that only the owner (root) has read-write access to the secret file.
Sourcing in Scripts
To use these credentials in automation scripts, use the shell's source (or .) command to load the variables into the script context:
#!/bin/bash
# Define the credential path
CREDS_FILE="/root/.vps_ssh_creds"
# Load variables if the file exists and is readable
if [ -f "$CREDS_FILE" ]; then
source "$CREDS_FILE"
else
echo "Error: Credentials file not found at $CREDS_FILE"
exit 1
fi
# Execute the connection securely using variables
sshpass -p "$SSH_PASS" ssh -p "$SSH_PORT" "$SSH_USER@$SSH_HOST"
6. Protecting Secrets in "Vibe Coding" Environments
"Vibe coding" (relying on AI coding assistants like Cursor, GitHub Copilot, or Claude to quickly generate and run project code) introduces new ways for secrets to leak. AI tools index your local files to build context and perform vector search, meaning they can easily read and transmit .env files to their model providers.
Here is how to stay safe:
1. Configure .gitignore First
Never create a .env file without immediately adding it to your .gitignore file.
# .gitignore
.env
*.creds
*.pem
.credential/
2. Implement AI-Specific Ignore Files
To prevent coding assistants from reading sensitive files or scraping configuration data, use AI-specific ignore files:
Cursor: Create a
.cursorignorefile in the root directory.GitHub Copilot: Use a
.copilotignorefile.
List the folders or config files you want the assistant to skip, using standard gitignore glob syntax. This prevents the assistant from scanning credentials and sending them in its LLM context window.
3. Store Configuration Outside the Workspace
If you are developing a project in D:\projects\my-app, do not store your secrets within D:\projects\my-app\.env.
Instead, configure your application to read configuration files from your user home configuration directory (e.g., ~/.config/my-app/config.json on Linux/Mac, or %APPDATA%\my-app\config.json on Windows). Because these directories are outside the project's root folder, local AI workspace indexing tools will not scan or index them.
4. Keep Permissions set to "Ask"
Never set your AI coding tool's file-write or terminal execution privileges to automatic or permissive by default. Always configure permissions to Ask before writing code or executing terminal processes, allowing you to catch any attempt to read, log, or transmit secret variables.
In some development workflows, you might choose to activate auto-execution mode—for example, by utilizing flags like --dangerously-skip-permissions in runtimes like antigravity. While this improves speed and developer flow, you must be fully aware of the consequences. Running an agent with skipped permissions gives the LLM complete authority to run arbitrary shell commands, read local files, and write modifications to your filesystem.
Conclusion
Securing developer secrets is not about creating complex systems; it is about establishing clean boundaries between your codebase and your environment configuration. By using registry-backed environment variables on Windows, avoiding command history leaks on Linux, locking down SSH keys and credential files to 600, and keeping secrets outside your AI indexing workspace, you can vibe code safely and confidently.
Thanks for reading. See you in the next lab.


