The first security question every agent user hits is also the one most users answer wrong: where do I put my API keys? The default answer is wrong. Most people paste the key into the Discord channel where the agent is listening, or commit a .env file to the Git repo, or hardcode it in a config script. Every one of those is a leak. The discipline this article teaches is simple: secrets live in ~/.openclaw/.env with chmod 600 permissions, the model is trained not to reveal them, and the file is in .gitignore from day one. The v2.26 release (cross-referenced in 9.2) adds a platform-native version of the same rule.

This article walks through the discipline, the verification, the platform-specific patterns (Notion, Discord, Telegram), the Git hygiene, and the incident-response flow when something does leak.

What you'll learn

  • The "Golden Rule" of the channel's security primer: never share API keys, tokens, or secrets in chat platforms (Discord, WhatsApp, Slack, Telegram), because even "I'll delete it later" leaks via caches, notification previews, screenshots, bot logs, and team-member access.
  • The right location is ~/.openclaw/.env with chmod 600 permissions — the model is trained not to reveal env vars, the OS protects the file at the user level, and the file is easy to .gitignore and easy to rotate.
  • The format is one KEY=value per line: NOTION_API_KEY=secret_abc..., DISCORD_BOT_TOKEN=..., TELEGRAM_BOT_TOKEN=1234567890:ABC..., plus your model API key (OPENAI_API_KEY, ANTHROPIC_API_KEY) and any third-party service (YOUTUBE_TRANSCRIPT_API_KEY, COINGECKO_API_KEY, TWITTER_API_KEY).
  • The platform-specific rotation flows: Notion "Regenerate" → update .envopenclaw gateway restart; Discord "Reset Token" in Developer Portal → update → restart; Telegram /revoke then /token via BotFather → update → restart.
  • The .gitignore block that protects you: .env, .env.local, .env.*.local, **/.env, plus the OpenClaw-specific .openclaw/.env and .openclaw/**/.env.
  • The incident response for a leaked key: revoke at source within 5 minutes, generate a new one, update .env, restart the gateway, audit logs within 24 hours, document the incident.

The Golden Rule: never share keys in chat

The first video in the syllabus (cross-listed with 9.2 and 9.3) is the channel's "your agent is acting stupid" primer. The .env discipline is item 1 of 4 in the "how to fix it" flow. The Golden Rule is unambiguous: never share API keys, tokens, or secrets in chat platforms like Discord, WhatsApp, Slack, or Telegram.

The reasoning is the part most users skip. Even if you plan to delete the message, the secret has already propagated to:

  • Platform caches — Discord, Slack, and Telegram all cache messages server-side, and the cache lifetime is rarely the same as your "delete" intent.
  • Notification previews — mobile notification previews show truncated message bodies, and screenshot automation routinely scrapes them.
  • Screenshots — every participant in the channel can screenshot before the delete propagates. The threat model is not "I trust my team," it is "I trust my team's screenshots."
  • Bot or integration logs — every other bot with read access to the channel has now seen the key. Some of those bots are third-party services you don't own.
  • Other team members — the channel is the wrong granularity. Pair-based sharing beats channel-based sharing for any secret.

The public.videos.summary_content for the video frames the four fixes as: (1) break down complex tasks, (2) provide API documentation first, (3) mandate testing at each step, (4) limit permissions. The .env discipline is part of (4) — limit the agent's blast radius by keeping secrets out of the surface area the agent can read or write.

Wrong vs right

# Wrong
Discord: "Hey team, here's the Notion API key: secret_abc123..."

# Right
Discord: "I've added the Notion integration. Each team member
should create their own integration at notion.so/my-integrations
and add it to their local .env file."

The "right" version puts the secret in ~/.openclaw/.env on each team member's machine, where the OS protects it at the user level and the model is trained not to reveal it.

Environment variables: why they work

The "why" matters because the discipline is a tax, and people skip taxes they don't understand. Five reasons env vars are the right home for secrets:

  1. AI models are trained not to reveal them. OpenClaw's model layer is trained to treat env-var contents as protected. The key never enters chat output unless you explicitly ask for it, and even then, the trained response is a refusal or a redaction.
  2. File permissions protect at the OS level. chmod 600 on the file means only your user can read or write it. Other users on a shared box — including the agent's runtime user, if you isolate it correctly — cannot read the file.
  3. Secrets stay separate from code and chat logs. The same secret can be referenced by ten different skills, five different integrations, and three different cron jobs, without ever appearing in a config file the agent edits.
  4. Version control is trivial to exclude. One .gitignore line protects you forever. The reverse — auditing a repo for leaked secrets — is hard.
  5. Easy rotation. Edit the file, restart the gateway, done. No code changes, no config-tree edits, no skill rewrites.

Setting up the file

The location is ~/.openclaw/.env, the permissions are chmod 600, and the editor is nano (because it's installed everywhere and doesn't try to do smart things with trailing whitespace).

# Create the directory if it doesn't exist
mkdir -p ~/.openclaw

# Create the .env file with restricted permissions
touch ~/.openclaw/.env
chmod 600 ~/.openclaw/.env

