Why This Checklist Exists
Every AI coding tool ships code with the same security mistakes. We know because we audit the output professionally. After reviewing over 100 AI-generated codebases, the same 15 issues appear in nearly every one.
This checklist is the condensed version. Each item takes under 2 minutes to check. If you want the extended 25-point version with CI/CD integration scripts, grab the gated checklist here.
1. Hardcoded Secrets in Source Code
Check: Search your codebase for API keys, passwords and tokens.
Why: AI tools embed credentials inline to make features work immediately.
grep -rn "sk_live\|password\|secret\|API_KEY\|token" --include="*.js" --include="*.ts" --include="*.py" .
2. Hallucinated Dependencies
Check: Verify every package in your dependency file exists on the official registry.
Why: AI models invent package names. Attackers register those names with malicious code.
# npm
cat package.json | jq -r '.dependencies | keys[]' | xargs -I {} npm view {} name 2>&1 | grep "404"
# pip
cat requirements.txt | cut -d'=' -f1 | xargs -I {} pip index versions {} 2>&1 | grep "ERROR"
3. Missing Authorization Checks
Check: Log in as User A. Change a record ID in the URL. See if User B's data loads.
Why: AI builds authentication but almost never adds per-resource authorization.
# Express.js middleware example
const authorize = (req, res, next) => {
const resource = await Resource.findById(req.params.id);
if (resource.userId !== req.user.id) return res.status(403).json({ error: 'Forbidden' });
next();
};
4. Exposed .env File
Check: Visit yourdomain.com/.env in your browser.
Why: Default server configs serve all files from the project root, including .env.
# .htaccess
<FilesMatch "^\.env">
Order allow,deny
Deny from all
</FilesMatch>
5. SQL Injection via String Concatenation
Check: Search for string concatenation in database queries.
Why: AI uses template literals in queries because they are syntactically simpler.
# Bad (AI default)
db.query(`SELECT * FROM users WHERE id = ${userId}`)
# Good (parameterized)
db.query('SELECT * FROM users WHERE id = ?', [userId])
6. Weak Password Hashing
Check: Search for MD5, SHA-1 or SHA-256 in your auth code.
Why: AI defaults to fast hashes. Password hashing needs to be deliberately slow.
# Node.js with bcrypt
const bcrypt = require('bcrypt');
const hash = await bcrypt.hash(password, 12);
7. No Rate Limiting
Check: Send 100 login attempts in 10 seconds. See if any get blocked.
Why: AI never adds rate limiting unless you specifically ask for it.
# Express.js
const rateLimit = require('express-rate-limit');
app.use('/api/auth', rateLimit({ windowMs: 15 * 60 * 1000, max: 10 }));
8. Wildcard CORS
Check: Look for Access-Control-Allow-Origin: * in your server config or middleware.
Why: Wildcard CORS lets any website make authenticated requests to your API.
# Replace wildcard with explicit origins
app.use(cors({ origin: ['https://yourdomain.com'], credentials: true }));
9. Debug Mode in Production
Check: Trigger an error and see if a stack trace appears in the response.
Why: Debug output reveals file paths, database schemas and server configuration.
# Django
DEBUG = False # in production settings
# Express
app.set('env', 'production');
10. Unrestricted File Uploads
Check: Upload a .php or .js file through your upload form. See if the server executes it.
Why: AI accepts all file types by default. Executables in upload directories mean remote code execution.
const allowedTypes = ['image/jpeg', 'image/png', 'application/pdf'];
if (!allowedTypes.includes(file.mimetype)) return res.status(400).json({ error: 'Invalid file type' });
11. Broken Session Management
Check: Log out and try reusing the session token. Check if tokens have expiration times.
Why: AI creates tokens but forgets expiration, logout invalidation and secure cookie flags.
// JWT with expiration
jwt.sign(payload, secret, { expiresIn: '1h' });
// Secure cookie flags
res.cookie('session', token, { httpOnly: true, secure: true, sameSite: 'strict' });
12. Missing Input Validation
Check: Submit <script>alert(1)</script> in every text field. Check if it renders.
Why: AI trusts all input. XSS in stored data affects every user who views it.
const sanitizeHtml = require('sanitize-html');
const clean = sanitizeHtml(userInput, { allowedTags: [], allowedAttributes: {} });
13. Verbose Error Responses
Check: Send malformed data to API endpoints. Read the error response carefully.
Why: AI returns the raw error object, which often includes internal paths, query strings and stack frames.
// Generic error handler
app.use((err, req, res, next) => {
console.error(err); // log internally
res.status(500).json({ error: 'Internal server error' }); // generic response
});
14. Missing Security Headers
Check: Run curl -I yourdomain.com and look for security headers.
Why: AI never adds Content-Security-Policy, X-Frame-Options or other protective headers.
# Express.js with helmet
const helmet = require('helmet');
app.use(helmet());
15. Unprotected Admin Routes
Check: Navigate to /admin, /dashboard, /api/admin as a regular user.
Why: AI creates admin panels but does not restrict access by role.
const requireAdmin = (req, res, next) => {
if (req.user.role !== 'admin') return res.status(403).json({ error: 'Forbidden' });
next();
};
app.use('/admin', requireAdmin);
What This Checklist Does Not Cover
This list handles the obvious, repeatable issues. It does not cover business logic flaws, complex authorization models, third-party integration security or infrastructure configuration. Those require a professional assessment.
If you want the full 25-point checklist with automated scripts you can add to your CI/CD pipeline, download the extended version here. It includes checks for infrastructure, deployment and monitoring that go beyond application code.
Run these 15 checks after every major feature you build with AI. It takes 30 minutes and catches the vulnerabilities that show up in every single AI code audit we perform.