PST-040: Other crafted inputs that crash with an unhandled exception #769
Labels
No labels
accessibility
authentication
breaking change
bug
documentation
enhancement
interface
internationalisation
observability
performance
security
tier
1
tier
2
tier
3
tier/4
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
Postulo/postulo#769
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Found in the security audit of 2026-10-10 (
SECURITY-AUDIT-2026-10-10.md), run againstmainatc30851bfrom 8 to 10 October 2026, as PST-040. Severity: Low.The text below is the audit's entry, unchanged apart from links to the other issues it names. The finding was produced by automated review and checked by a second automated pass; re-check it before acting on it.
src/postulo/core/kind_files.py(kind_files.py:405-442);src/postulo/core/cells.py(cells.py:94-102);src/postulo/documents/views.py(1083-1097)Who can do it, and what they need. A third party who hands a member a JSON file for one of the four kinds (companies, contacts, listings, applications) or a member who edits an export; the victim is the member who uploads it.
How it works.
Impact. A hostile or merely malformed file disables that import page for the session (a persistent 500, not a one-off). Only the uploader is affected; nothing is written. The candidate file path, fuzzed with 35 leaves and 21 hostile values, does not have this problem.
Evidence.
Verification (verdict: confirmed; severity after verification: Low). Two corrections to the report. First, dicts do not reach the form: file_review.kept() flattens them to [], which becomes a 'this is not text' problem message with no crash. Only ints and bools reach the date field, and only the date fields of the four kinds are affected (posted_at for listings, and the date fields of applications and the other kinds go through the same path). Second, the date crash is more general than listings: exported_at in the header crashes the review page for all four kinds. Recovery is POST action=forget, sign-out and sign-in, or session expiry. Suggested fix: reject non-str, non-None values in _through_the_form() (treat int and bool like list), and wrap _moment() in try/except ValueError.
Suggested remediation. Validate every held value's type when the file is read (text, or a string matching the date shape) and drop or refuse the row there; wrap _moment in try/except; have the review view catch exceptions from plan() and offer the 'forget' form instead of a 500.
Also covered by this issue.
src/postulo/core/cells.py(cells.py:94-102); Informational). 500 on the member's own cell edit; the docstring promises an unreadable stamp is treated as not moved. Nothing crosses accounts. A far-future aware stamp makes the conflict check pass, which only defeats the member's own stale-edit warning.src/postulo/documents/views.py(1083-1097); Informational). No injection (Django refuses the header). A confusing 500 and a spent send allowance for the person who typed the subject.Fixed in
ec01219beon main.