{"id":50894011,"url":"https://github.com/atkei/piccolo-sql-guard","last_synced_at":"2026-06-15T23:01:36.896Z","repository":{"id":353929815,"uuid":"1221328501","full_name":"atkei/piccolo-sql-guard","owner":"atkei","description":"Static analysis tool for detecting unsafe raw SQL construction in Piccolo ORM projects","archived":false,"fork":false,"pushed_at":"2026-04-26T08:53:29.000Z","size":81,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-26T10:21:51.597Z","etag":null,"topics":["piccolo","pyton","security","sql-injection","static-analysis"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/atkei.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-26T03:48:25.000Z","updated_at":"2026-04-26T09:05:33.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/atkei/piccolo-sql-guard","commit_stats":null,"previous_names":["atkei/piccolo-sql-guard"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/atkei/piccolo-sql-guard","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/atkei%2Fpiccolo-sql-guard","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/atkei%2Fpiccolo-sql-guard/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/atkei%2Fpiccolo-sql-guard/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/atkei%2Fpiccolo-sql-guard/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/atkei","download_url":"https://codeload.github.com/atkei/piccolo-sql-guard/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/atkei%2Fpiccolo-sql-guard/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34383468,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-15T02:00:07.085Z","response_time":63,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["piccolo","pyton","security","sql-injection","static-analysis"],"created_at":"2026-06-15T23:01:35.933Z","updated_at":"2026-06-15T23:01:36.891Z","avatar_url":"https://github.com/atkei.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# piccolo-sql-guard\n\nA community-maintained static checker for unsafe Piccolo raw SQL construction.\n\n## What it checks\n\n| Rule | Name | Description |\n|------|------|-------------|\n| `PQS001` | `raw-sql-fstring` | Flags f-strings passed into `Table.raw()` |\n| `PQS002` | `raw-sql-string-formatting` | Flags concatenation, `%` formatting, and `.format()` passed into `Table.raw()` |\n| `PQS003` | `querystring-unsafe-template` | Flags the same unsafe patterns for `QueryString()` |\n| `PQS004` | `unsafe-sql-token-builder` | Flags uncontrolled SQL tokens in helper builders |\n\n### PQS004 — unsafe SQL token builders\n\nPQS004 performs cross-function analysis to find SQL builder functions that\ninterpolate parameters of unsafe type and are reachable from a Piccolo raw SQL\nsink.  A parameter is **safe** when its type\nannotation constrains it to a finite set of values:\n\n- `Literal[\"ASC\", \"DESC\"]` — explicitly enumerated strings\n- `bool` — Boolean (maps to e.g. `\" WHERE active\"` / `\"\"`)\n- `int` / `float` — numeric constants\n- A local `Enum` / `StrEnum` subclass\n\nA plain `str` parameter is **unsafe** and triggers PQS004.\n\n```python\n# PQS004 fires — sort_col is unconstrained str\ndef build(sort_col: str) -\u003e str:\n    return f\"SELECT * FROM my_model ORDER BY {sort_col}\"\n\n# Safe — Literal constrains the set of allowed values\ndef build(direction: Literal[\"ASC\", \"DESC\"]) -\u003e str:\n    return f\"SELECT * FROM my_model ORDER BY id {direction}\"\n```\n\nPQS004 also follows simple helper-call chains and common string-building\npatterns such as f-strings, string concatenation, and `str.join()` over literal\ncontainers.\n\n## Quick start\n\n```bash\npip install piccolo-sql-guard\npiccolo-sql-guard src/\n```\n\n## Usage\n\n```bash\npiccolo-sql-guard [PATH ...]                  # scan paths\npiccolo-sql-guard --format json src/          # JSON output\npiccolo-sql-guard --select PQS001,PQS002 src/ # enable specific rules\npiccolo-sql-guard --ignore PQS004 src/        # disable specific rules\npiccolo-sql-guard --statistics src/           # print file/violation counts\npiccolo-sql-guard --profile src/              # print per-phase timing\npiccolo-sql-guard --version\n```\n\nUnknown rule codes passed to `--select` or `--ignore` are treated as\nconfiguration errors so CI does not accidentally run with an empty ruleset.\n\n## Development\n\nThis project uses `uv` for the local development environment and lockfile.\nThe package supports Python 3.11 through 3.14.\n\n```bash\nuv sync --extra dev\nuv run --extra dev pytest\nuv run --extra dev ruff check .\nuv run --extra dev mypy src\n```\n\n## Configuration\n\n`piccolo-sql-guard.toml` or `pyproject.toml`:\n\n```toml\n[tool.piccolo-sql-guard]\ninclude = [\"src\"]\nexclude = [\"migrations\", \".venv\"]\nselect = [\"PQS001\", \"PQS002\", \"PQS003\", \"PQS004\"]\nignore = []\nbuilder_allowlist = [\"build_*_sql\"]\npiccolo_modules = [\"piccolo\"]\noutput_format = \"text\"\npqs004_max_iterations = 5   # fixed-point iteration cap for recursive builders\n```\n\n### `builder_allowlist`\n\nA list of glob patterns matching builder function names that are assumed safe and\nexcluded from PQS004 analysis.  Use this for third-party or generated builders you\ncannot annotate.\n\n### `pqs004_max_iterations`\n\nMaximum number of fixed-point iterations for recursive or mutually-recursive\nbuilder groups (default: `5`).  Increase if you have deeply recursive builders;\ndecrease if scan time is a concern.\n\n## Limitations\n\n`piccolo-sql-guard` is a best-effort static checker.  Dynamic dispatch, complex\ncontainer mutation, runtime imports, and values assembled outside the scanned\nsource tree may be treated as unknown or missed.  Treat a clean run as a lint\nsignal, not as proof that every raw SQL path is injection-safe.\n\n## Exit codes\n\n| Code | Meaning |\n|------|---------|\n| `0` | No violations |\n| `1` | Violations found |\n| `2` | Config or usage error |\n| `3` | Internal checker error |\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fatkei%2Fpiccolo-sql-guard","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fatkei%2Fpiccolo-sql-guard","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fatkei%2Fpiccolo-sql-guard/lists"}