Skip to main content

ConcurrencyGuard (cguard)

CI Python 3.10+ License: MIT

Deterministic AST + Runtime Concurrency & Idempotency Verifier for Python FastAPI, SQLAlchemy, and Celery Backends.


⚡ Why ConcurrencyGuard?

Modern async Python services frequently suffer from silent concurrency bugs, double-spend race conditions, lost updates, and duplicate background tasks. Traditional linters only check syntax and type hints, while external LLM tools hallucinate or miss non-local control flow races.

ConcurrencyGuard (cguard) solves this with a 100% deterministic pipeline:

  1. Pure AST Static Scanning: Catches race patterns, missing idempotency keys, N+1 queries, uniqueness races, and unsafe Celery retry tasks.
  2. Runtime asyncio.Barrier Exploit Engine: Proves race conditions empirically by synchronizing concurrent coroutines to hit endpoints at the exact same microsecond.
  3. Deterministic LibCST Auto-Patcher: Safely rewrites code to apply database row locks (.with_for_update()), inject FastAPI Idempotency-Key headers, and wrap transactions in IntegrityError guards.
  4. Automated GitHub PR Reporter: Emits rich Markdown comments with exploit proofs and diff previews for pull requests.

📋 Rule Catalog

Rule ID Name Target / Trigger Condition Automated Fix
CG-001 Unlocked Read-Modify-Write Race Async route reads database state with select(), mutates an attribute, and calls commit() without .with_for_update() locking. Appends .with_for_update() row-level locks via LibCST.
CG-002 Missing Idempotency Guard Async @app.post or @router.post route mutates state without an idempotency_key parameter. Injects idempotency_key: str = Header(..., alias="Idempotency-Key") into route parameters.
CG-003 Async Loop N+1 Query Explode db.execute(...) or session.execute(...) call located directly inside a for or async for loop body. Flags query explosion; suggests batching or eager loading (joinedload/selectinload).
CG-004 Check-Then-Act Uniqueness Race Async route checks existence with select(), calls add(), and commits without catching sqlalchemy.exc.IntegrityError. Wraps commit statements in try...except IntegrityError with session rollback.
CG-005 Non-Idempotent Celery Retry Task Celery task (@app.task, @shared_task) with autoretry_for or max_retries executes mutations (.add(), .commit(), .post()) without acks_late=True or an idempotency lock. Recommends acks_late=True and distributed deduplication lock before side-effects.

🚀 Installation

# Clone and install in virtual environment
git clone https://github.com/AyushkhatiDev/concurrency-guard.git
cd concurrency-guard
python -m venv .venv
source .venv/bin/activate
pip install -e .

To install with development and testing dependencies:

pip install -e ".[dev]"

🛠️ CLI Usage

1. cguard scan — Static AST Analysis

Scan files or entire directories for concurrency vulnerabilities:

# Scan a single file
cguard scan examples/vulnerable_wallet.py

# Scan an entire codebase
cguard scan src/

2. cguard verify — Runtime asyncio.Barrier Verification

Simulate high-concurrency traffic using synchronized barrier workers to prove whether an invariant holds or breaks under load:

cguard verify examples/vulnerable_wallet.py --workers 20

Sample exploit proof output:

❌ CONCURRENCY INVARIANT VIOLATED (RACE PROVEN)
Target File: examples/vulnerable_wallet.py
Target Endpoint: POST /wallet/withdraw
Concurrent Barrier Workers: 20
Initial Wallet Balance: $50
Successful Withdrawals ($50 each): 20
Final Resulting Balance: $-950

INVARIANT VIOLATION PROVEN:
Multiple concurrent withdrawals succeeded against a $50 balance due to an unlocked
Read-Modify-Write race condition (CG-001).

3. cguard fix — Deterministic LibCST Auto-Patcher

Inspect and apply deterministic code patches:

# Preview auto-fixes (dry-run)
cguard fix examples/vulnerable_wallet.py

# Apply specific rule fix
cguard fix examples/vulnerable_wallet.py --rule CG-001 --write

# Apply all available auto-fixes directly to disk
cguard fix examples/vulnerable_wallet.py --write

4. cguard report — GitHub Pull Request Markdown Reporter

Generate comprehensive Markdown summaries for CI/CD:

# Print report to stdout
cguard report examples/vulnerable_wallet.py

# Write report to markdown file for GitHub Actions PR comment
cguard report examples/vulnerable_wallet.py --output pr_report.md

🤖 GitHub Action Integration

Add ConcurrencyGuard to your pull request workflows:

name: Concurrency Guard CI

on:
  pull_request:
    branches: [main]

jobs:
  concurrency-audit:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Run ConcurrencyGuard Action
        uses: AyushkhatiDev/concurrency-guard@main
        with:
          path: "app"
          report-file: "app/main.py"
          output: "pr-report.md"

      - name: Post PR Comment
        if: failure() || success()
        uses: actions/github-script@v7
        with:
          script: |
            const fs = require('fs');
            if (fs.existsSync('pr-report.md')) {
              const body = fs.readFileSync('pr-report.md', 'utf8');
              github.rest.issues.createComment({
                issue_number: context.issue.number,
                owner: context.repo.owner,
                repo: context.repo.repo,
                body: body
              });
            }

🧪 Testing

ConcurrencyGuard is thoroughly tested with unit tests and runtime stress verifications:

# Run test suite
pytest -v

# Run lint and type checking
ruff check .
mypy src/

📄 License

MIT License. See LICENSE for details.

Metadata

Release files for concurrency-guard 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for concurrency-guard 0.1.0
File Size Uploaded Provenance Actions
concurrency_guard-0.1.0.tar.gz 31.1 kB Without provenance Details for concurrency_guard-0.1.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for concurrency-guard 0.1.0
File Interpreter ABI Platform Actions
concurrency_guard-0.1.0-py3-none-any.whl Python 3 none any Details for concurrency_guard-0.1.0-py3-none-any.whl

Total release size: 57.1 kB

Release files / concurrency_guard-0.1.0.tar.gz

Download URL concurrency_guard-0.1.0.tar.gz
Size 31.1 kB
Tags Source
SHA-256 checksum
How to use checksums
940ad64b2fc83164fd73ed0433eee96fbda13d4cbe8955d1cee547de2654462e
BLAKE2b-256 checksum
How to use checksums
96ea0a6a1710b8ffd0cc9568e67a56bfa3182e81ad265dc0fbed47ca26bfead3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.8

Release files / concurrency_guard-0.1.0-py3-none-any.whl

Download URL concurrency_guard-0.1.0-py3-none-any.whl
Size 25.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
d6904159ed58878f440a3abb7965bcdc825b2d071e1a4abd5993432abff925c5
BLAKE2b-256 checksum
How to use checksums
f543281bf96c5f4743d97c8aa2eedad9cbfb409d9e3812667b6067c9abe5aa2b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.8

Security for concurrency-guard 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page