* docs(#4440): stop telling agents to grep .env files the secret guard denies verification-patterns.md's <environment_config> and user-setup.md's three per-service Verification examples documented reading .env/.env.local directly via grep. Every covered runtime's secret-read guard denies that (Claude Code deny-rules since #768/v1.4.0; the always-on gsd-secret-read-guard hook since #4236/#4221 in 1.13.0) -- verified by piping each documented command through the shipped hook. verification-patterns.md now checks the environment (printenv) instead of the file, with a case statement replacing a broken grep -v alternation (grep's BRE `|` is literal, so the old placeholder filter matched nothing -- PLACEHOLDER/TODO_fill values passed the "substantive" check as real). Verified under sh (dash) against real/placeholder/empty/ unset values. Existence check ([ -f ".env" ] || [ -f ".env.local" ]) is untouched -- it was never denied. user-setup.md's three grep <SERVICE> .env.local lines are removed outright rather than swapped for printenv: those examples describe a Next.js shape where the framework loads .env.local at runtime without exporting it to the shell, so a printenv substitute would wrongly report "not set" on a correctly configured project. Each block's existing service-level check (build/webhook/connection/email test) already verifies the setup. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * docs(#4440): changeset for the secret-guard verification-examples fix Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * docs(#4440): backfill changeset PR number Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> --------- Co-authored-by: sim <sim@local> Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
5
.changeset/quick-bears-tumble.md
Normal file
5
.changeset/quick-bears-tumble.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
type: Fixed
|
||||
pr: 4500
|
||||
---
|
||||
**Verification examples no longer tell agents to grep .env files** — `verification-patterns.md` and `user-setup.md` documented reading `.env`/`.env.local` directly to verify environment variables, which every covered runtime's secret-read guard denies. The environment-variable checks now read the environment (`printenv`) instead of the file, and a broken placeholder-filter regex (`grep -v "a|b|c"`, where `|` is a literal BRE character) is replaced with a working case-insensitive check. (#4440)
|
||||
@@ -309,14 +309,17 @@ grep -r "$hook_name()" src/ --include="*.tsx" --include="*.ts" | grep -v "$hook_
|
||||
# .env file exists
|
||||
[ -f ".env" ] || [ -f ".env.local" ]
|
||||
|
||||
# Required variable is defined
|
||||
grep -E "^$VAR_NAME=" .env .env.local 2>/dev/null
|
||||
# Required variable is defined (in the environment: dotenv/direnv/the framework has loaded it)
|
||||
printenv "$VAR_NAME" >/dev/null
|
||||
```
|
||||
|
||||
**Substantive check:**
|
||||
```bash
|
||||
# Variable has actual value (not placeholder)
|
||||
grep -E "^$VAR_NAME=.+" .env .env.local 2>/dev/null | grep -v "your-.*-here|xxx|placeholder|TODO" -i
|
||||
# Variable has an actual value (not a placeholder) -- tests the shape, never prints the value;
|
||||
# exit 0 = real value, exit 1 = missing or placeholder (case-insensitive)
|
||||
v=$(printenv "$VAR_NAME"); case "$(printf %s "$v" | tr '[:upper:]' '[:lower:]')" in
|
||||
""|*your-*-here*|*xxx*|*placeholder*|*todo*) exit 1;;
|
||||
esac
|
||||
|
||||
# Value looks valid for type:
|
||||
# - URLs should start with http
|
||||
@@ -324,6 +327,16 @@ grep -E "^$VAR_NAME=.+" .env .env.local 2>/dev/null | grep -v "your-.*-here|xxx|
|
||||
# - Booleans should be true/false
|
||||
```
|
||||
|
||||
When the variable is not present in the agent's own environment (a framework that loads
|
||||
`.env.local` itself at runtime does not export it to the shell that runs these checks),
|
||||
ask the user to confirm it is set rather than reading `.env` directly. Variable NAMES can
|
||||
still be checked against `.env.example`, which the secret-read guard exempts from its
|
||||
protected-file patterns.
|
||||
|
||||
One guard-matching note worth knowing when auditing docs for `.env` mentions: the guard
|
||||
treats a grep PATTERN whose last path segment is a secret file name as a file operand, so
|
||||
`grep -n "\.env" file.md` is denied while `grep -n "\.env\b" file.md` is allowed.
|
||||
|
||||
**Stub patterns specific to env:**
|
||||
```bash
|
||||
# RED FLAGS - These are stubs:
|
||||
|
||||
@@ -171,9 +171,6 @@ Use the webhook signing secret from CLI output (starts with `whsec_`).
|
||||
After completing setup:
|
||||
|
||||
```bash
|
||||
# Check env vars are set
|
||||
grep STRIPE .env.local
|
||||
|
||||
# Verify build passes
|
||||
npm run build
|
||||
|
||||
@@ -232,9 +229,6 @@ Complete these items for Supabase Auth to function.
|
||||
After completing setup:
|
||||
|
||||
```bash
|
||||
# Check env vars
|
||||
grep SUPABASE .env.local
|
||||
|
||||
# Verify connection (run in project directory)
|
||||
npx supabase status
|
||||
```
|
||||
@@ -285,9 +279,6 @@ Complete these items for SendGrid email to function.
|
||||
After completing setup:
|
||||
|
||||
```bash
|
||||
# Check env var
|
||||
grep SENDGRID .env.local
|
||||
|
||||
# Test email sending (replace with your test email)
|
||||
curl -X POST http://localhost:3000/api/test-email \
|
||||
-H "Content-Type: application/json" \
|
||||
|
||||
Reference in New Issue
Block a user