Hardening: POSTULO_CONNECTIONS_ALLOW_PRIVATE is said to cover company logos, which have been public-only since #215 #537

Closed
opened 2026-10-01 10:47:28 +00:00 by tiagoagueda · 1 comment
Owner

Found on 2026-09-29 in a read-only review of postulo at 95348908d and the wiki at de1f52467, checking every outbound request against the client it uses.

Checked again on 2026-10-01 against main at 0a5cad587: still present. The code is now at core/mail.py:165, 180, 240 (host_policy and the two destinations.approve calls); the other locations have not moved.

Hardening says POSTULO_CONNECTIONS_ALLOW_PRIVATE "applies to plugin connections and to company logos", and not to captures and link checks. Logos stopped following the setting in #215: jobs/logos.py now uses the public-only client, which refuses private addresses whatever the setting says. The paragraph also leaves out what the setting does widen besides plugin connections: the Gravatar fetch, the catalogue and consent requests, and the mail servers (the instance's SMTP and a person's own outbox).

  • Where: postulo.wiki/Hardening.md:323-328; jobs/logos.py:109-121 (download, http.public_only_client); accounts/avatars.py:119 (fetch_gravatar, http.client); core/updates.py:51 and plugins/browser/webpush.py:222 (public-only); plugins/catalogue.py:228, 296 and plugins/consent.py:238 (http.client); core/mail.py:175, 190, 250 (destinations.approve under private_allowed()).
  • What happens: an operator turns the setting on so logos can come from an intranet site, as the page says they will, and every logo from a private address is still refused. An operator auditing what the switch opens reads "plugin connections and company logos" and misses Gravatar, catalogues, OAuth token exchanges and mail servers, which it does reach.
  • Why it matters: Hardening is where an operator decides whether to turn this switch on; a wrong list of what it widens is a wrong basis for that decision.
  • Fix: rewrite the paragraph to list the requests that refuse private addresses whatever the setting (captures and their robots.txt, portfolio link checks, company logos, the update check, web push) and the ones the setting widens (plugin connections, catalogues, OAuth token requests, mail servers, Gravatar). Gravatar is public by nature, like logos: consider moving fetch_gravatar to public_only_client by #215's reasoning, and then list it with the public-only ones.

Related to #215 (closed), which moved logos to the public-only client but left this paragraph as it was.

Done when

  • Hardening.md lists the public-only fetches and the ones the setting widens, matching the clients in the code.
  • If Gravatar moves: a test in tests/security/test_outbound.py fails while fetch_gravatar reaches a private address with POSTULO_CONNECTIONS_ALLOW_PRIVATE=true, and passes once it uses public_only_client.
Found on 2026-09-29 in a read-only review of postulo at 95348908d and the wiki at de1f52467, checking every outbound request against the client it uses. Checked again on 2026-10-01 against `main` at `0a5cad587`: still present. The code is now at `core/mail.py:165, 180, 240` (`host_policy` and the two `destinations.approve` calls); the other locations have not moved. *Hardening* says `POSTULO_CONNECTIONS_ALLOW_PRIVATE` "applies to plugin connections and to company logos", and not to captures and link checks. Logos stopped following the setting in #215: `jobs/logos.py` now uses the public-only client, which refuses private addresses whatever the setting says. The paragraph also leaves out what the setting does widen besides plugin connections: the Gravatar fetch, the catalogue and consent requests, and the mail servers (the instance's SMTP and a person's own outbox). - **Where:** `postulo.wiki/Hardening.md:323-328`; `jobs/logos.py:109-121` (`download`, `http.public_only_client`); `accounts/avatars.py:119` (`fetch_gravatar`, `http.client`); `core/updates.py:51` and `plugins/browser/webpush.py:222` (public-only); `plugins/catalogue.py:228, 296` and `plugins/consent.py:238` (`http.client`); `core/mail.py:175, 190, 250` (`destinations.approve` under `private_allowed()`). - **What happens:** an operator turns the setting on so logos can come from an intranet site, as the page says they will, and every logo from a private address is still refused. An operator auditing what the switch opens reads "plugin connections and company logos" and misses Gravatar, catalogues, OAuth token exchanges and mail servers, which it does reach. - **Why it matters:** *Hardening* is where an operator decides whether to turn this switch on; a wrong list of what it widens is a wrong basis for that decision. - **Fix:** rewrite the paragraph to list the requests that refuse private addresses whatever the setting (captures and their `robots.txt`, portfolio link checks, company logos, the update check, web push) and the ones the setting widens (plugin connections, catalogues, OAuth token requests, mail servers, Gravatar). Gravatar is public by nature, like logos: consider moving `fetch_gravatar` to `public_only_client` by #215's reasoning, and then list it with the public-only ones. Related to #215 (closed), which moved logos to the public-only client but left this paragraph as it was. ## Done when - `Hardening.md` lists the public-only fetches and the ones the setting widens, matching the clients in the code. - If Gravatar moves: a test in `tests/security/test_outbound.py` fails while `fetch_gravatar` reaches a private address with `POSTULO_CONNECTIONS_ALLOW_PRIVATE=true`, and passes once it uses `public_only_client`.
tiagoagueda added this to the 0.6.0 milestone 2026-10-01 10:47:28 +00:00
Author
Owner

Fixed in 764cb2195 on main.

Fixed in 764cb2195 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#537
No description provided.