From 23db1259711fd4e42059d55340fa74a54f72cd45 Mon Sep 17 00:00:00 2001 From: Chummy Date: Tue, 17 Feb 2026 18:25:23 +0800 Subject: [PATCH] docs(security): refine local secret management guidance Supersedes: #406 Co-authored-by: Gabriel Nahum --- .env.example | 59 ++++++++++++++++++++++++----- .githooks/pre-commit | 8 ++++ .gitignore | 13 ++++++- CONTRIBUTING.md | 88 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 157 insertions(+), 11 deletions(-) create mode 100755 .githooks/pre-commit diff --git a/.env.example b/.env.example index 17686d3..6fd6fc6 100644 --- a/.env.example +++ b/.env.example @@ -1,26 +1,65 @@ # ZeroClaw Environment Variables -# Copy this file to .env and fill in your values. -# NEVER commit .env — it is listed in .gitignore. +# Copy this file to `.env` and fill in your local values. +# Never commit `.env` or any real secrets. -# ── Required ────────────────────────────────────────────────── -# Your LLM provider API key -# ZEROCLAW_API_KEY=sk-your-key-here +# ── Core Runtime ────────────────────────────────────────────── +# Provider key resolution at runtime: +# 1) explicit key passed from config/CLI +# 2) provider-specific env var (OPENROUTER_API_KEY, OPENAI_API_KEY, ...) +# 3) generic fallback env vars below + +# Generic fallback API key (used when provider-specific key is absent) API_KEY=your-api-key-here +# ZEROCLAW_API_KEY=your-api-key-here -# ── Provider & Model ───────────────────────────────────────── -# LLM provider: openrouter, openai, anthropic, ollama, glm +# Default provider/model (can be overridden by CLI flags) PROVIDER=openrouter +# ZEROCLAW_PROVIDER=openrouter # ZEROCLAW_MODEL=anthropic/claude-sonnet-4-20250514 # ZEROCLAW_TEMPERATURE=0.7 +# Workspace directory override +# ZEROCLAW_WORKSPACE=/path/to/workspace + +# ── Provider-Specific API Keys ──────────────────────────────── +# OpenRouter +# OPENROUTER_API_KEY=sk-or-v1-... + +# Anthropic +# ANTHROPIC_OAUTH_TOKEN=... +# ANTHROPIC_API_KEY=sk-ant-... + +# OpenAI / Gemini +# OPENAI_API_KEY=sk-... +# GEMINI_API_KEY=... +# GOOGLE_API_KEY=... + +# Other supported providers +# VENICE_API_KEY=... +# GROQ_API_KEY=... +# MISTRAL_API_KEY=... +# DEEPSEEK_API_KEY=... +# XAI_API_KEY=... +# TOGETHER_API_KEY=... +# FIREWORKS_API_KEY=... +# PERPLEXITY_API_KEY=... +# COHERE_API_KEY=... +# MOONSHOT_API_KEY=... +# GLM_API_KEY=... +# MINIMAX_API_KEY=... +# QIANFAN_API_KEY=... +# DASHSCOPE_API_KEY=... +# ZAI_API_KEY=... +# SYNTHETIC_API_KEY=... +# OPENCODE_API_KEY=... +# VERCEL_API_KEY=... +# CLOUDFLARE_API_KEY=... + # ── Gateway ────────────────────────────────────────────────── # ZEROCLAW_GATEWAY_PORT=3000 # ZEROCLAW_GATEWAY_HOST=127.0.0.1 # ZEROCLAW_ALLOW_PUBLIC_BIND=false -# ── Workspace ──────────────────────────────────────────────── -# ZEROCLAW_WORKSPACE=/path/to/workspace - # ── Docker Compose ─────────────────────────────────────────── # Host port mapping (used by docker-compose.yml) # HOST_PORT=3000 diff --git a/.githooks/pre-commit b/.githooks/pre-commit new file mode 100755 index 0000000..d162ba3 --- /dev/null +++ b/.githooks/pre-commit @@ -0,0 +1,8 @@ +#!/usr/bin/env bash +set -euo pipefail + +if command -v gitleaks >/dev/null 2>&1; then + gitleaks protect --staged --redact +else + echo "warning: gitleaks not found; skipping staged secret scan" >&2 +fi diff --git a/.gitignore b/.gitignore index 49980c2..e5fbf74 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,17 @@ firmware/*/target *.db-journal .DS_Store .wt-pr37/ -.env __pycache__/ *.pyc +docker-compose.override.yml + +# Environment files (may contain secrets) +.env +.env.local +.env.*.local + +# Secret keys and credentials +.secret_key +*.key +*.pem +credentials.json diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a25ad4e..d98a2ce 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -79,6 +79,94 @@ git push --no-verify > **Note:** CI runs the same checks, so skipped hooks will be caught on the PR. +## Local Secret Management (Required) + +ZeroClaw supports layered secret management for local development and CI hygiene. + +### Secret Storage Options + +1. **Environment variables** (recommended for local development) + - Copy `.env.example` to `.env` and fill in values + - `.env` files are Git-ignored and should stay local + - Best for temporary/local API keys + +2. **Config file** (`~/.zeroclaw/config.toml`) + - Persistent setup for long-term use + - When `secrets.encrypt = true` (default), secret values are encrypted before save + - Secret key is stored at `~/.zeroclaw/.secret_key` with restricted permissions + - Use `zeroclaw onboard` for guided setup + +### Runtime Resolution Rules + +API key resolution follows this order: + +1. Explicit key passed from config/CLI +2. Provider-specific env vars (`OPENROUTER_API_KEY`, `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, ...) +3. Generic env vars (`ZEROCLAW_API_KEY`, `API_KEY`) + +Provider/model config overrides: + +- `ZEROCLAW_PROVIDER` / `PROVIDER` +- `ZEROCLAW_MODEL` + +See `.env.example` for practical examples and currently supported provider key env vars. + +### Pre-Commit Secret Hygiene (Mandatory) + +Before every commit, verify: + +- [ ] No `.env` files are staged (`.env.example` only) +- [ ] No raw API keys/tokens in code, tests, fixtures, examples, logs, or commit messages +- [ ] No credentials in debug output or error payloads +- [ ] `git diff --cached` has no accidental secret-like strings + +Quick local audit: + +```bash +# Search staged diff for common secret markers +git diff --cached | grep -iE '(api[_-]?key|secret|token|password|bearer|sk-)' + +# Confirm no .env file is staged +git status --short | grep -E '\.env$' +``` + +### Optional Local Secret Scanning + +For extra guardrails, install one of: + +- **gitleaks**: [GitHub - gitleaks/gitleaks](https://github.com/gitleaks/gitleaks) +- **truffleHog**: [GitHub - trufflesecurity/trufflehog](https://github.com/trufflesecurity/trufflehog) +- **git-secrets**: [GitHub - awslabs/git-secrets](https://github.com/awslabs/git-secrets) + +This repo includes `.githooks/pre-commit` to run `gitleaks protect --staged --redact` when gitleaks is installed. + +Enable hooks with: + +```bash +git config core.hooksPath .githooks +``` + +If gitleaks is not installed, the pre-commit hook prints a warning and continues. + +### What Must Never Be Committed + +- `.env` files (use `.env.example` only) +- API keys, tokens, passwords, or credentials (plain or encrypted) +- OAuth tokens or session identifiers +- Webhook signing secrets +- `~/.zeroclaw/.secret_key` or similar key files +- Personal identifiers or real user data in tests/fixtures + +### If a Secret Is Committed Accidentally + +1. Revoke/rotate the credential immediately +2. Do not rely only on `git revert` (history still contains the secret) +3. Purge history with `git filter-repo` or BFG +4. Force-push cleaned history (coordinate with maintainers) +5. Ensure the leaked value is removed from PR/issue/discussion/comment history + +Reference: [GitHub guide: removing sensitive data from a repository](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/removing-sensitive-data-from-a-repository) + ## Collaboration Tracks (Risk-Based) To keep review throughput high without lowering quality, every PR should map to one track: