• v0.38.0 866a7afb28

    v0.38.0 Stable

    joeyr released this 2026-08-23 21:30:37 -05:00 | 95 commits to main since this release

    A feed URL'''s redaction kept the one segment that is sometimes the whole secret. Found by reading a real boot log, not by a test: a Canvas subscription printed as https://<school>.instructure.com/…/user_<hash>.ics — the elision worked on the middle of the path and then wrote out the credential.

    Security

    • safe_url now drops the entire path, keeping only scheme, host and a plausible file extension. It kept the last path segment on the reasoning that a capability URL "hides in the path, not the query". That is true of Google'''s secret address, where the secret is a middle segment and basic.ics is generic — and false of Canvas, where the filename IS the secret. Nothing in a URL distinguishes the two, so the rule is now uniform. What this gives up is telling a typo'''d filename from a 404; a typo'''d host still reads clearly, which is the case worth debugging from a log.

    • Feed.fallback_name is redacted too, and it was the worse of the two. It returned the same last path segment, and it does not only reach a log: it becomes Calendar.name for a feed that could not be fetched, so an unreachable Canvas feed would hand its capability URL to list_calendars — into a model'''s context and a transcript.

    • .env.example no longer promises something the code did not do. It told operators a log paste could not leak a feed URL. Anyone who configured a feed whose secret is its filename before this release should regenerate it — a capability URL has no other revocation, and the old value may sit in container logs.

    Testing

    Seven tests cover this and all seven were run against the previous implementation and watched to fail, per A new guard is not proved until it has been broken. The existing suite could not have caught it: every redaction test used the Google shape, where keeping the last segment happens to be safe. 1297 tests green.

    Downloads