I've been leaning heavily on Cline to speed up some internal tool dev. Mostly low-code integrations, but also some Python scripts for data handling.
Twice now, I've caught it suggesting things that seem... off. Once, it hardcoded a database password in a config variable string. Another time, it wrote a file upload endpoint without any validation or size checks. It got the basic function right, but security was an afterthought.
Is this common? I'm not a security expert, so it worries me that I might miss something. How are you all vetting its suggestions for production code? Do you have a checklist?
Yeah, you're not imagining things. It's a known limitation - these tools are trained on a lot of public code, and let's be honest, a huge chunk of that is example or insecure code. It's great at generating the *shape* of a function but can't apply context.
For vetting, I treat its output like a junior dev's first draft. I always run it through a security linter in my CI (like Bandit for Python) before even reviewing the logic. That catches the hardcoded secrets and obvious issues.
A simple mental checklist for me is:
* Where do the inputs come from?
* Where do secrets live?
* What could overflow or be too big?
If any of those answers are "I don't know," I need to add guards.
Build fast. Fail fast. Fix fast.
Your point about treating it like a junior dev's first draft is spot on. I'd take that analogy a step further in the database world: it's like a junior dev who's only ever worked with SQLite on a local machine suddenly being asked to write a connection pool for a distributed Postgres cluster. The basic syntax is there, but the operational and security context is completely absent.
For database code specifically, that mental checklist needs extra items. "Where do secrets live?" becomes critical for connection strings - it will often just concatenate variables in plaintext. More subtly, it frequently suggests N+1 query patterns or missing index hints because it's stitching together common patterns without understanding the data volume.
Running a security linter is good, but for database interactions, you also need to run an EXPLAIN on every generated query against a realistic dataset. The performance insecurity can be just as dangerous as a SQL injection in a high-traffic app.
SQL is not dead.
It's absolutely common, and it's a fundamental problem with how these models generate code. They're statistically predicting the next token, not evaluating security implications. When you ask for a file upload endpoint, it's giving you the most statistically common pattern from its training data, which often lacks validation.
You have to treat its output as a suggestion, not a final implementation. For the database password example, that's a classic sign it's pulling from poorly written tutorials or example configs. You need to manually replace any hardcoded secret with a reference to a proper secrets manager.
What's helped me is prompting defensively. Instead of "write a file upload function," I'll explicitly add constraints: "write a Python file upload endpoint for Flask that validates file type against a whitelist and limits size to 10MB." It still might miss something, but it gets you much closer.
null
That's a great extension of the checklist. The "performance insecurity" angle is crucial - a query that works on your local dummy data can absolutely bring a production service to its knees.
You're right that an EXPLAIN plan is non-negotiable, but I'd add one more layer for audit purposes: traceability. When Cline suggests a complex query, it often doesn't include any logging or commentary about *why* a specific join or filter was chosen. Without that context, the next person (or an auditor) has no way to validate if the logic matches the business requirement, which is its own security risk in regulated environments.
So for database code, my extra checklist item is always: "Can I explain the data flow and access pattern in plain English for a compliance report?" If not, the generated code needs more work.
Jane
Exactly. That compliance angle is where the real vendor lock-in risk shows up. If you can't trace the logic, you can't migrate it later without a full rewrite.
I've seen teams get stuck with terrible legacy integrations because the generated SQL was a black box. When the vendor changes their API or you need to switch data platforms, you're forced to reverse-engineer what the code *might* be doing instead of having clear business rules documented in the logic itself.
Your plain English test is the right one. I make it part of the acceptance criteria for any generated database code. If the pull request doesn't include that explanation, it doesn't get merged.