PyPI / sqlglot / 30.23.0

sqlglot 30.23.0

Source
https://github.com/tobymao/sqlglot
Tag scanned
v30.23.0
Compared with
v30.22.0 (0 signals introduced since)
Files
262 scanned, 86 skipped (binary, oversized, or unrecognised)
Signals
1 critical · 0 warn · 11 info
Scan time
12.1 s
LLM review
Reviewed by claude-haiku-5-5 (Anthropic): 7 of 7 warn and critical signals; 6 demoted to info.
Disclude version
4.0.0
Scanned (UTC)
2026-10-15 12:10

Signals

Ordered by severity, then signals introduced in this release. Hidden characters are shown as ⟨U+…⟩.

  1. critical dynamic-import sqlglot/serde.py:116:18

    `__import__` called on a non-literal expression (ast pass, confidence 0.70)

            module_path, class_name = class_name.rsplit(".", maxsplit=1)
            module = __import__(module_path, fromlist=[class_name])
        else:
            module = exp
    suspicious LLM, confidence 0.70 Dynamically imports the module named in a serialized class path during expression deserialization.
    Reasoning

    __import__ is called with a module path derived from a class name string in a serialization loader, which is a dynamic import pattern worth noting since serialized input could name arbitrary modules. The snippet shows the path being split from a class-name string, consistent with deserializing known sqlglot expression classes; the critical severity reflects the dynamic-import surface rather than evidence of malice.

  2. info warn → info by review dynamic-attribute pdoc/cli.py:14:29

    reach-by-name through `globals` (ast pass, confidence 0.60)

    # Load all dialects up front because lazy loading breaks pdoc's dynamic importing
    sqlglot.dialects.__all__ = [globals()[attr_name] for attr_name in sqlglot.dialects.__all__]
    likely benign LLM, confidence 0.85 Eagerly loads sqlglot dialect classes by name via globals() so pdoc documentation generation works.
    Reasoning

    Rebinding sqlglot.dialects.__all__ to a list comprehension over globals() is a documented workaround for pdoc's dynamic import behavior, with an explanatory comment. Name-based lookup of module attributes is ordinary Python here and no payload or hidden execution is involved.

  3. info warn → info by review dynamic-attribute sqlglot/dialects/__init__.py:126:9

    reach-by-name through `globals` (ast pass, confidence 0.60)

            attr = getattr(module, name)
            globals()[name] = attr
            return attr
    likely benign LLM, confidence 0.88 Lazy attribute loader that caches resolved module attributes into the package globals.
    Reasoning

    This is a standard lazy-module __getattr__ pattern that imports a submodule attribute and caches it in globals(). It is a common, legitimate Python idiom with no network, decoding, or execution of untrusted data.

  4. info warn → info by review dynamic-execution sqlglot/executor/context.py:46:16

    `eval` called on a non-literal expression (ast pass, confidence 0.70)

        def eval(self, code):
            return eval(code, self.env)
    
        def eval_tuple(self, codes):
    likely benign LLM, confidence 0.80 Evaluates Python code generated from SQL expressions inside the sqlglot in-memory executor.
    Reasoning

    eval is used on code strings produced by sqlglot's own Python executor compiler from parsed SQL expressions, with a restricted env. This is by design for a SQL-to-Python execution engine, but eval on generated code is a real risk surface if inputs were untrusted; it is not obfuscation or a dropper.

  5. info warn → info by review dynamic-execution sqlglot/executor/python.py:95:16

    `compile` called on a non-literal expression (ast pass, confidence 0.70)

            sql = self.generator.generate(expression)
            return compile(sql, sql, "eval", optimize=2)
    
        def _replace_subqueries(self, expression):
    likely benign LLM, confidence 0.80 Compiles generated Python expression source from SQL in the sqlglot executor.
    Reasoning

    compile is applied to SQL-generated Python source in the executor's code path, so the non-literal input comes from the library's own generator rather than attacker-controlled bytes. Expected for this kind of engine and not an encoded payload.

  6. info warn → info by review dynamic-attribute sqlglot/optimizer/__init__.py:64:9

    reach-by-name through `globals` (ast pass, confidence 0.60)

                    raise AttributeError(f"module {__name__!r} has no attribute {name!r}") from None
            globals()[name] = value
            return value
    likely benign LLM, confidence 0.85 Lazy module attribute resolver that caches loaded values into globals().
    Reasoning

    Same lazy-loading __getattr__ idiom caching a value into globals(), with a clear AttributeError on failure. Standard and benign.

  7. info warn → info by review high-complexity tests/dialects/test_athena.py:130:14

    string literal compression ratio 0.956 (136 bytes) (raw pass, confidence 0.60)

            self.validate_identity(
                "CREATE TABLE foo WITH (table_type='ICEBERG', location='s3://foo/', format='orc', partitioning=ARRAY['bucket(id, 5)']) AS SELECT * FROM a"
            )
            self.validate_identity(
    dismissed LLM, confidence 0.95 Test SQL string literal for Athena CREATE TABLE statement flagged for compressibility.
    Reasoning

    This is a long SQL string literal in a test file, a normal CREATE TABLE statement with a compression ratio flagged only because of its repetitive text. Raw-pass heuristics have a high false-positive rate here and there is no obfuscation.

  8. compression ratio 0.939 is >2σ above file mean 0.795 (raw pass, confidence 0.50)

            self.validate_identity(
                "COPY customer FROM 's3://mybucket/customer' IAM_ROLE 'arn:aws:iam::0123456789012:role/MyRedshiftRole' REGION 'us-east-1' FORMAT orc",
            )
            self.validate_identity(
  9. compression ratio 0.924 is >2σ above file mean 0.795 (raw pass, confidence 0.50)

            self.validate_identity(
                "SELECT attr AS attr, JSON_TYPEOF(val) AS value_type FROM customer_orders_lineitem AS c, UNPIVOT c.c_orders[0] WHERE c_custkey = 9451"
            )
            self.validate_identity(
  10. compression ratio 0.910 is >2σ above file mean 0.611 (raw pass, confidence 0.50)

                write={
                    "duckdb": "SELECT h.id, amount FROM hourlycostagg AS h CROSS JOIN LATERAL (SELECT UNNEST(h.adjustments, max_depth => 2)) AS _u_0(type, val, curr)",
                },
            )
  11. info whitespace-anomaly tests/test_executor.py:23:1

    file mixes tab and space indentation (6 tab-indented and 1564 space-indented lines) (raw pass, confidence 0.40)

    from tests.helpers import (
        FIXTURES_DIR,
        SKIP_INTEGRATION,
        TPCH_SCHEMA,
  12. info high-complexity tests/test_optimizer.py:1236:22

    compression ratio 0.864 is >2σ above file mean 0.656 (raw pass, confidence 0.50)

                    parse_one(
                        "SELECT (SELECT SUM(ci.amount) FROM my_table LATERAL VIEW EXPLODE(items) ci AS ci WHERE ci.type = 'promotion') AS total FROM my_table",
                        read="spark",
                    ),

Reproduce This Scan

Run disclude locally to verify. Add --format sarif for SARIF output. Add --llm (with an API key in the environment) to include the LLM review.

cargo install disclude --version 4.0.0
git clone https://github.com/tobymao/sqlglot sqlglot && cd sqlglot
git checkout v30.23.0
disclude scan --severity info --diff v30.22.0 .