PST-068: Administrators and the log collector can read members' activity (hosts, captured addresses, file names) in the logs #797

Closed
opened 2026-10-10 10:56:39 +00:00 by tiagoagueda · 1 comment
Owner

Found in the security audit of 2026-10-10 (SECURITY-AUDIT-2026-10-10.md), run against main at c30851b from 8 to 10 October 2026, as PST-068. Severity: Informational.

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.


  • Severity: Informational
  • Category: logging-of-personal-data
  • Location: src/postulo/plugins/registry.py (454,479); src/postulo/documents/scrub.py (103-121); src/postulo/core/server_views.py (506-540)
  • Found by: completeness review: recent changes, information disclosure, ownership review of core
  • Related: PST-004 (#733)

Who can do it, and what they need. An administrator reading Server settings → Logs, or a holder of POSTULO_LOGS_TOKEN. Precondition: a member captures a posting whose source raises, or a logo fetch fails — ordinary events on any instance.

How it works.

A member captures https://careers.example-employer.com/job/123 and a source plugin raises; logger.exception("Capture source %r failed on %r", source.name, url) writes the URL (and logger.exception("Could not list the places on %r", url), logger.warning("Filling gaps with %s failed on %r", ..., url)). Find logo on a company writes logger.info("Logo for %s: %s", host, problem). These lines appear on the administrator's Logs page and in the NDJSON handed to a collector. The Logs page acknowledges this ("These records can name people and their applications"), but the threat model's row for administrators says they "see accounts, never anyone's applications or documents".

Impact. An administrator (or an external collector) learns which employers' postings a member is capturing and which companies they record — a record of the person's job search — contradicting the documented administrator boundary. Limited scope: only failing captures/logo fetches, and the reader is trusted.

Verification (verdict: confirmed; severity after verification: Informational; first-pass claim: Low). File and line references are accurate (registry.py:454 and :479, builtin/init.py:498, logos.py:428). Correct the characterisation. The threat-model line that Server settings shows administrators "accounts, never anyone's applications or documents" is about the accounts and records pages. The Logs page and /logs endpoint are explicitly carved out by the project's own warnings and docstrings, so there is no contradiction with the documented boundary. The only readers are an administrator, who is trusted with the database anyway, and an operator-configured collector holding POSTULO_LOGS_TOKEN. …

Suggested remediation. Log the capture id and the source name rather than the URL (the review page already shows the URL to its owner), and the company pk rather than the host for logo problems; or reduce such lines to DEBUG so they reach neither the file nor the page by default.

Also covered by this issue.

  • Scheduled orphan sweep writes member-chosen upload file names to the staff-readable log at INFO (src/postulo/documents/scrub.py (103-121); Informational). A person's upload file name can be a name, a document type or a health or union reference, plus the owner id. It reaches people the project says should only see account metadata. …
  • Administrator Logs page and /logs endpoint expose members' activity (company hosts, captured addresses, account ids) (src/postulo/core/server_views.py (506-540); Informational). A limited contradiction of 'administrators see accounts, never anyone's applications or documents': the log names companies and job-posting addresses a member is pursuing, though not the member's name on the same line. …
Found in the security audit of 2026-10-10 (`SECURITY-AUDIT-2026-10-10.md`), run against `main` at `c30851b` from 8 to 10 October 2026, as **PST-068**. Severity: **Informational**. 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. --- - **Severity:** Informational - **Category:** logging-of-personal-data - **Location:** `src/postulo/plugins/registry.py` (454,479); `src/postulo/documents/scrub.py` (103-121); `src/postulo/core/server_views.py` (506-540) - **Found by:** completeness review: recent changes, information disclosure, ownership review of core - **Related:** PST-004 (#733) **Who can do it, and what they need.** An administrator reading Server settings → Logs, or a holder of POSTULO_LOGS_TOKEN. Precondition: a member captures a posting whose source raises, or a logo fetch fails — ordinary events on any instance. **How it works.** A member captures `https://careers.example-employer.com/job/123` and a source plugin raises; `logger.exception("Capture source %r failed on %r", source.name, url)` writes the URL (and `logger.exception("Could not list the places on %r", url)`, `logger.warning("Filling gaps with %s failed on %r", ..., url)`). `Find logo` on a company writes `logger.info("Logo for %s: %s", host, problem)`. These lines appear on the administrator's Logs page and in the NDJSON handed to a collector. The Logs page acknowledges this ("These records can name people and their applications"), but the threat model's row for administrators says they "see accounts, never anyone's applications or documents". **Impact.** An administrator (or an external collector) learns which employers' postings a member is capturing and which companies they record — a record of the person's job search — contradicting the documented administrator boundary. Limited scope: only failing captures/logo fetches, and the reader is trusted. **Verification** (verdict: confirmed; severity after verification: Informational; first-pass claim: Low). File and line references are accurate (registry.py:454 and :479, builtin/__init__.py:498, logos.py:428). Correct the characterisation. The threat-model line that Server settings shows administrators "accounts, never anyone's applications or documents" is about the accounts and records pages. The Logs page and /logs endpoint are explicitly carved out by the project's own warnings and docstrings, so there is no contradiction with the documented boundary. The only readers are an administrator, who is trusted with the database anyway, and an operator-configured collector holding POSTULO_LOGS_TOKEN. … **Suggested remediation.** Log the capture id and the source name rather than the URL (the review page already shows the URL to its owner), and the company pk rather than the host for logo problems; or reduce such lines to DEBUG so they reach neither the file nor the page by default. **Also covered by this issue.** - **Scheduled orphan sweep writes member-chosen upload file names to the staff-readable log at INFO** (`src/postulo/documents/scrub.py` (103-121); Informational). A person's upload file name can be a name, a document type or a health or union reference, plus the owner id. It reaches people the project says should only see account metadata. … - **Administrator Logs page and /logs endpoint expose members' activity (company hosts, captured addresses, account ids)** (`src/postulo/core/server_views.py` (506-540); Informational). A limited contradiction of 'administrators see accounts, never anyone's applications or documents': the log names companies and job-posting addresses a member is pursuing, though not the member's name on the same line. …
tiagoagueda added this to the 1.0.0 milestone 2026-10-10 10:58:04 +00:00
Author
Owner

Fixed in 0c655eacb on main.

Fixed in 0c655eacb on main.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
Postulo/postulo#797
No description provided.