YAML Metadata Warning:empty or missing yaml metadata in repo card
Check out the documentation for more information.
QA Sentinel
A language-agnostic QA scanner for development teams. Point it at any repository and it will:
- Run the project's tests (pytest, npm, go, cargo, Maven, Gradle, dotnet, RSpec, PHPUnit, or any custom command with JUnit XML) and turn failures into findings.
- Find bugs with multi-language static analysis (mutable defaults, swallowed exceptions, wrong equality, ignored errors, shell script bugs…).
- Find security vulnerabilities: SQL/command injection, XSS, path traversal, SSRF, insecure deserialization, weak crypto, disabled TLS verification, JWT misuse, unsafe C functions.
- Find leaked secrets: API keys, private keys, tokens, passwords, credentials in connection strings.
- Find vulnerable dependencies (known CVEs) for npm, PyPI, Go, Maven, Cargo, NuGet, RubyGems, Packagist and more.
- Find insecure configuration in Dockerfiles, Kubernetes manifests, Terraform and CI scripts.
- Generate a developer report: interactive HTML (filters, search, CSV export, "fix these first"), Markdown, JSON and SARIF (GitHub Code Scanning). Every finding has severity, file:line, the offending code, why it matters, and how to fix it.
How "any language" works
QA Sentinel is an orchestrator with a plugin architecture:
| Scanner | Covers | Required? |
|---|---|---|
builtin-rules |
50+ regex rules across 40+ languages & config formats, extensible via config | built in, zero dependencies |
semgrep |
Deep SAST for 30+ languages | optional (pip install semgrep) |
bandit |
Python security | optional (pip install bandit) |
gitleaks |
150+ secret formats | optional |
osv-scanner |
CVEs in dependencies for all major ecosystems | optional |
shellcheck / hadolint |
Shell scripts / Dockerfiles | optional |
tests |
Project test suite | uses the project's own toolchain |
Missing tools are skipped (and reported as such), so the tool always works; installing more scanners gives deeper results. Findings reported by several scanners for the same issue are merged. The Docker image ships with every scanner preinstalled.
Web interface (English / العربية)
Upload a file, a folder or a .zip / .tar.gz archive in the browser and get the report in English or Arabic (right-to-left):
python -m qa_sentinel serve # opens http://localhost:8000
On Windows, double-click serve.bat. The server listens on 127.0.0.1 only by default (--host, --port,
--no-browser to change). Uploaded code is never executed (the test runner is always skipped for uploads),
archives are extracted with path-traversal and size limits, and the upload is deleted after the scan.
Reports can be downloaded as HTML, JSON, SARIF or Markdown. The HTML report has an EN/AR toggle (?lang=ar).
Hosting it on the internet
qa-sentinel serve --public binds 0.0.0.0 on $PORT, rate-limits scans per client (using the last
X-Forwarded-For hop, so run it behind a reverse proxy), caps uploads, queues scans and deletes reports after
a while. Tune with QAS_SCANS_PER_HOUR (20), QAS_MAX_UPLOAD_MB (50), QAS_REPORT_HOURS (24),
QAS_MAX_PARALLEL (2) and QAS_QUEUE_SECONDS (300). Dockerfile.web packages it with every scanner on port
7860 (Hugging Face Spaces, Render, Fly.io, ...):
docker build -f Dockerfile.web -t qa-sentinel-web . && docker run --rm -p 7860:7860 qa-sentinel-web
Quick start
Requires Python 3.9+. Run these from inside the unzipped qa-sentinel folder:
pip install . # core tool, no other dependencies
pip install semgrep bandit # optional: deeper analysis
qa-sentinel scanners # show which scanners are installed
qa-sentinel scan path/to/project
Then open path/to/project/qa-report/report.html in a browser.
If qa-sentinel is "not recognized / command not found" (common on Windows when Python's Scripts folder is not on PATH), use the module form instead, which always works:
python -m qa_sentinel scan path/to/project
Or with Docker (all scanners included):
docker build -t qa-sentinel .
docker run --rm -v "$PWD:/src" qa-sentinel scan /src
Options
qa-sentinel scan [PATH] [-o OUT_DIR] [-f html,json,sarif,md] [--fail-on high] [--min-severity low]
[--only builtin-rules,semgrep] [--skip tests] [--no-tests] [--exclude 'docs/*'] [--config FILE]
Exit codes: 0 no findings at/above --fail-on (default high), 1 threshold exceeded, 2 usage error, so it can gate CI pipelines.
Running tests executes the project's code. Use
--no-tests(or run inside the Docker image) when scanning untrusted repositories.
Configuration (.qa-sentinel.json)
Create a starter file with qa-sentinel init.
{
"exclude": ["docs/*", "*.generated.*"],
"disable": ["semgrep"],
"disable_rules": ["QAS-CFG-002"],
"ignore": ["QAS-QLT-001", "3f2a9c0d1e4b5a6f"],
"severity_overrides": {"QAS-CRY-003": "medium"},
"fail_on": "high",
"test_command": "make test",
"junit_glob": "build/test-results/*.xml",
"semgrep_configs": ["p/default", "p/owasp-top-ten"],
"rules": [
{"id": "CUSTOM-001", "title": "Deprecated internal API", "pattern": "legacy_client\\.",
"languages": ["Python", "JavaScript"], "severity": "low", "category": "quality",
"recommendation": "Migrate to new_client."}
]
}
ignoreaccepts rule IDs or finding fingerprints (shown in the report) to accept known risks.- Inline suppression: add
qa-sentinel: ignore(ornosec) as a comment on the line. rulesadds your own checks for any language or file type.
CI integration
GitHub Actions (uploads SARIF to Code Scanning, writes a job summary, and stores the HTML report as an artifact):
- uses: actions/checkout@v4
- uses: <owner>/qa-sentinel@main
with:
fail-on: high
Any other CI: run the Docker image and archive qa-report/.
Examples
examples/ contains intentionally vulnerable projects (Python/Flask, Node/Express, and a polyglot Java/Go/C/Shell/Terraform/Kubernetes project) to demo the tool:
qa-sentinel scan examples/python-flask-app
Development
pip install -e ".[dev]"
pytest
Adding a scanner: subclass qa_sentinel.scanners.base.Scanner, implement run(project) -> list[Finding], and register it in qa_sentinel/scanners/__init__.py.