summaryrefslogtreecommitdiff
path: root/app/src
diff options
context:
space:
mode:
authorPeter Stone <thepeterstone@gmail.com>2026-10-28 07:56:40 +0000
committerPeter Stone <thepeterstone@gmail.com>2026-10-28 07:56:40 +0000
commit2c893238914b246cd3f77a20a71bc88399790cb9 (patch)
tree68573100890e0394eb23627df17396ad7b326e0d /app/src
parentf2b5c8f471096ce467c0b606dfaaa88ebf46648a (diff)
Every outbound fetch may only reach a public address
A security review flagged the transcript download as an SSRF: the URL comes from a <podcast:transcript> tag, so a publisher chooses it. It was the third place with that shape, not the first -- the feed fetch takes a URL the phone sent, and the enclosure download takes one from inside the feed, and both had been doing it for longer. Fixing the flagged instance alone would have fixed nothing. The exposure is specific rather than theoretical. listend listens on 127.0.0.1:38090 behind Apache on a host running other services, so a feed naming a loopback, private or link-local address -- 169.254.169.254 among them -- would have the server fetch something only it can reach. In the transcript case the result would then be stored and handed to the phone as an episode's words, which turns an internal reachability problem into a readable one. The check runs when the connection is dialled, not when the URL is read, so it also covers a redirect into an internal address and a hostname that resolves to one. The address connected to is the address that was checked. internal/safefetch now has a structural test that walks this server's own source and refuses any production file that builds its own HTTP client or uses the shared default. It was watched failing against a deliberately added violation before being kept. Tests still inject a plain client through the seam each type already had, because a httptest server is on loopback by definition -- which is exactly what production is now refusing. Checked against the live subscription list before committing: all 44 feeds use https and none resolves to a private, loopback or link-local address, so nothing Peter subscribes to is affected. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018AwnALZL6bD4VBtATDVv3B
Diffstat (limited to 'app/src')
0 files changed, 0 insertions, 0 deletions