Home/Blog/Vulnerability Research
Vulnerability ResearchPublished · Updated ⚡ 15 min read

Stop Deploying AI Slop: The Gritty 25-Point Checklist You Actually Need

An exhaustive, no-nonsense DevSecOps guide to securing LLM-generated code before it blows up your production environment.

VG
Vladyslav Gusarov
DevSecOps Lead at Bryxe
The Ultimate AI Code Security Checklist: 25 Things to Verify Before Shipping AI-Generated Code [2026] [Audit]

Look, AI is writing half your codebase now. That's fine. It's fast, it gets the boilerplate out of the way. But let's stop pretending it knows what a secure architecture looks like. When you let an LLM vomit out a bunch of Node or Python and just YOLO it into prod, you're building a bomb. You want a breach? Keep blindly trusting the autocomplete.

This isn't theory. I've audited enough AI-generated slop this year to know exactly what it gets wrong. It hardcodes secrets. It invents APIs that don't exist. It completely ignores SSRF protections. Bottom line: if you don't verify what the bot wrote, you're the one on the hook when the ransomware hits.

Here is the ultimate AI code security checklist. 25 things you absolutely must check before that pull request gets merged.

Authentication & Authorization (The Front Door)

The AI loves to build custom auth. Never let it.

1. Hardcoded Credentials

AI will just drop API keys in plain text. Nuke it.

pythonSource Code
# Bad
api_key = "sk-live-12345"
# Good
import os
api_key = os.environ.get("API_KEY")

2. Broken JWT Validation

It skips signature verification because it's lazy.

javascriptSource Code
// Bad
const payload = jwt.decode(token);
// Good
const payload = jwt.verify(token, process.env.JWT_SECRET, { algorithms: ['HS256'] });

3. Missing Role-Based Access Control

AI endpoints default to anyone with a token.

pythonSource Code
# Bad
@app.route('/admin/delete')
def delete_user():
# Good
@app.route('/admin/delete')
@require_role('ADMIN')
def delete_user():

4. Weak Password Hashing

MD5 is dead. Tell the AI to stop using it.

pythonSource Code
# Bad
hash = hashlib.md5(password).hexdigest()
# Good
hash = bcrypt.hashpw(password.encode(), bcrypt.gensalt())

5. Insecure Direct Object Reference (IDOR)

Just because they know the ID doesn't mean they own the record.

javascriptSource Code
// Bad
db.users.find({ id: req.params.id })
// Good
db.users.find({ id: req.params.id, owner_id: req.user.id })

Input Validation (Trust Nothing)

Look, I've seen this a hundred times. LLMs assume users are nice. Users are not nice.

6. SQL Injection

Yes, AI still writes raw SQL strings in 2026.

javascriptSource Code
// Bad
db.execute(`SELECT * FROM users WHERE name = '${req.body.name}'`);
// Good
db.execute('SELECT * FROM users WHERE name = ?', [req.body.name]);

7. Cross-Site Scripting (XSS)

React usually saves you, but dangerouslySetInnerHTML is the AI's favorite footgun.

javascriptSource Code
// Bad
<div dangerouslySetInnerHTML={{ __html: userInput }} />
// Good
import DOMPurify from 'dompurify';
<div dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(userInput) }} />

8. Command Injection

Don't let user input touch a shell.

pythonSource Code
# Bad
os.system(f"ping {user_ip}")
# Good
subprocess.run(["ping", "-c", "4", user_ip], check=True)

9. Server-Side Request Forgery (SSRF)

AI will just fetch whatever URL the user gives it.

pythonSource Code
# Bad
requests.get(user_provided_url)
# Good
if is_safe_url(user_provided_url):
    requests.get(user_provided_url, timeout=5)

10. Path Traversal

Stop letting them read /etc/passwd.

javascriptSource Code
// Bad
fs.readFile(path.join(__dirname, req.query.file));
// Good
const safePath = path.resolve(__dirname, 'public', path.basename(req.query.file));

