PolicyEngine / PolicyEngine/policyengine-api

Audit remaining f-string/interpolated SQL and add CI guard

Open
#3,477 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug security
Dominant language
Python
Stars
18
Forks
33
Avg merge
23h 40m
Merged PRs (30d)
22

Description

Summary

#3445 (parameterize update_user_policy keys) and #3451 (drop f-string LIMIT in get_simulations) were filed in isolation from a targeted bug audit. Neither was found via a systematic grep of the repo's SQL surface. A repo-wide audit of f-string/.format() SQL construction is overdue to flush out any remaining patterns before the next incident.

What goes wrong

Today's workflow assumes contributors notice string-interpolated SQL during review. There is no:

  • Automated check (ruff, bandit, semgrep rule) for execute(f"..." or execute("..." % ...) patterns.
  • Pre-commit hook blocking string-interpolated SQL.
  • Documented guideline in CONTRIBUTING.md about parameterization.

The result is that new endpoints can quietly reintroduce injection vectors; #3445 and #3451 both survived multiple reviews.

Suggested fix

  1. Audit: grep the repo for all SQL execution sites (cursor.execute, db.execute, connection.execute, etc.) and verify every dynamic segment is a ?/:param placeholder. Cover at minimum:
    • policyengine_api/endpoints/ (all files)
    • policyengine_api/services/
    • policyengine_api/data/
    • policyengine_api/utils/
  2. Codify: add a bandit config or semgrep rule to CI that fails on execute(f"..." and similar patterns. Example rule:
- id: fstring-sql
  pattern-either:
    - pattern: $CONN.execute(f"...")
    - pattern: $CONN.execute("..." % $X)
    - pattern: $CONN.execute("..." + $X)
  message: Don't build SQL with string interpolation — use parameterized queries.
  severity: ERROR
  languages: [python]
  1. Document in CONTRIBUTING.md: "SQL must use parameterized queries; never f"..." or .format() into a SQL string."

Severity

Medium — no known active vulnerability, but the class of bug has now resurfaced twice in the same repo.

Relates to

Fixes #3445, #3451 (both closed).

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by grepping cursor.execute, db.execute, and connection.execute across policyengine_api/endpoints/, services/, data/, and utils/, then inspect the existing CI configuration. Audit each dynamic SQL construction, add a CI rule covering the listed interpolation patterns, and update CONTRIBUTING.md with the parameterization guideline. Done means the audited sites use placeholders, CI rejects the patterns, and the guideline is documented.

Written by the indexing model from the issue text.

Assessment

Tech stack
python, sql
Domain
backend, ci-cd, databases, documentation, security
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.