Skip to content

feat(lint): apply SQL rules to pgdevkit PostgresJsonResponse - #80

Merged
aersam merged 3 commits into
mainfrom
postgres-json-response-lint
Oct 9, 2026
Merged

aersam merged 3 commits into
mainfrom
postgres-json-response-lint

Conversation

@aersam

@aersam aersam commented Oct 9, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Extends the SQL injection lint (bdt lint / bdt find-injection) to the query argument of pgdevkit.fastapi.PostgresJsonResponse (bmsuisse/pgdevkit#48, #49), the same way #79 did for fetch_all/fetch_one/fetch_scalar: f-string / concatenation / % / .format() SQL is an error, and the inline-complexity and positional-param rules apply. t-string, load_sql(), psycopg.sql and literal+params calls stay clean.

  • bdt lint --help, the README and the devtools skill now name the checked callees.
  • Matched by name only, so not covered (documented in the code comment): an alias (as PJR), a subclass under another name (class AppJson(PostgresJsonResponse)), and CCMT2's own legacy PostgresJsonResponse("postgres", sql, ...) (first argument is a connection source, not SQL; skipped silently, never a false positive). Moving CCMT2 to pgdevkit's class brings those call sites under the lint.
  • Version 0.34.0.

Test plan

  • tests/test_lint_sql.py: f-string / concat / % / .format() flagged, bare-name, attribute (pgf.PostgresJsonResponse) and query= call shapes, variable followed to its unsafe assignment, safe forms clean (incl. t-string), complexity + positional rules, legacy CCMT2 shape not flagged (mutation-checked: 4 of the new tests fail without the registration)
  • Before/after on CCMT2, OneSales and MDMApp: no findings on any PostgresJsonResponse call (no new false positives)
  • bdt lint and bdt find-injection end to end on a throwaway project

🤖 Generated with Claude Code

@aersam
aersam marked this pull request as ready for review October 9, 2026 13:43
@aersam
aersam enabled auto-merge (squash) October 9, 2026 13:43
@aersam
aersam merged commit 2b10de8 into main Oct 9, 2026
1 check passed
aersam and others added 3 commits October 9, 2026 15:35
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Its first argument is run as SQL like .execute()/fetch_all, so f-string / concat / % / .format()
SQL is flagged, and the inline-complexity and positional-param rules apply. The fix advice for it
doesn't recommend t-strings (the class wraps the query as a subquery and rejects them).
CCMT2's legacy PostgresJsonResponse('postgres', sql) shape stays unchecked (first arg is no SQL).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…l advice

pgdevkit 0.14.1 accepts t-string queries, so the usual 'change f to t' fix is right for it too.
Also: bdt lint --help and the devtools skill name the checked callees; document that aliases,
subclasses and CCMT2's legacy shape are matched by name only.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant