PST-085: The page-rendering child process inherits the full environment, including the secret key and database credentials #814

Closed
opened 2026-10-10 10:56:52 +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-085. 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: defence in depth / sandboxing
  • Location: src/postulo/jobs/rendering.py (98-104)
  • Found by: completeness review: chains

Who can do it, and what they need. A malicious web page captured by a member, combined with a hypothetical memory-safety bug in WeasyPrint's text shaping or layout stack (Pango, HarfBuzz, FreeType).

How it works.

  1. A captured page is drawn by WeasyPrint in a child process. The fetcher refuses every URL, so only the page's text and CSS reach the native stack.
  2. If a native-library bug were triggered by crafted text or CSS, code would run as the Postulo user with POSTULO_SECRET_KEY, POSTULO_FIELD_KEY and POSTULO_DATABASE_URL/password in its environment and read access to /app/data (SQLite DB, media).

Impact. No known exploit. The process isolation protects availability but not confidentiality of the instance's secrets if the renderer itself were compromised.

Verification (verdict: confirmed; severity after verification: Informational). Keep informational. Add that env scrubbing alone would not protect the database, media or a .env file in the working directory, because the child runs as the same user. Real containment would need a seccomp or namespace sandbox or a dedicated unprivileged user. The sentence 'The process isolation protects availability but not confidentiality if the renderer itself were compromised' is correct. The affected lines are rendering.py:98-104, not 98-104 plus rendering_child.py:56-76 as a defect, because the child's limits are working as designed.

Suggested remediation. Pass env={} plus the minimal PATH/LANG/fontconfig variables and a throwaway cwd. Consider prctl no_new_privs or seccomp, and bound the captured stderr.

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-085**. 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:** defence in depth / sandboxing - **Location:** `src/postulo/jobs/rendering.py` (98-104) - **Found by:** completeness review: chains **Who can do it, and what they need.** A malicious web page captured by a member, combined with a hypothetical memory-safety bug in WeasyPrint's text shaping or layout stack (Pango, HarfBuzz, FreeType). **How it works.** 1. A captured page is drawn by WeasyPrint in a child process. The fetcher refuses every URL, so only the page's text and CSS reach the native stack. 2. If a native-library bug were triggered by crafted text or CSS, code would run as the Postulo user with POSTULO_SECRET_KEY, POSTULO_FIELD_KEY and POSTULO_DATABASE_URL/password in its environment and read access to /app/data (SQLite DB, media). **Impact.** No known exploit. The process isolation protects availability but not confidentiality of the instance's secrets if the renderer itself were compromised. **Verification** (verdict: confirmed; severity after verification: Informational). Keep informational. Add that env scrubbing alone would not protect the database, media or a .env file in the working directory, because the child runs as the same user. Real containment would need a seccomp or namespace sandbox or a dedicated unprivileged user. The sentence 'The process isolation protects availability but not confidentiality if the renderer itself were compromised' is correct. The affected lines are rendering.py:98-104, not 98-104 plus rendering_child.py:56-76 as a defect, because the child's limits are working as designed. **Suggested remediation.** Pass env={} plus the minimal PATH/LANG/fontconfig variables and a throwaway cwd. Consider prctl no_new_privs or seccomp, and bound the captured stderr.
tiagoagueda added this to the 1.0.0 milestone 2026-10-10 10:58:16 +00:00
Author
Owner

Fixed in e256f3bdc on main.

Fixed in e256f3bdc 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#814
No description provided.