| Version | Supported |
|---|---|
| 3.0.x | ✅ |
| 2.5.x | ✅ (security only, until 2026-11-01) |
| < 2.5 | ❌ |
dorm follows Semantic Versioning. Patch releases on the latest minor get the full bug-fix flow; the previous minor receives security-only patches for ~6 months after a new minor ships.
Please do NOT file a public GitHub issue for a security vulnerability. Public discussion gives an attacker a window between disclosure and a patched release on PyPI.
Email ricardo.r.f@hotmail.com with:
- A short description of the issue (one paragraph is fine).
- The affected versions (run
python -c "import dorm; print(dorm.__version__)"). - A reproduction case: minimum Python code, model definition, or request that triggers the bug. The smaller, the faster we triage.
- The impact you observed (RCE, SQL injection, data leak, denial-of-service, …) and any constraints on exploitation (auth required, specific backend, …).
We aim to:
- Acknowledge your report within 72 hours.
- Confirm or rule out the issue within 7 days.
- Ship a patched release within 30 days for a confirmed high-severity issue (CVSS ≥ 7.0). Lower-severity fixes ride the next normal patch release.
- Credit you in the release notes unless you ask us not to.
dorm runs Python code that you control plus database drivers, so the hot ORM path is generally not the most fruitful attack surface. A few areas deserve explicit attention in production:
- Cache payload signing is on by default since 2.5.0 — the
queryset cache HMAC-signs every blob before it leaves the
process. Set
CACHE_SIGNING_KEY(or the existingSECRET_KEY) in production; deploy withCACHE_REQUIRE_SIGNING_KEY = Trueso the per-process random fallback is refused. Without a shared key, a multi-worker deployment silently collapses to per-worker visibility — and with a key but writeable Redis, an attacker who can write to Redis gets RCE on every reader. The HMAC closes that window. settings.pyauto-discovery executes Python from the filesystem. Pass--settings=myproj.settings(orDORM_SETTINGS=…) explicitly in production runners and audit container images for straysettings.pyfiles.execute_streaming()refuses to run insideatomic()— server-side cursors need their own transaction. This is by design (the previous silent fallback materialised the whole result set in memory); don't paper over the error by stripping theatomic().dorm.contrib.encryptedciphertexts are bound to a singleFIELD_ENCRYPTION_KEY(or the rotation listFIELD_ENCRYPTION_KEYS). Rotation does not re-encrypt existing rows automatically — schedule a background job to rewrite them through the new primary key once you've decided to retire the old one.dorm lint-migrationsis meant as a CI gate. Run it on every PR that touches a migration; suppression (# noqa: DORM-M00X) should require a reviewer's sign-off so the rule doesn't get silenced by accident.
- Vulnerabilities in upstream packages (psycopg, redis-py, cryptography, …). Report those to their maintainers; we will bump our pins as soon as fixed releases are out.
- Bugs that require an attacker who already has shell access on the server, write access to your settings file, or admin privileges in the database. Those need fixing at the infrastructure layer.
- DoS by configuring a deliberately small
MAX_POOL_SIZEor by issuing pathological queries. Pool sizing and query review are operator concerns.