v0.0.55
Pain001 Release v0.0.55
Release Date: 2026-07-18
Tag: v0.0.55
Python: 3.10+
Status: Stable
Executive Summary
A security-hardening release. It closes every open code-scanning and
Dependabot finding: three py/path-injection alerts in the REST API's job
store, the mkdir sink in the generation path, an import-style note, and the
mcp < 1.28.1 advisory. No behavioural change to valid requests.
What's in v0.0.55 at a glance
- Path-injection hardening (
pain001/api/job_store.py): job identifiers
now pass a strict token guard (^[A-Za-z0-9][A-Za-z0-9_-]{0,127}$,
fullmatch, raisingValueError) before they are ever used to build a
filesystem path or a Redis key.FileJobStoreadditionally resolves the
candidate withos.path.realpathand enforces a
commonpath == base+startswith(base + os.sep)containment barrier — the
canonical CWE-22 sanitiser the CodeQLpy/path-injectionquery recognises.
job_idoriginates from theGET /api/status/{job_id}route parameter, so
this is a real defence, not only a static-analysis nicety. - Output-directory sink (
pain001/api/app.py): the canonicalised path
returned by_gate_output_dirnow carries the recognised
startswith(base + os.sep)containment check alongside the existing
commonpathequality, so the value flowing intomkdirclears the query
natively (no reliance on the CodeQL model pack). - Import hygiene: collapsed a duplicate
import pain001/
from pain001 import …in the SEPA B2B profile test into a single import. - Dependency:
mcpraised to>=1.28.1,<2(Dependabot HIGH);poetry.lock
resolvesmcp1.28.1.pip-auditreports no known vulnerabilities.
Quality
- 1,324 tests passing, 100% line + branch coverage against a 100% enforced
floor. - mypy
--strictclean, 100% docstring coverage (interrogate), bandit clean. - New regression tests cover the job-id guard (traversal / separators /
leading-dot / empty rejected; UUIDs and safe tokens accepted) for both the
file-backed and Redis-backed stores.
Upgrade notes
No API or configuration changes. Callers that were (incorrectly) relying on
job identifiers containing path separators will now receive a ValueError;
use plain identifier tokens (UUIDs are ideal).