abhinavsarkar.net
feed-repeat v1.1: Hosting on GitHub Pages, New Posts Passthrough, SSRF Protection, and More
feed-repeat is a small tool that selects old posts from RSS/Atom feeds you configure and puts them into a new Atom feed. Use it with your feed reader for a spaced-repetition-like experience for blog posts. See the announcement post for the motivation behind it, and more details.
I just released v1.1 of feed-repeat. This release brings some great new features, and improves the security and performance. The biggest highlight: **you can now run feed-repeat entirely on GitHub** , no server needed!
The repo now includes a GitHub Actions workflow that runs feed-repeat daily, and publishes the generated feeds to GitHub Pages. Getting started is simple: fork the repo, edit `config.yaml` with your source feeds, enable the workflow, enable GitHub Pages, and subscribe to the generated feeds in your feed reader. That’s it! The documentation has the full step-by-step guide.
**Passthrough of new entries** : The new `passthroughNewEntries` option passes new entries from a source feed directly to the output feed, turning it into a combined feed of old repeats and new content, so that you can subscribe to only one feed for both old and new posts.
**Authenticated feeds** : URL credentials in source feeds (e.g., `https://token@host/feed`) were previously stripped before sending the HTTP request, breaking authentication for password-protected feeds. This is now fixed — the original URL is preserved as-is, enabling feed-repeat to subscribe to private feeds.
**SSRF protection** : feed-repeat now validates DNS resolution and IP ranges before connecting to source feed URLs, preventing server-side request forgery attacks.
**Persistent conditional fetches** : `ETag` and `Last-Modified` headers from source feeds are now persisted to the cache between runs. This means feed-repeat only downloads a feed when it has actually changed, reducing bandwidth and processing time, and load on feed servers.
**Other notable changes** : The HTTP retry for 5xx errors was fixed — they are now properly retried with exponential backoff. feed-repeat now also handles HTTP 429 responses gracefully, redacts credentials from all log output, deduplicates source feed fetches across tasks, uses per-task cache files (migrated automatically), and supports a configurable `User-Agent` via `--user-agent`.
**Minimum GHC version bumped** : feed-repeat now requires GHC 9.10+, dropping support for GHC 9.6 and 9.8.
See the full changelog for all the details.
If you have any questions or comments, please leave a comment below. If you liked this post, please share it. Thanks for reading!