Data Protection (Stop Leaking)

11. Plaintext PII

Encrypt social security numbers, emails, whatever.

pythonSource Code
# Bad
db.save({"ssn": user_ssn})
# Good
db.save({"ssn": encrypt_kms(user_ssn)})

12. Verbose Error Messages

Don't spit stack traces to the frontend.

javascriptSource Code
// Bad
res.status(500).send(err.stack);
// Good
res.status(500).send("Internal Server Error");

13. Logging Secrets

AI loves console.log(req.body).

javascriptSource Code
// Bad
console.log("User config:", config);
// Good
const safeConfig = omit(config, ['password', 'token']);
console.log("User config:", safeConfig);

14. Insecure Randomness

Math.random() is not for crypto.

javascriptSource Code
// Bad
const resetToken = Math.random().toString(36);
// Good
const resetToken = crypto.randomBytes(32).toString('hex');

15. Missing Security Headers

Add HSTS, CSP, the works.

javascriptSource Code
// Bad
app.use(cors());
// Good
const helmet = require('helmet');
app.use(helmet());

API & Network Security (Close the Holes)

16. No Rate Limiting

APIs without rate limits are just DDoS targets.

javascriptSource Code
// Bad
app.post('/login', loginHandler);
// Good
const limiter = rateLimit({ windowMs: 15 * 60 * 1000, max: 100 });
app.post('/login', limiter, loginHandler);

17. Unsafe Deserialization

Pickle and YAML are loaded weapons.

pythonSource Code
# Bad
data = yaml.load(user_input)
# Good
data = yaml.safe_load(user_input)

18. Permissive CORS

* is not an acceptable origin.

javascriptSource Code
// Bad
app.use(cors({ origin: '*' }));
// Good
app.use(cors({ origin: 'https://myapp.com' }));

19. Cleartext Protocols

Force TLS everywhere.

pythonSource Code
# Bad
url = "http://api.internal.svc"
# Good
url = "https://api.internal.svc"

20. GraphQL Introspection

Turn it off in prod or get scraped.

javascriptSource Code
// Bad
const server = new ApolloServer({ typeDefs, resolvers });
// Good
const server = new ApolloServer({ typeDefs, resolvers, introspection: false });

Infrastructure & Deployment (Lock It Down)

21. Overprivileged Containers

Root in Docker is a bad joke.

dockerfileSource Code
# Bad
USER root
# Good
USER appuser

22. Outdated Base Images

Stop pulling node:latest.

dockerfileSource Code
# Bad
FROM python:3
# Good
FROM python:3.11-slim@sha256:abcd...

23. Hardcoded Cloud Perms

AI will write Action: "*" in IAM policies.

jsonSource Code
// Bad
{"Effect": "Allow", "Action": "s3:*", "Resource": "*"}
// Good
{"Effect": "Allow", "Action": ["s3:GetObject"], "Resource": "arn:aws:s3:::my-bucket/*"}

24. Exposed Debug Ports

Don't bind debugging to 0.0.0.0.

jsonSource Code
// Bad
"start": "node --inspect=0.0.0.0 index.js"
// Good
"start": "node index.js"

25. Missing Dependency Pins

Yarn or NPM, pin the exact versions.

jsonSource Code
// Bad
"express": "^4.0.0"
// Good
"express": "4.18.2"

Stop Doing This By Hand

Look, you can run through this AI code security checklist manually for every PR, but that's a waste of engineering hours. Bryxe automates all 25 of these checks directly in your CI pipeline. It scans the LLM output, flags the janky code, and enforces actual DevSecOps standards before anything gets shipped to prod. Stop trusting the bot and start verifying the bits.

AUTOMATED DEFENSE

Don't wait for an exploit to audit your codebase

Review supported code risks, exposed secrets and dependency findings with Bryxe Shield. Verify the fixes in your application before release.

Need a practical next step? Explore the security field guides or read our editorial and sourcing policy.

Recommended Security Research