{"id":"CVE-2026-55598","kind":"vulnerability","aliases":["CVE-2026-55598"],"related":[],"title":"PinePods: podcast feed enclosures let users reach internal services","description":"PinePods is a complete, self-hosted podcast management system written in Rust. Prior to 0.9.0, an authenticated user can subscribe to an attacker-controlled RSS feed through `POST /api/data/add_podcast` in `rust-api/src/handlers/podcasts.rs`. `get_podcast_values` and `add_episodes` in `rust-api/src/database.rs` parse the feed with `feed-rs` and store the `<enclosure url>` verbatim in `Episodes.episodeurl` without destination host/IP validation. `POST /api/data/download_podcast` invokes `spawn_download_podcast_episode` and `download_episode_and_wait()` in `rust-api/src/services/tasks.rs`, which sends a `reqwest` GET to the stored URL and saves and records the response in `DownloadedEpisodes` for later retrieval. The `estimate_duration_from_audio_url_async()` path in `rust-api/src/database.rs` also sends an unvalidated HEAD during feed add/refresh. Default redirect following permits an initially external enclosure URL to redirect to an internal target. A low-privilege user can make server-side GET/HEAD requests to reachable loopback, private-network and cloud metadata services and read downloaded internal responses, enabling internal-service enumeration, confidential-data disclosure and possible metadata credential theft. Episode downloading requires server downloads to be enabled, which is the default; self-service signup is supported. This issue is fixed in version 0.9.0.","summary":"PinePods, a self-hosted podcast manager written in Rust, fetches podcast enclosure URLs from user-added RSS feeds without checking the destination host. A logged-in user can make the server request loopback, private-network and cloud metadata addresses and read the responses it saves.","severity":"critical","cvss":9.1,"epss":null,"exploited":false,"exploited_at":null,"products":[],"ecosystems":[],"tags":["cloud-metadata","package","pinepods","rust","self-hosted"],"not_affected_if":["downloads-disabled","fixed-0.9.0","no-user-accounts"],"how_to_check":"- Check the PinePods version the server runs; versions before `0.9.0` are affected.\n- Confirm whether episode downloads are enabled on the server (on by default, per the sources).\n- Check whether self-service signup is open, since any account can add a feed.","fix":"- Upgrade PinePods to `0.9.0` or later.","status":"open","published_at":"2026-10-30T20:17:10+00:00","first_seen_at":"2026-10-30T20:25:38+00:00","triaged_at":"2026-10-30T20:26:10+00:00","updated_at":"2026-10-30T20:26:10+00:00","category":"package","confidence":0.8,"triage":{"at":"2026-10-30T20:26:10Z","model":"claude-haiku-5-5","output":{"fix":"- Upgrade PinePods to `0.9.0` or later.","reach":"network","title":"PinePods: podcast feed enclosures let users reach internal services","impact":"high","summary":"PinePods, a self-hosted podcast manager written in Rust, fetches podcast enclosure URLs from user-added RSS feeds without checking the destination host. A logged-in user can make the server request loopback, private-network and cloud metadata addresses and read the responses it saves.","audience":"businesses","category":"package","nicknames":[],"who_cares":["pinepods","self-hosted","rust","cloud-metadata"],"confidence":0.8,"fix_status":"available","needs_auth":"yes","worst_case":"Server reads cloud metadata credentials and internal service responses","analyst_note":"","how_to_check":"- Check the PinePods version the server runs; versions before `0.9.0` are affected.\n- Confirm whether episode downloads are enabled on the server (on by default, per the sources).\n- Check whether self-service signup is open, since any account can add a feed.","plain_action":"","needs_analyst":false,"not_affected_if":["fixed-0.9.0","downloads-disabled","no-user-accounts"],"who_is_affected":"Self-hosted PinePods instances below 0.9.0 where users can add podcast feeds and episode downloads are enabled, which is the default. Any authenticated account can trigger the server-side requests, and self-service signup makes that easy to get. Managed hosting that does not run PinePods itself, and instances already on 0.9.0 or later, can skip it.","user_interaction":"no","needs_special_setup":"no","severity_if_unknown":"high"},"cost_usd":0.000739,"input_tokens":4516,"output_tokens":574,"severity_before":"critical"},"analyst_status":null,"analyst_note":null,"search":"'-2026':11A,14A '-55598':12A,15A '/api/data/add_podcast':104C '/api/data/download_podcast':139C '/src/database.rs':120C,187C '/src/handlers/podcasts.rs':109C '/src/services/tasks.rs':154C '0.9.0':89C,276C 'add':42B,114C 'add/refresh':195C 'address':67B 'also':188C 'api':108C,119C,153C,186C 'async':181C 'attack':98C 'attacker-control':97C 'audio':179C 'authent':91C 'check':46B 'cloud':17B,65B,230C 'cloud-metadata':16B 'complet':77C 'confidenti':244C 'confidential-data':243C 'control':99C 'credenti':250C 'cve':10A,13A 'data':245C 'default':196C,263C 'destin':48B,135C 'disclosur':246C 'download':142C,146C,235C,253C,256C 'downloadedepisod':171C 'durat':177C 'enabl':238C,259C 'enclosur':4A,37B,203C 'enumer':242C 'episod':115C,144C,147C,252C 'episodes.episodeurl':133C 'estim':176C 'extern':202C 'feed':3A,44B,101C,123C,126C,194C 'feed-r':125C 'fetch':35B 'fix':273C 'follow':198C 'get':110C,159C 'get/head':221C 'head':192C 'host':24B,29B,49B,80C 'host/ip':136C 'initi':201C 'intern':8A,209C,236C,240C 'internal-servic':239C 'invok':140C 'issu':271C 'later':173C 'let':5A 'log':52B 'logged-in':51B 'loopback':60B,225C 'low':213C 'low-privileg':212C 'make':56B,217C 'manag':31B,82C 'metadata':18B,66B,231C,249C 'network':63B,228C 'packag':19B 'pars':121C 'path':182C 'permit':199C 'pinepod':1A,20B,25B,74C 'podcast':2A,30B,36B,81C,111C,143C 'possibl':248C 'post':103C,138C 'prior':87C 'privat':62B,227C 'private-network':61B,226C 'privileg':214C 'reach':7A 'reachabl':224C 'read':69B,234C 'record':167C 'redirect':197C,206C 'request':59B,222C 'requir':254C 'reqwest':158C 'respons':71B,169C,237C 'retriev':174C 'rs':127C 'rss':43B,100C 'rust':21B,34B,86C,107C,118C,152C,185C 'rust-api':106C,117C,151C,184C 'save':73B,165C 'self':23B,28B,79C,265C 'self-host':22B,27B,78C 'self-servic':264C 'send':156C,189C 'server':58B,219C,255C 'server-sid':218C 'servic':9A,232C,241C,266C 'side':220C 'signup':267C 'spawn':141C 'store':129C,162C 'subscrib':94C 'support':269C 'system':83C 'target':210C 'theft':251C 'unvalid':191C 'url':38B,163C,180C,204C 'user':6A,41B,54B,92C,215C 'user-ad':40B 'valid':137C 'valu':112C 'verbatim':131C 'version':275C 'wait':149C 'without':45B,134C 'written':32B,84C","nicknames":[],"mitigations":[],"who_affected":"Self-hosted PinePods instances below 0.9.0 where users can add podcast feeds and episode downloads are enabled, which is the default. Any authenticated account can trigger the server-side requests, and self-service signup makes that easy to get. Managed hosting that does not run PinePods itself, and instances already on 0.9.0 or later, can skip it.","tier":"B","verified":{},"analyst_revisit_at":null,"fix_status":"available","audience":"businesses","plain_action":null,"first_public_at":"2026-10-30T20:17:10+00:00","kev":null,"cvss_vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:L/A:L","cvss_by":"security-advisories@github.com","poc_count":0,"sources":[{"source":"nvd","external_id":"CVE-2026-55598","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-55598","severity":null,"published_at":"2026-10-30T20:17:10+00:00","modified_at":"2026-10-30T20:17:10+00:00","first_seen_at":"2026-10-30T20:25:38+00:00","fetched_at":"2026-10-30T20:25:38+00:00","note":null}],"documents":[],"notice":"Free to read at a human pace. An API with keys and an MCP server are in preparation; early access: hello@infrastack.ai"}