env-config-validator — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited env-config-validator (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Before generating any output, read config/defaults.md and adapt all patterns, imports, and code examples to the user's configured stack.
.env file (and .env.local, .env.development, .env.production if they exist).process.env.* and import.meta.env.* references..env.example and optionally a typed env validation schema.Scan all .ts, .tsx, .js, .jsx files for process.env.VARIABLE_NAME patterns. Flag any variable referenced in code but absent from .env.
🔴 MISSING: DATABASE_URL
Referenced in: lib/prisma.ts:3, lib/db.ts:7
Not defined in any .env file
🔴 MISSING: NEXTAUTH_SECRET
Referenced in: lib/auth.ts:12
Not defined in any .env fileVariables defined in .env but never referenced in code.
🟡 UNUSED: LEGACY_API_URL
Defined in: .env:14
No references found in codebaseExclude from this check: variables used by frameworks implicitly (e.g., PORT, NODE_ENV, HOSTNAME, NEXT_PUBLIC_* referenced in client code).
🟡 EMPTY: SMTP_HOST=
Defined in: .env:22
Variable exists but has no value🔴 DUPLICATE: NEXT_PUBLIC_API_URL
Line 5: NEXT_PUBLIC_API_URL=https://api.example.com
Line 18: NEXT_PUBLIC_API_URL=https://staging.example.com
Last definition wins — likely unintentional🟡 FORMAT: PORT=three thousand
Expected: numeric value
Suggested: PORT=3000
🟡 FORMAT: DEBUG=yes
Expected: boolean-like value (true/false, 1/0)
Suggested: DEBUG=trueFlag variables that appear to contain real secrets (not placeholders):
🔴 SECRET EXPOSED: STRIPE_SECRET_KEY=sk_live_abc123...
This looks like a real API key. Ensure .env is in .gitignore.
🔴 SECRET EXPOSED: DATABASE_URL=postgresql://admin:realpassword@prod-db:5432/app
Connection string contains credentials.Check that .gitignore includes .env and .env.local. Warn if it does not.
Produce a .env.example file with all required variables, replacing real values with descriptive placeholders.
# Database
DATABASE_URL="postgresql://user:password@localhost:5432/dbname"
# Authentication (generate with: openssl rand -base64 32)
NEXTAUTH_SECRET="your-nextauth-secret-here"
NEXTAUTH_URL="http://localhost:3000"
# External APIs
STRIPE_SECRET_KEY="sk_test_..."
STRIPE_PUBLISHABLE_KEY="pk_test_..."
# Email
SMTP_HOST="smtp.example.com"
SMTP_PORT="587"
SMTP_USER="[email protected]"
SMTP_PASS="your-smtp-password"
# Public (exposed to browser)
NEXT_PUBLIC_API_URL="http://localhost:3000/api"
NEXT_PUBLIC_APP_NAME="My App"Rules for placeholder generation:
http://localhost:* or https://example.comyour-*-here or the service's test key prefix (e.g., sk_test_...)true or false3000 for PORT)protocol://user:password@localhost:port/dbname// env.ts
import { createEnv } from "@t3-oss/env-nextjs";
import { z } from "zod";
export const env = createEnv({
server: {
DATABASE_URL: z.string().url(),
NEXTAUTH_SECRET: z.string().min(1),
NEXTAUTH_URL: z.string().url().optional(),
STRIPE_SECRET_KEY: z.string().startsWith("sk_"),
SMTP_HOST: z.string().min(1),
SMTP_PORT: z.coerce.number().int().min(1).max(65535),
SMTP_USER: z.string().email(),
SMTP_PASS: z.string().min(1),
NODE_ENV: z.enum(["development", "test", "production"]).default("development"),
},
client: {
NEXT_PUBLIC_API_URL: z.string().url(),
NEXT_PUBLIC_APP_NAME: z.string().min(1),
},
runtimeEnv: {
DATABASE_URL: process.env.DATABASE_URL,
NEXTAUTH_SECRET: process.env.NEXTAUTH_SECRET,
NEXTAUTH_URL: process.env.NEXTAUTH_URL,
STRIPE_SECRET_KEY: process.env.STRIPE_SECRET_KEY,
SMTP_HOST: process.env.SMTP_HOST,
SMTP_PORT: process.env.SMTP_PORT,
SMTP_USER: process.env.SMTP_USER,
SMTP_PASS: process.env.SMTP_PASS,
NODE_ENV: process.env.NODE_ENV,
NEXT_PUBLIC_API_URL: process.env.NEXT_PUBLIC_API_URL,
NEXT_PUBLIC_APP_NAME: process.env.NEXT_PUBLIC_APP_NAME,
},
});// env.ts
import { z } from "zod";
const envSchema = z.object({
DATABASE_URL: z.string().url(),
PORT: z.coerce.number().int().default(3000),
NODE_ENV: z.enum(["development", "test", "production"]).default("development"),
API_KEY: z.string().min(1),
});
export const env = envSchema.parse(process.env);
export type Env = z.infer<typeof envSchema>;Flag variables that don't follow standard prefixes:
| Prefix | Purpose |
|---|---|
DATABASE_ | Database configuration |
NEXT_PUBLIC_ | Client-exposed variables (Next.js) |
NEXTAUTH_ | NextAuth.js / Auth.js configuration |
AUTH_ | Authentication-related |
SMTP_ / EMAIL_ | Email service |
STRIPE_ / PAYMENT_ | Payment provider |
AWS_ / S3_ | AWS services |
REDIS_ | Redis configuration |
🔵 NAMING: apiKey
Convention: use SCREAMING_SNAKE_CASE with descriptive prefix
Suggested: EXTERNAL_API_KEY## Env Validation Report
### Summary
| Category | Count |
|----------|-------|
| 🔴 Missing | N |
| 🔴 Security | N |
| 🟡 Unused | N |
| 🟡 Format | N |
| 🔵 Naming | N |
### Findings
[Grouped by severity, each with file location and recommendation]
### Generated Files
- `.env.example` — [created/updated]
- `env.ts` — [created/updated] (typed validation schema)After identifying issues, automatically generate: (1) an updated .env.example with all missing variables added with placeholder values, (2) a typed env schema file using the configured validation library. Ask the user before overwriting existing files.
See references/env-patterns.md for T3 env setup details and common variable catalogs.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.