Static checker for unsafe Piccolo raw SQL construction
Project description
piccolo-sql-guard
A community-maintained static checker for unsafe Piccolo raw SQL construction.
What it checks
| Rule | Name | Description |
|---|---|---|
PQS001 |
raw-sql-fstring |
Flags f-strings passed into Table.raw() |
PQS002 |
raw-sql-string-formatting |
Flags concatenation, % formatting, and .format() passed into Table.raw() |
PQS003 |
querystring-unsafe-template |
Flags the same unsafe patterns for QueryString() |
PQS004 |
unsafe-sql-token-builder |
Flags uncontrolled SQL tokens in helper builders |
PQS004 — unsafe SQL token builders
PQS004 performs cross-function analysis to find SQL builder functions that interpolate parameters of unsafe type and are reachable from a Piccolo raw SQL sink. A parameter is safe when its type annotation constrains it to a finite set of values:
Literal["ASC", "DESC"]— explicitly enumerated stringsbool— Boolean (maps to e.g." WHERE active"/"")int/float— numeric constants- A local
Enum/StrEnumsubclass
A plain str parameter is unsafe and triggers PQS004.
# PQS004 fires — sort_col is unconstrained str
def build(sort_col: str) -> str:
return f"SELECT * FROM my_model ORDER BY {sort_col}"
# Safe — Literal constrains the set of allowed values
def build(direction: Literal["ASC", "DESC"]) -> str:
return f"SELECT * FROM my_model ORDER BY id {direction}"
PQS004 also follows simple helper-call chains and common string-building
patterns such as f-strings, string concatenation, and str.join() over literal
containers.
Quick start
pip install piccolo-sql-guard
piccolo-sql-guard src/
Usage
piccolo-sql-guard [PATH ...] # scan paths
piccolo-sql-guard --format json src/ # JSON output
piccolo-sql-guard --select PQS001,PQS002 src/ # enable specific rules
piccolo-sql-guard --ignore PQS004 src/ # disable specific rules
piccolo-sql-guard --statistics src/ # print file/violation counts
piccolo-sql-guard --profile src/ # print per-phase timing
piccolo-sql-guard --version
Unknown rule codes passed to --select or --ignore are treated as
configuration errors so CI does not accidentally run with an empty ruleset.
Development
This project uses uv for the local development environment and lockfile.
The package supports Python 3.11 through 3.14.
uv sync --extra dev
uv run --extra dev pytest
uv run --extra dev ruff check .
uv run --extra dev mypy src
Configuration
piccolo-sql-guard.toml or pyproject.toml:
[tool.piccolo-sql-guard]
include = ["src"]
exclude = ["migrations", ".venv"]
select = ["PQS001", "PQS002", "PQS003", "PQS004"]
ignore = []
builder_allowlist = ["build_*_sql"]
piccolo_modules = ["piccolo"]
output_format = "text"
pqs004_max_iterations = 5 # fixed-point iteration cap for recursive builders
builder_allowlist
A list of glob patterns matching builder function names that are assumed safe and excluded from PQS004 analysis. Use this for third-party or generated builders you cannot annotate.
pqs004_max_iterations
Maximum number of fixed-point iterations for recursive or mutually-recursive
builder groups (default: 5). Increase if you have deeply recursive builders;
decrease if scan time is a concern.
Limitations
piccolo-sql-guard is a best-effort static checker. Dynamic dispatch, complex
container mutation, runtime imports, and values assembled outside the scanned
source tree may be treated as unknown or missed. Treat a clean run as a lint
signal, not as proof that every raw SQL path is injection-safe.
Exit codes
| Code | Meaning |
|---|---|
0 |
No violations |
1 |
Violations found |
2 |
Config or usage error |
3 |
Internal checker error |
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file piccolo_sql_guard-0.1.0.tar.gz.
File metadata
- Download URL: piccolo_sql_guard-0.1.0.tar.gz
- Upload date:
- Size: 64.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
190e5bba337f0a0849c57f408fadac29bc69a57ad2f2e01e73bf668de95598d9
|
|
| MD5 |
327719a93eadf756acb23efa226c74ac
|
|
| BLAKE2b-256 |
71bac884baf64d1136fe116b5cecca7cfc50b63b4f24a467e78687267223e59f
|
Provenance
The following attestation bundles were made for piccolo_sql_guard-0.1.0.tar.gz:
Publisher:
release.yml on atkei/piccolo-sql-guard
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
piccolo_sql_guard-0.1.0.tar.gz -
Subject digest:
190e5bba337f0a0849c57f408fadac29bc69a57ad2f2e01e73bf668de95598d9 - Sigstore transparency entry: 1388968764
- Sigstore integration time:
-
Permalink:
atkei/piccolo-sql-guard@999136e0bee0c251219e0ebd8723ee02218bba96 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/atkei
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@999136e0bee0c251219e0ebd8723ee02218bba96 -
Trigger Event:
release
-
Statement type:
File details
Details for the file piccolo_sql_guard-0.1.0-py3-none-any.whl.
File metadata
- Download URL: piccolo_sql_guard-0.1.0-py3-none-any.whl
- Upload date:
- Size: 43.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
31e1e5ed2da584ff19165791b8d80bba86cdb14e5f5df2320508dadf177d9825
|
|
| MD5 |
4058d5aaf0b6552b6b1e4f4f18a7a68e
|
|
| BLAKE2b-256 |
32cb2fe3a014806e7167c082d5ed4b28c56c3c4675d5459de1a762d226965353
|
Provenance
The following attestation bundles were made for piccolo_sql_guard-0.1.0-py3-none-any.whl:
Publisher:
release.yml on atkei/piccolo-sql-guard
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
piccolo_sql_guard-0.1.0-py3-none-any.whl -
Subject digest:
31e1e5ed2da584ff19165791b8d80bba86cdb14e5f5df2320508dadf177d9825 - Sigstore transparency entry: 1388968825
- Sigstore integration time:
-
Permalink:
atkei/piccolo-sql-guard@999136e0bee0c251219e0ebd8723ee02218bba96 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/atkei
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@999136e0bee0c251219e0ebd8723ee02218bba96 -
Trigger Event:
release
-
Statement type: