QWED
v7.2.2 GitHub 60

Type to search pages, engines and advisories.

    Looking for API details?Search the docs

    GHSA-q8r4-6gpp-5fx2

    QueryGuard ignores MySQL executable comments, bypassing table allow-lists and PII column protection

    Impact

    QueryGuard in qwed-finance parses SQL without a dialect, and the parser treats MySQL executable comments (/*! ... */ and /*!NNNNN ... */) as ordinary comments. MySQL and MariaDB execute the contents of these comments. Table references and columns placed inside an executable comment are therefore invisible to the table allow-list and to PII column enforcement, while the database still reads them.

    Reproduced on v3.0.0:

    Call Result
    QueryGuard().verify_table_access("SELECT a FROM t1 /*!50000 , t2 */", {"t1"}) safe=True, tables ['t1'], no violations (MySQL reads t2)
    CrossGuard().verify_query_with_pii_protection("SELECT a /*!50000 , ssn */ FROM t1", ["t1"], ["ssn"]) passed=True, no violations (MySQL projects ssn)
    QueryGuard().sanitize_query("SELECT a FROM t1 /*!50000 , t2 */") safe=True, sanitized_query returned unchanged, including the executable comment

    Who is affected: applications that execute LLM-generated SQL against MySQL or MariaDB and rely on QueryGuard / CrossGuard for table allow-listing or PII column protection. Other database engines do not execute these comments.

    Root cause

    query_guard.py calls sqlglot.parse_one(sql_query) with no dialect and drops comments, and sanitize_query returns the original input string instead of a re-serialized form of what was analysed. The analysed AST and the executed statement differ.

    Patches

    Fixed in qwed-finance 3.0.1 (release). Upgrade with pip install -U qwed-finance==3.0.1.

    Any query containing a MySQL /*! ... */ or MariaDB /*M! ... */ executable comment is now unsafe in verify_readonly_safety, and therefore in verify_table_access, verify_column_access, sanitize_query and CrossGuard.verify_query_with_pii_protection. sanitize_query no longer rewrites such queries. Ordinary comments and optimizer hints (/*+ ... */) are unaffected.

    Workarounds

    • Reject any query containing /*! before verification when the target is MySQL or MariaDB.
    • Execute the re-serialized AST rather than the original string, and use database-level permissions (a read-only role with access only to permitted tables and columns) as the actual enforcement boundary.

    References

    Reproduced on qwed-finance 3.0.0 (bb0cdf3).