Skip to content

Bug: SQL LIMIT enforcement bypass via subquery nesting in skill_endpoints validator #26

@PavanendraBaahubali

Description

@PavanendraBaahubali

Description

The validate_sql function in the skill endpoints uses re.captures() / re.replace() which only operate on the first LIMIT clause found. A query with a low inner LIMIT (below MAX_ROWS) followed by a high outer LIMIT passes validation with the outer limit intact.

File: crates/daemon/src/server/skill_endpoints.rs (lines ~183-195)

Example

sql -- Inner LIMIT 50 is found first (< MAX_ROWS=100) → no replacement triggered -- Outer LIMIT 5000 is never inspected → survives unchanged SELECT * FROM (SELECT * FROM frames LIMIT 50) AS t LIMIT 5000

An LLM-generated query like this would return up to 5000 rows, scanning the entire database and consuming large amounts of memory.

Impact

The MAX_ROWS = 100 cap can be bypassed by any nested/subquery pattern, potentially causing the daemon to load and return unbounded result sets.

Suggested Fix

Use captures_iter() to inspect and cap all LIMIT clauses, or wrap the entire query unconditionally:

ust let capped = format!( "SELECT * FROM ({}) AS _capped LIMIT {}", normalized, MAX_ROWS );

This guarantees the cap regardless of query structure.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions