Reviewed for the final v2.0.2 portfolio release.
- The QueryPilot repository does not have an active GitHub Pages site; the
GitHub Pages API returns
404. querypilot.eraykulkizaga.comresolves through a CNAME tocustom-domains.chatgpt.site.- The public application is deployed through Sites on Cloudflare. GitHub stores source code only; it does not receive the Gemini runtime secret.
The public demo accepts EXPLAIN JSON, not SQL. It has no PostgreSQL binding, database credential, or SQL execution path, so its AI endpoint cannot be used for SQL injection.
The separate local runtime applies layered controls before EXPLAIN ANALYZE:
- PostgreSQL SQL is parsed as an AST with SQLGlot.
- Exactly one statement is accepted.
- Only
SELECTorWITH ... SELECTquery ASTs are accepted. - Data-changing, locking, transaction, command, copy, and
SELECT INTOnodes are rejected. - Known side-effect functions and all unknown/user-defined functions are rejected.
- PostgreSQL runs the validated statement in a read-only transaction with a statement timeout and a least-privilege application role.
Tests cover stacked statements, data-changing CTEs, row locks, side-effect functions, user-defined functions, statement-like text inside string literals, and statement-like text inside comments.
This remains an educational local tool. It must not receive production credentials or run unreviewed queries against a production database.
- The complete pasted EXPLAIN JSON stays in the visitor's browser.
- Only a bounded category, severity, and fixed-shape evidence payload is accepted by the same-origin Worker endpoint.
- User-submitted summaries are replaced with an application-owned canonical summary before prompting.
- Evidence fields must match the exact metric shape for their deterministic category; prompt-like evidence and unsafe identifiers are rejected.
- A category-owned PostgreSQL knowledge chunk is selected server-side.
- Model output must use known evidence and citation IDs.
- Invented numbers, URLs, SQL action commands, unknown backticked identifiers, HTML markup, extra fields, and malformed JSON are rejected.
- Provider failures, invalid output, timeout, quota exhaustion, or a missing key leave the deterministic result unchanged.
- Provider calls have a 15-second timeout and a best-effort per-client, per-isolate request limit. The Gemini project remains on its free tier so quota abuse can exhaust availability but cannot silently create paid usage.
GEMINI_API_KEYexists only as a secret production runtime value in Sites..env*files are ignored; only a placeholder.env.exampleis tracked.- The key is read from the Worker runtime environment and is never returned in an API response.
- Provider error bodies are not forwarded to visitors.
- The browser bundle test rejects the Gemini endpoint, runtime variable name, or Google API-key-shaped values in client JavaScript.
- The release gate scans tracked files for secret patterns before deployment.
- GitHub secret scanning and push protection are enabled for the repository.
- CodeQL analyzes the Python and JavaScript/TypeScript source on every push and pull request.
- Private vulnerability reporting is enabled; disclosure instructions live in
the root
SECURITY.mdfile.
The Worker adds content-type, framing, referrer, permissions, transport,
cross-origin, and Content Security Policy headers. The API accepts JSON POST
requests from the same origin and returns no-store responses.
No known critical SQL-injection or API-key-leakage path remains within the documented public and local boundaries. This review is an automated and manual engineering assessment, not a third-party penetration test.