Scenario
A developer used GitHub Copilot to generate a Node.js authentication module. The AI-generated code hardcoded credentials that were committed and pushed before anyone noticed.// auth/config.js — generated by AI assistant
const config = {
jwtSecret: 'supersecret', // CRITICAL: predictable JWT secret
awsKey: 'AKIAIOSFODNN7EXAMPLE', // CRITICAL: AWS access key
awsSecret: 'wJalrXUtnFEMI/K7...', // HIGH: hardcoded AWS secret
dbPassword: 'admin123', // HIGH: hardcoded password
sessionDuration: '365d', // HIGH: year-long sessions
};
// Store JWT in localStorage after login
localStorage.setItem('auth_jwt', generateToken(user)); // HIGH: XSS exposure
Detection
zenveil scan repo .
╭──────────────────────────────────────────────────────────────────────╮
│ ZenVeil Security Scan │
│ Target: /home/user/node-auth · Scanners: secrets, supply_chain │
│ Duration: 1.2s │
╰──────────────────────────────────────────────────────────────────────╯
┌──────────┬──────────┬──────────┬────────────────────────────────────────┬──────────────────────────┐
│ ID │ Severity │ Scanner │ Title │ Location │
├──────────┼──────────┼──────────┼────────────────────────────────────────┼──────────────────────────┤
│ ZG-A1B2 │ CRITICAL │ secrets │ AWS access key │ auth/config.js:4 │
│ ZG-C3D4 │ CRITICAL │ secrets │ Predictable JWT signing secret │ auth/config.js:3 │
│ ZG-E5F6 │ HIGH │ secrets │ Hardcoded API key assignment │ auth/config.js:5 │
│ ZG-G7H8 │ HIGH │ secrets │ Hardcoded password assignment │ auth/config.js:6 │
│ ZG-I9J0 │ HIGH │ secrets │ Token stored in browser storage │ auth/login.js:47 │
│ ZG-K1L2 │ HIGH │ secrets │ Long-lived session token │ auth/config.js:7 │
└──────────┴──────────┴──────────┴────────────────────────────────────────┴──────────────────────────┘
6 finding(s) · CRITICAL: 2 · HIGH: 4
Exiting with code 1 (CRITICAL/HIGH findings present)
Triage
zenveil triage
Triaging 6 finding(s)…
PRIORITY ORDER (highest risk first)
════════════════════════════════════
1. ZG-A1B2 — AWS access key [CRITICAL]
⚠ IMMEDIATE ACTION REQUIRED
An active AWS access key in source code is a live credential exposure.
Automated bots scan GitHub continuously for this exact pattern (AKIA prefix).
If this was ever pushed to a remote repository, assume it's compromised.
Effort: 15 minutes
Action:
1. Revoke at https://console.aws.amazon.com/iam → Users → Security credentials
2. git rm --cached auth/config.js
3. git filter-branch or BFG to purge from history if committed
4. Replace with: process.env.AWS_ACCESS_KEY_ID
2. ZG-C3D4 — Predictable JWT signing secret [CRITICAL]
Any JWT signed with 'supersecret' can be forged by an attacker.
Run: node -e "require('jsonwebtoken').sign({admin:true}, 'supersecret')"
→ Any attacker can mint admin tokens.
Effort: 30 minutes (must invalidate all existing sessions)
Action: Replace with crypto.randomBytes(64).toString('hex'), store in secrets manager
[... continues for all 6 findings ...]
AI explanation
zenveil explain ZG-A1B2
Explaining ZG-A1B2: AWS access key
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
What this is:
An AWS access key starting with 'AKIA' was found committed at
auth/config.js:4. This is a live AWS credential — the AKIA prefix
is a signature that AWS uses for long-lived access keys.
Why it's critical:
AWS access keys have no expiry by default and grant API-level access
to every AWS service the associated IAM user can access. Within minutes
of being committed to a public or semi-public repository, automated
scanners (GitGuardian, TruffleHog, and numerous threat actor tools)
will find and test this key.
Real-world consequence:
In 2023, a startup's AWS bill jumped from $10/month to $49,000 in 48
hours after an access key was committed to GitHub. The attacker spun up
GPU instances for crypto mining. AWS may not waive these charges.
OWASP: A02:2021 — Cryptographic Failures
Confidence: 95%
Auto-fix: secret redaction PR
zenveil fix ZG-A1B2 --auto-pr --repo owner/node-auth
Applying redaction directly (no API key needed).
Opened pull request: https://github.com/owner/node-auth/pull/23
PR title: [ZenVeil] Redact AWS access key (ZG-A1B2)
PR description:
ZenVeil detected an AWS access key at auth/config.js:4.
This PR redacts the value with <REDACTED_AWS_ACCESS_KEY>.
IMPORTANT: The key must also be revoked in the AWS IAM console:
https://console.aws.amazon.com/iam
Finding ID: ZG-A1B2 · Severity: CRITICAL · OWASP: A02:2021
- awsKey: 'AKIAIOSFODNN7EXAMPLE',
+ awsKey: '<REDACTED_AWS_ACCESS_KEY>',
Fix: JWT secret (with AI)
zenveil fix ZG-C3D4
Generating fix for ZG-C3D4: Predictable JWT signing secret
The JWT signing secret 'supersecret' at auth/config.js:3 is trivially
guessable. Any attacker who knows you're using JWT can forge tokens.
Here's the fix:
**Step 1: Generate a strong secret**
```bash
node -e "console.log(require('crypto').randomBytes(64).toString('hex'))"
# → a3f2b8c1d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1
# .env (never commit this)
JWT_SECRET=a3f2b8c1d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1
const config = {
jwtSecret: process.env.JWT_SECRET, // Load from environment
// ... other config
};
// Validate at startup
if (!config.jwtSecret || config.jwtSecret.length < 32) {
throw new Error('JWT_SECRET must be at least 32 characters');
}
## Final state after remediation
After applying all fixes:
```javascript
// auth/config.js — after remediation
const config = {
jwtSecret: process.env.JWT_SECRET, // Strong, from env
awsAccessKeyId: process.env.AWS_ACCESS_KEY_ID, // From env/secrets manager
awsSecretKey: process.env.AWS_SECRET_ACCESS_KEY,
dbPassword: process.env.DB_PASSWORD, // From env
sessionDuration: '1h', // Reasonable lifetime
};
// auth/login.js — after remediation
// Removed: localStorage.setItem('auth_jwt', token)
// Replaced with server-side httpOnly cookie:
res.cookie('session', token, {
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
sameSite: 'strict',
maxAge: 3600000,
});
zenveil scan repo .
# ✓ No findings. Exiting with code 0.