Skip to content

fix: parameterize table name in PostgreSQL get_collection_info - #290

Open
akushonkamen wants to merge 1 commit into
ANative-Lab:mainfrom
akushonkamen:fix/287-parameterize-collection-info
Open

akushonkamen wants to merge 1 commit into
ANative-Lab:mainfrom
akushonkamen:fix/287-parameterize-collection-info

Conversation

@akushonkamen

Copy link
Copy Markdown

Fixes #287

Root cause

get_collection_info() built its row-count query with an f-string, interpolating the LLM-controlled collection_name directly into SQL (SELECT COUNT(*) as row_count FROM {collection_name}, pre-fix evoagentx/tools/database_postgresql.py:896) — while the same function already passed the very same argument as a bound parameter to the information_schema.columns query two lines below (:898), so this one call site is an omission. A name like information_schema.tables WHERE table_name='users'-- escapes the statement and executes against arbitrary SQL.

Fix

  • Table names are identifiers and cannot be bound parameters, so the query is now composed as psycopg2.sql.SQL("SELECT COUNT(*) as row_count FROM {}").format(psycopg2.sql.Identifier(collection_name)), which safely quotes the value while preserving the function's semantics of returning the real row count of the named table.
  • Added conn.rollback() in the function's except block, aligning with the existing convention in execute_query() (:637-641): without it, a correctly rejected injection leaves the session's transaction aborted and poisons subsequent queries on the same connection — reproduced and verified during testing.

Tests

New regression tests: mocked-cursor tests assert the payload only rides as a quoted Identifier and that errors trigger rollback, plus an opt-in live PostgreSQL test (enabled via EVOAGENTX_TEST_PG_DSN).

  • Live PoC (docker postgres:16, non-destructive read-only): on unfixed code, payload information_schema.tables WHERE table_name='users'-- returned success=True, row_count=1, proving execution against the catalog. After the fix, the injection returns success=False (quoted-identifier error), the legitimate users table reports row_count=2, and a x; DROP TABLE users; -- payload only produces a quoting error — the table stays intact.
  • Unit tests pytest tests/src/tools/test_database_postgresql.py -k "not live_postgres" -q: 3 failed before the fix, 3 passed after.
  • Opt-in live test (-m live_postgres with EVOAGENTX_TEST_PG_DSN): 1 passed.
  • -k database subset cannot fully collect in our environment: 18–24 pre-existing ModuleNotFoundError collection errors from heavy deps (the repo-pinned faiss-cpu==1.8.0.post1 has no Python 3.14 wheel, verified via pip). Degraded faithful run with --continue-on-collection-errors: 3 passed, 1 skipped, 99 deselected, 18 errors — none of the errored modules match database.
  • Regression sanity: pytest tests/src/tools/test_alita_generated_code_tool.py → 7 passed.

Note

While verifying, we noticed the sibling find/update/delete tools in the same file also splice model-controllable fragments into SQL via f-strings — possibly by design. Flagged on the issue for maintainer triage: #287 (comment)

get_collection_info() interpolated the LLM-controlled collection_name
directly into an f-string SQL statement while the same function already
parameterized the same argument two lines below (issue ANative-Lab#287). Table
names are identifiers and cannot be bound parameters, so wrap them with
psycopg2.sql.Identifier, which safely quotes the value. Also roll back
on error in get_collection_info so a rejected name does not leave the
session's transaction aborted for subsequent queries, matching the
existing convention in execute_query().

Add regression tests: mocked-cursor tests assert the payload only rides
as a quoted Identifier and that errors roll back, plus an opt-in live
PostgreSQL test (EVOAGENTX_TEST_PG_DSN).
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 11, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ⚠️ Failed 2026-10-11T19:22:42.315085Z e51f6f7 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Security] SQL injection in get_collection_info via unsanitized collection_name

1 participant