Files
sales-trainer/docs/test-evidence/2026-08-15-legacy-security-remediation.md

4.8 KiB

Legacy Security Remediation Evidence — 2026-08-15

Scope

Test-first remediation of the exact-current legacy-security findings from scoped review deleg_a274603c:

  • tenant/group visibility, private-owner authorization, tenant-admin persona mutation, weak-area scope, and group mutation races;
  • JWT required claims, canonical identity, empty-tenant filtering, JSON-store corruption semantics, and fail-closed rate limiting;
  • signed export-token malformed state, CSV formula injection, malformed debrief data, and bounded PDF extraction.

No commit, push, deploy, credential access/rotation, public-access change, or production operation occurred. JSON stores remain runtime-authoritative.

TDD evidence

A new regression module was written before remediation and run against the current tree. The expected RED run produced 18 failures covering the reported behaviors. After the minimal fixes, the same targeted set passed:

backend/.venv/bin/python -m pytest -q backend/tests/test_legacy_security_regressions.py backend/tests/test_weak_area_analysis.py
18 passed

Implemented controls

  • Non-super-admin group indexes require a non-empty tenant and exclude explicit private-owner records; malformed owner markers fail closed.
  • Private-group reuse requires a valid owner/tenant and status=ready; stale records return a controlled conflict through the API.
  • Persona updates use an explicit tenant-admin editable allowlist and hold the group mutation lock across authorization/read/write.
  • Variant generation holds the source-group mutation lock through generation and append; report-build failures persist status=failed.
  • Weak-area analysis requires explicit user_id and org_id scope and ignores sessions outside both boundaries.
  • JWT decoding requires sub, org_id, role, auth_version, iat, and exp; stored id/username identity consistency is required.
  • JSON stores accept and return only object records; corruption propagates as StoreError instead of being silently omitted. Rate limiting remains fail-closed.
  • Export-token reads/consumption handle malformed records as invalid links; CSV formula detection scans leading whitespace/control characters; malformed debrief values produce safe zero scores.
  • PDF extraction is performed in clipped page bands with a raw file-size preflight and a cumulative extracted-character cap.

Verification results

backend/.venv/bin/python -m pytest -q backend/tests
247 passed in 46.55s

backend/.venv/bin/python -m compileall -q backend/app backend/tests
passed

AST parse of backend/app and backend/tests
70 files passed

git diff --check
passed

Added-line security scan
hardcoded_secret=[]
shell_command=[]
dynamic_code=[]
pickle_load=[]
sql_format=[]

Targeted post-remediation security/parser suites also passed:

backend/.venv/bin/python -m pytest -q backend/tests/test_legacy_security_regressions.py backend/tests/test_upload_security.py backend/tests/test_final_review_regressions.py backend/tests/test_weak_area_analysis.py
54 passed in 5.23s

A direct PyMuPDF probe with a multi-page text fixture rejected extraction at the configured character cap. ruff and mypy were unavailable in the verification environment.

Independent review status

The full-scope exact-current review deleg_93ef64c5 timed out after 600 seconds without a complete five-key JSON verdict and is not approval. Replacement batch deleg_df17f04e was stopped because it began before final service-boundary hardening. Final code-freeze batch deleg_6885e5b9 is in progress. This evidence is local verification only and does not close the legacy-security gate until every required scope in final batch deleg_6885e5b9 returns valid JSON with passed=true, empty security_concerns, and empty logic_errors.

Latest post-review remediation evidence (2026-08-15)

The valid exact-current review deleg_4357d521 identified a blocking migration gap: directory-backed rate limiting did not preserve legacy DATA_DIR/ratelimit.json counters. The current tree now migrates that state under a collection lock, preserves the legacy file, fails closed on malformed migration data, and has a regression proving an existing counter still blocks.

Additional current-tree evidence:

Targeted legacy/auth/rate-limit/password suites: 125 passed
Backend full suite: 280 passed
Frontend unit suite: 4 passed
compileall: passed
git diff --check: passed

Three fresh exact-current read-only reviewer scopes were dispatched after the final source change. Their outputs are pending; no incomplete status is approval.

Remaining limits

Docker, PostgreSQL runtime/parity, real-provider LLM QA, browser/mobile QA, authenticated production smoke, deployment, public-access restoration, and credential/JWT rotation remain unperformed and require separate operator approval.