The Upload Endpoint Passed Every Test. Then the Security Checklist Found a Path Traversal. A developer found that an AI-generated file upload endpoint passed all functional tests but contained a path traversal vulnerability, allowing attackers to write files anywhere on the server. The developer recommends a 15-minute security checklist and provides a fix using Path().name and an extension allowlist, along with a shell script for CI to catch common vulnerability patterns. A file upload endpoint generated by an AI coding assistant passed every functional test in the suite. It accepted valid files, rejected oversized ones, and returned the correct status codes for each scenario. Then a fifteen-minute security checklist found a path traversal vulnerability that would have allowed an attacker to write files anywhere on the server. The endpoint was functionally correct and completely unsafe at the same time. This gap is exactly what most AI code review workflows miss. Functional tests verify that code does what it is supposed to do, and security review verifies that code does not do what it is not supposed to do. AI models are trained on patterns that look correct, and those patterns rarely include adversarial input. A test suite that checks the happy path and a few error cases tells a developer nothing about whether an endpoint is safe. The upload endpoint had tests for valid uploads, empty files, and oversized files, and all of them passed. None of the tests used a filename like ../../etc/cron.d/evil , because the test author was thinking about functionality, not about what an attacker could do. Security issues live in the space between what the code does and what the code should be allowed to do. A functional test asks whether the code works, and a security check asks whether the code can be abused. These are different questions, and they require different review techniques. The following checklist takes about fifteen minutes to run on a typical endpoint. It is not a comprehensive security audit, but it catches the most common vulnerability classes in AI-generated code. Each item on this list maps to a concrete code pattern. The path handling check, for example, looks for open , os.path.join , or Path calls that include a variable derived from request data. The AI-generated upload endpoint stored files with a user-supplied filename, and the code was compact enough to look innocent: python @app.post "/upload" def upload file request : filename = request.form "filename" content = request.files "file" .read with open f"/uploads/{filename}", "wb" as f: f.write content return {"status": "ok"} A request with filename=../../tmp/pwned would escape the uploads directory and write a file anywhere the process could write. A request with filename=../../app/main.py could overwrite the application itself, depending on file permissions. The fix is to sanitize the filename and validate the extension against an allowlist: python from pathlib import Path ALLOWED EXTENSIONS = {".jpg", ".png", ".pdf"} @app.post "/upload" def upload file request : filename = Path request.form "filename" .name if Path filename .suffix not in ALLOWED EXTENSIONS: return {"error": "invalid extension"}, 400 content = request.files "file" .read with open f"/uploads/{filename}", "wb" as f: f.write content return {"status": "ok"} The Path .name call strips any directory components, and the allowlist rejects anything that is not an image or a PDF. The same endpoint now handles the original test cases and the adversarial ones. A simple shell script can catch the most common vulnerability patterns in seconds, and it can run in CI on every pull request: bash /usr/bin/env bash security-triage.sh - quick pattern checks for AI-generated code echo "== SQL string concatenation ==" grep -rnE "SELECT. \+|f\" " --include=" .py" . || echo "OK" echo "== open with request-derived variables ==" grep -rnE "open\ . request|form|args|json " --include=" .py" . || echo "OK" echo "== subprocess or os.system with variables ==" grep -rnE " subprocess|os\.system . \+|f\" " --include=" .py" . || echo "OK" echo "== hardcoded secrets ==" grep -rnE " password|secret|api key \s =\s '\" " --include=" .py" . \ | grep -vE "os\.environ|getenv" || echo "OK" This script is a triage tool, not a security review. It produces false positives, and it misses anything that does not match a pattern. What it does well is catching the obvious mistakes that AI models make with surprising regularity. MonkeyCode's free model access was used to generate the original upload endpoint, and its free server option deployed it for testing. The same free model access can review the code with a security-focused prompt, and the review is useful as a second pair of eyes. The model flagged the unsanitized filename as a potential issue, though it did not explain the full attack chain, and the confirmation came from the checklist and a manual trace of the request path. Disclosure: This article was prepared as part of MonkeyCode's product outreach. The free server also makes the CI triage script practical for side projects and small teams. A scan that runs in seconds and costs nothing is a scan that runs on every pull request, and a scan that runs on every pull request catches issues before they reach production. This checklist covers common web application vulnerabilities, and it does not cover business logic flaws, race conditions, or issues that require deep domain knowledge. The automated script is pattern-based, which means it misses anything that does not match a known pattern and flags some things that are not vulnerabilities. A checklist and a grep script are a floor, not a ceiling. The approach also assumes that the reviewer understands the vulnerability classes well enough to evaluate the checklist results. Someone who does not know what path traversal is will not be able to judge whether the code is vulnerable, and a checklist cannot teach that knowledge. Teams building payment systems, healthcare platforms, or other high-risk applications should not rely on a checklist and a pattern scan. Those systems need professional security review, penetration testing, and threat modeling, and no amount of free-tier tooling replaces that. The checklist is for developers who currently do no security review at all, and it gives them a starting point that is better than nothing. The upload endpoint is still in production, and the security scan now runs on every pull request. The vulnerability was found by a fifteen-minute checklist, and the fix was three lines of code. That is the pattern that matters: most AI-generated code has common, predictable vulnerabilities, and common vulnerabilities can be caught with common checks.