T09 · Insecure Skill Coding Practices
- Location
patterns.md:123- Finding
SQL Injection in Incremental Loading Query
- Content
View full analysis
Vulnerability Details
File Location:
patterns.md:123
Vulnerability Type: SQL injection through string interpolation
Risk Level: MediumVulnerable Code:
python new_data = query(f"WHERE updated_at > '{last_loaded}'")Technical Analysis
The incremental-loading example directly embeds
last_loadedinto an SQL predicate using an f-string. It does not use a bound parameter, strict timestamp conversion, or escaping. This unsafe example also contradicts the parameterization requirement documented inquerying.md:41.If an implementation follows this pattern and
last_loadedcan be influenced through user input, upstream data, or persisted workflow state, an attacker could insert quote characters and additional SQL syntax. Whether stacked statements are available depends on the database driver, but predicate manipulation orUNION-based extraction may remain possible even when multiple statements are disabled.Attack Path
- The attacker influences the value stored or supplied as
last_loaded. - The application inserts that value directly between SQL quotes.
- A malicious value terminates the intended timestamp literal and adds SQL syntax.
- The database parses the injected content as part of the query.
- The attacker may alter filtering behavior or retrieve data outside the intended incremental window, subject to the database account's permissions.
Impact Assessment
Exploitation may expose records beyond the intended date range and, depending on the surrounding query, driver behavior, and database privileges, may enable broader unauthorized database reads. The resulting access is bounded by the permissions of the database connection used by the workflow. If the connection has write or administrative privileges, the potential scope may be greater.
- The attacker influences the value stored or supplied as
- Remediation
View remediation
Remediation Suggestions
-
Replace f-string construction with the database driver's parameter-binding mechanism.
-
Parse and validate the watermark as a timestamp before executing the query.
-
Store watermarks in a typed state store rather than accepting arbitrary SQL fragments.
-
Run extraction with a read-only, least-privileged database account.
-
Add tests containing quotes, SQL metacharacters, malformed timestamps, and boundary values.
-
Update the example to follow a safe pattern such as:
python last_loaded = parse_timestamp(get_last_watermark()) new_data = query( "SELECT required_columns FROM source_table WHERE updated_at > ?", parameters=(last_loaded,), )The exact placeholder syntax should be adjusted for the selected database driver.
-