Edit with nano:

nano ~/.openclaw/.env

In nano: Ctrl + X to exit, Y to confirm save, Enter to confirm filename.

The format

One secret per line, in KEY=value format, with a comment per integration. The channel's recommended block:

# Notion Integration
NOTION_API_KEY=secret_abc123XYZ456def789

# Discord Bot
DISCORD_BOT_TOKEN=MTIzNDU2Nzg5MDEyMzQ1Njc4OQ.GhIjKl.MnOpQrStUvWxYzAbCdEfGhIjKlMnOpQrStUv

# Telegram Bot
TELEGRAM_BOT_TOKEN=1234567890:ABCdefGHIjklMNOpqrsTUVwxyz1234567890

# YouTube Transcripts API
YOUTUBE_TRANSCRIPT_API_KEY=yt_live_abc123def456ghi789

# Custom APIs
COINGECKO_API_KEY=CG-abc123def456ghi789jkl012
TWITTER_API_KEY=AAAAAAAAAAAAAAAAAAAAABcde

Model API keys live in the same file:

# Model provider
OPENAI_API_KEY=sk-...
ANTHROPIC_API_KEY=sk-ant-...

Verification

After creating the file, check the permissions:

ls -la ~/.openclaw/.env

The expected output:

-rw------- 1 username username 256 May 6 12:00 /home/username/.openclaw/.env

The -rw------- means only your user can read/write the file. If you see -rw-r--r-- (world-readable) or -rw-rw-r-- (group-readable), the file is unsafe — re-run chmod 600.

Platform-specific flows

Each platform has a different key-management UI, but the .env discipline is the same. The channel documents three of the most common.

Notion

  • Where to get the key: notion.so/my-integrations → create integration → copy "Internal Integration Secret."
  • Environment variable: NOTION_API_KEY=secret_your_key_here.
  • Permissions: use read-only if you only need data analysis; enable write for task management.
  • Rotation: click "Regenerate" in integration settings → update .envopenclaw gateway restart.

Discord

  • Where to get the key: discord.com/developers/applications → create application → Bot → Reset Token.
  • Environment variable: DISCORD_BOT_TOKEN=your_token_here.
  • Security settings: enable "Server Members Intent" and "Message Content Intent" before you save the bot page (the two intents have to be on before the token is generated, otherwise the bot will be online but unable to read messages). Use specific permissions, not Administrator, whenever possible.
  • Rotation: Reset Token in Developer Portal → update .env → restart gateway → bot reconnects automatically.

Telegram

  • Where to get the key: message @BotFather on Telegram → /newbot command → copy the token.
  • Environment variable: TELEGRAM_BOT_TOKEN=1234567890:ABCdefGHIjklMNOpqrsTUVwxyz.
  • Security settings: configure pairing policy (DM only, allowlist, etc.) → use pairing codes for new users → review paired users monthly.
  • Rotation: message @BotFather → /revoke/token → update .env → restart gateway.

Third-party APIs

The pattern is SERVICE_NAME_API_KEY=your_key_here. Common examples from the channel's coverage:

  • YOUTUBE_TRANSCRIPT_API_KEY — YouTube Transcripts API
  • COINGECKO_API_KEY — CoinGecko crypto data
  • OPENAI_API_KEY — OpenAI
  • ANTHROPIC_API_KEY — Anthropic Claude

Git and version control

The .gitignore block that protects you on day one:

# Environment variables
.env
.env.local
.env.*.local
**/.env

# OpenClaw specific
.openclaw/.env
.openclaw/**/.env

The **/.env pattern catches env files in subdirectories, which matters if you have multi-agent setups or per-skill configurations. The .openclaw/**/.env pattern is OpenClaw-specific and protects any .env file the agent creates inside its own directory tree.

Before every commit

# Check what will be committed
git status

# Search for potential secrets in staged files
git diff --cached | grep -i "api_key\|token\|secret\|password"

The grep is a last-line defence. If it returns anything, the commit is unsafe. Use --cached to scan only staged files, not the whole working tree.

If you accidentally commit secrets

Three steps, in order:

  1. Immediately rotate all exposed keys. This is the most important step. The commit is already public the moment it lands, regardless of what you do with Git history.
  2. Remove from Git history (only if the secret has never been public — which you cannot reliably know):
# Remove file from Git history (use with caution)
git filter-branch --force --index-filter \
  "git rm --cached --ignore-unmatch .env" \
  --prune-empty --tag-name-filter cat -- --all

# Force push (only if you're sure)
git push origin --force --all
  1. Better approach: treat the repo as compromised and rotate all secrets. The filter-branch rewrite is technically correct but practically leaky — every clone, every fork, every CI cache, every mirror has the secret. Rotation is the only durable fix.

Access control: principle of least privilege

The "principle of least privilege" — only grant the minimum permissions needed — is the same shape across every integration. The channel's reference table:

Use Case Notion Permissions Discord Permissions Telegram Policy
Data Analysis Read only N/A Read only
Task Management Read + Write Send messages, Read history DM pairing
Team Collaboration Read + Write Manage channels, Send messages Allowlist
Public Bot Read + Write Limited to specific channels Pairing codes

Monthly audit checklist

  • Review all active API integrations
  • Remove unused integrations
  • Check who has access to .env files
  • Verify bot permissions haven't expanded
  • Review paired Telegram users
  • Check Discord bot role assignments
  • Rotate keys for critical services

The discipline is a calendar event, not a memory event.

Incident response

Two scenarios, both with concrete time-bound steps.

If an API key is exposed

Immediate actions (within 5 minutes):

  1. Revoke the exposed key at the source (Notion, Discord, etc.)
  2. Generate a new key
  3. Update your .env file with the new key
  4. Restart the OpenClaw gateway: openclaw gateway restart

Follow-up actions (within 24 hours):

  1. Review logs for unauthorized access — look for API calls from IPs you don't recognise, calls at times you weren't active, and reads of resources you don't normally touch
  2. Check for unexpected changes in connected services
  3. Notify team members if it's a shared integration
  4. Document the incident and how it happened
  5. Update procedures to prevent recurrence

If the .env file is compromised

Immediate actions:

  1. Rotate ALL keys in the .env file
  2. Check system logs for unauthorized access:
    sudo grep "\.env" /var/log/auth.log
    
  3. Review recent file access:
    ls -lu ~/.openclaw/.env
    
  4. Change system passwords if needed

Follow-up actions:

  1. Enable 2FA on all integrated services
  2. Review SSH access logs
  3. Consider changing SSH keys
  4. Audit all connected services for suspicious activity

The 24-hour window is the channel's default. Anything longer than that and the blast radius starts to include compliance exposure (GDPR, HIPAA, etc., depending on your jurisdiction and your data).

Try it yourself

The hands-on goal: a defensible .env setup, on disk, with verification you can run on demand.

  1. Create the file with the right permissions. mkdir -p ~/.openclaw && touch ~/.openclaw/.env && chmod 600 ~/.openclaw/.env. Verify with ls -la ~/.openclaw/.env — the permissions should be -rw-------.
  2. Populate the file with your real keys. One per line, in KEY=value format. Add a comment per integration. Do not paste keys into a chat app or a web form to "save them somewhere first" — that's the leak.
  3. Add the .gitignore block. All four lines: .env, .env.local, .env.*.local, **/.env, plus the OpenClaw-specific lines. Verify with git check-ignore -v ~/.openclaw/.env — should print the matching pattern.
  4. Run the pre-commit scan. git diff --cached | grep -i "api_key\|token\|secret\|password". Should return nothing.
  5. Set the rotation reminder. Calendar event 90 days out titled "Rotate agent secrets." Quarterly rotation is the channel's default.
  6. Test the incident response. Pick one integration (Notion is the easiest). Revoke the key at source. Generate a new one. Update .env. Restart gateway. Verify the integration still works. The first time you do this under pressure is not the time to learn the flow.
  7. Run the monthly audit checklist. Do it once now to baseline, then calendar it monthly. Most users find at least one unused integration or one expanded permission on the first run.
  8. Document your .env schema. A short README in ~/.openclaw/ that lists which keys you expect to find, where to get them, and how to rotate them. The discipline scales only if the next person (or future-you) can recover from a clean box.

Common pitfalls

  • Pasting keys into Discord "just to test" — the chat-platform surface is the wrong surface. Use the nano flow or the platform's secret-management UI.
  • chmod 644 on the .env file — the default for touch on some systems is world-readable. Re-run chmod 600 explicitly. Verify with ls -la.
  • Pasting a fresh top-level object into a non-empty config — this is the JSON-parse gotcha from Course 4: Claude Code & AI Coding §4.2. It applies to settings.json and to any structured config the agent reads. Paste only the inner object and check the trailing comma.
  • Treating chmod 600 as a one-time setup — verify it after every cp, every mv, and every git checkout. Permissions are not sticky across copies.
  • Skipping the .gitignore — the default Git behaviour is to track every file in the working tree. The first commit is the leak; the .gitignore is the prevention.
  • Rotating one key and assuming the rest are safe — the blast radius of a .env leak is the whole file. If one key was in a screenshot, the other keys are compromised too. Rotate them all.
  • Trusting "I deleted the message" — Discord, Slack, and Telegram caches live longer than your delete intent. Notification previews have already fired. The team member has already screenshotted. The secret is out. Rotate.
  • Hardcoding secrets in config.py — the channel's anti-pattern #4. The fix is os.getenv("NOTION_API_KEY") and the same KEY=value env-var format.
  • Using the same key across team members — every team member should have their own integration. The discipline is per-user, not per-team.
  • Granting Administrator permission to a Discord bot "to make it work" — Administrator is a footgun, not a default. The channel's stance: use specific permissions, not Administrator. The fact that "Administrator" makes the bot work faster is a sign that the scope is wrong.
  • Forgetting to restart the gateway after a rotation — the new key is in .env, but the gateway is still using the old one in memory. openclaw gateway restart is the explicit handoff.

Sources