64 Commits

Author SHA1 Message Date
Fred 1d10e7a089 fix(config): accept spaces and trailing commas in list option values
MEDIA_PROXY_RESOURCE_TYPES and TRUSTED_REVERSE_PROXY_NETWORKS were
validated by splitting the raw value without trimming, while the parser
trims items and skips empty ones. Values such as "image, video" or
"192.168.0.0/16, 10.0.0.0/8", and lists with a trailing comma, failed
startup even though the parser accepts them.

Validate the parsed list instead, and reject values that contain no
items at all so that a comma-only value cannot silently clear the
default media proxy resource types.
2026-07-21 21:22:35 -07:00
Fred 308e1f966c fix(config): reject non-positive SCHEDULER_ENTRY_FREQUENCY_FACTOR values
SCHEDULER_ENTRY_FREQUENCY_FACTOR was the only scheduler option without a
validator, so 0 was accepted at startup. With the entry_frequency polling
scheduler, the factor is used as part of a divisor in ScheduleNextCheck,
and a feed with weekly entries then triggered a division-by-zero panic
inside a background worker, crashing the daemon.

Require the factor to be >= 1, matching the validation of the other
scheduler options, so the misconfiguration fails at startup instead.
2026-07-20 20:54:54 -07:00
Frédéric Guillot 9702c6269f feat(config): allow disabling local auth without user creation
Lift the validation that rejected DISABLE_LOCAL_AUTH=1 combined with
OAUTH2_USER_CREATION=0 or AUTH_PROXY_USER_CREATION=0. Admins can now
pre-create users and forbid auto-registration while still forcing all
logins through OAuth2 or an auth proxy.

Fixes: #3163
2026-04-17 19:14:19 -07:00
Frédéric Guillot b160f92ff8 refactor(config): move cross-field validation into config parser
Move option combination checks from cli.go into an exported
Validate() method on configOptions, called after both config file
and environment variable parsing complete. Add new checks for
TLS, metrics auth, database pool, and scheduler interval consistency.
2026-03-27 18:14:58 -07:00
Frédéric Guillot f9b756ecf8 feat: add SSRF protection for integration HTTP clients
Add a shared HTTP client factory that blocks connections to private
network addresses at connect time via a custom DialContext, preventing
SSRF and DNS-rebinding attacks.

A new INTEGRATION_ALLOW_PRIVATE_NETWORKS option (default: false)
controls this behavior. Integrations targeting fixed external services
(Telegram, Archive.org, Pinboard, Notion, Instapaper) skip the check.
2026-03-01 21:56:41 -08:00
Frédéric Guillot 26824211aa feat: add FETCHER_ALLOW_PRIVATE_NETWORKS option
Block outbound requests to private networks made by the fetcher
by default. The restriction now applies to all outgoing requests
performed by the fetcher.

Previous PR #3947 intentionally enforced this restriction only
for the media proxy and icon fetching, considering the
self-hosted nature of Miniflux.
2026-02-28 21:12:15 -08:00
eyjhb f19fc2ff53 feat: add validation for TRUSTED_REVERSE_PROXY_NETWORKS config
Currently if the IP is not in CIDR notation it will just silently
fail, which can be very confusing. This commit changes that, as well
as adds a test.
2026-02-08 14:19:37 -08:00
Frédéric Guillot e54e6c097c feat(config)!: deprecate FILTER_ENTRY_MAX_AGE_DAYS config option
This option can be replaced with a filter rule `max-age:<duration>` instead.

Global environment variables should be reserved for the Miniflux process
configuration that are not meant to be modified by end users.
2026-01-08 20:28:01 -08:00
Frédéric Guillot 561389da69 feat: add TRUSTED_REVERSE_PROXY_NETWORKS config option
Add an IP-based allow list to prevent spoofing of HTTP headers that
should only be set by trusted reverse proxies.

Note that `TRUSTED_REVERSE_PROXY_NETWORKS` must be configured when
`AUTH_PROXY_HEADER` is used.

The following HTTP headers are taken into consideration only when the
client is an allowed reverse proxy: `X-Forwarded-For`,
`X-Forwarded-Proto` and `X-Real-Ip`.
2026-01-04 11:10:46 -08:00
Frédéric Guillot 29f6dc8896 feat(icon): disallow fetching icon on private networks
This change avoid possible SSRF issues and it's configurable at the instance level
2025-12-29 11:15:44 -08:00
Frédéric Guillot 6c83e8c477 feat(mediaproxy): disallow the media proxy to fetch resources on private networks
This change avoid possible SSRF issues and it's configurable at the instance level
2025-12-29 11:15:44 -08:00
Julien Voisin 473c9f225e refactor(config): reuse validateChoices in validateListChoices to avoid duplication 2025-12-28 17:10:20 -08:00
jvoisin 854985bcfa refactor(config): visibility reduction and assorted changes
- Don't expose struct members unnecessarily
- Don't use `fmt.Fprintf` to format strings
- Don't check if a value needs to be redacted if it's empty
2025-12-20 16:55:58 -08:00
Julien Voisin 4063ca39c9 feat(config): add new option to disable Miniflux's API 2025-12-04 17:43:08 -08:00
jvoisin dd44fbcc76 refactor(misc): replace fmt.Errorf with errors.New where possible
No need to to invoke the whole Printf machinery for constant strings. While
this shouldn't have an impact on memory consumption nor allocation (as
constructing errors to return is never in a hot path), this should reduce a bit
the code size, as errors.New will be inlined to a simple struct initialization
instead of a function call.
2025-10-06 17:54:04 -07:00
Frédéric Guillot 5e607be86a refactor(config): rewrite config parser
This PR refactors the configuration parser, replacing the old parser implementation with a new, more structured approach that includes validation and improved organization.

Key changes:
- Complete rewrite of the configuration parser using a map-based structure with built-in validation
- Addition of comprehensive validator functions for configuration values
- Renamed numerous configuration getter methods for better consistency
2025-09-14 10:51:04 -07:00
Frédéric Guillot e8f5c2446c fix(config): FORCE_REFRESH_INTERVAL duration should be in minutes
Regression introduced in commit c6536e8
2025-08-25 15:46:10 -07:00
gudvinr 983291c78b refactor(cli): use time.Duration for cleanup tasks 2025-08-20 19:45:24 -07:00
gudvinr 7060ecc163 refactor(cli): use time.Duration for scheduler frequency
Polling frequency is undocumented so it's not exacly clear what units were.
2025-08-20 19:45:24 -07:00
gudvinr 4af12a4129 refactor(metric): use time.Duration for refresh duration 2025-08-20 19:45:24 -07:00
gudvinr c6536e8d90 refactor(http): use time.Duration for refresh interval
It's not clear which units of time used for refresh interval.
Convert to time.Duration for clarity.
2025-08-20 19:45:24 -07:00
gudvinr 30453ad7ec refactor(fetcher): use time.Duration for client timeout values
All functions use time.Duration, so instead of converting everywhere, do it once.
2025-08-20 19:45:24 -07:00
gudvinr 71af68becd refactor(server): use time.Duration for timeout values
Instead of converting at the very last moment,
it's simpler and more readable to use time.Duration ASAP.
2025-08-20 19:45:24 -07:00
gudvinr ed3bf59356 refactor(reader): use time.Duration instead of minutes count
In general, duration is used as time unit representation.

At some places when int is returned, there's no documentation which unit is used.

So just convert to time.Duration ASAP.
2025-08-20 19:45:24 -07:00
gudvinr 03021af53c feat(config): time interval parser
Simplifies handling of time intervals in config values.
2025-08-20 19:45:24 -07:00
gudvinr ce6cadc176 refactor(mediaproxy): use *url.URL for MEDIA_PROXY_CUSTOM_URL
Same behaviour as for HTTP_CLIENT_PROXY.
2025-08-15 18:12:44 -07:00
gudvinr ab26a4e20f refactor(config): fix typos in test 2025-08-15 16:24:48 -07:00
Frédéric Guillot 34499b887b feat: add POLLING_LIMIT_PER_HOST to limit concurrent requests per host
Each batch of feeds sent to the worker pool is now guaranteed to contain unique feed URLs.

When `POLLING_LIMIT_PER_HOST` is set, an additional limit is applied to the number of concurrent requests per hostname, helping to prevent overloading a single server.

Note: Additional requests may still be made during feed refresh. For example, to fetch feed icons or when the web scraper is enabled for a particular feed.
2025-08-08 12:33:46 -07:00
Julien Voisin 566670cc06 refactor: unexport symbols 2025-08-07 17:27:04 -07:00
Frédéric Guillot 80f48c88c7 refactor: replace interface{} with any 2025-08-05 20:26:07 -07:00
Julien Voisin 078eb39db9 refactor(config): don't check random.Read's return value
As stated in the documentation:

> Read calls io.ReadFull on Reader and crashes the program irrecoverably if an
error is returned. The default Reader uses operating system APIs that are
documented to never return an error on all but legacy Linux systems.
2025-07-31 18:03:53 -07:00
jvoisin 61583d53d5 refactor(config): simplify SortedOptions
Make use of the slices and maps packages instead of doing things by hand,
and pre-allocated sortedOptions.
2025-07-09 19:29:53 -07:00
jvoisin 7c42e777ec refactor(config): minor improvements of the config parser
- Surface the faulty line number when trying to parse it
- Use strings.Cut instead of strings.SplitN
- Use strings.TrimSuffix instead of an if
- Simplify parseStringList and make its code more compact
2025-07-09 19:28:02 -07:00
jvoisin 24043ece07 refactor(config): unexport some symbols 2025-07-07 16:01:21 -07:00
jvoisin 052e8dd0aa refactor(config): remove two unused constants 2025-07-07 15:45:20 -07:00
Ingmar Stein 8fa5041c37 feat: Allow multiple listen addresses
This change implements the ability to specify multiple listen addresses.
This allows the application to listen on different interfaces or ports simultaneously,
or a combination of IP addresses and Unix sockets.

Closes #3343
2025-06-20 12:46:34 -07:00
Frédéric Guillot d291d6a74d refactor(config): remove deprecated config options 2025-06-15 14:42:28 -07:00
Frédéric Guillot e0f7e6f2a8 feat(config)!: remove SERVER_TIMING_HEADER config option
BREAKING CHANGE: This option is not really useful and it's used only on
the unread page.
2025-06-15 14:17:28 -07:00
jvoisin 117c031f1c feat(integration)!: remove Pocket integration
BREAKING CHANGE: Pocket will no longer be available after July 8, 2025.

https://support.mozilla.org/en-US/kb/future-of-pocket#w_when-is-pocket-shutting-down
2025-06-15 13:29:55 -07:00
Frédéric Guillot ac44507af2 refactor(sanitizer): use a map for iframe allow list 2025-06-13 21:05:23 -07:00
Frédéric Guillot c87c93d85f feat(config): add SCHEDULER_ROUND_ROBIN_MAX_INTERVAL option
Add option to cap maximum refresh interval when RSS TTL, Retry-After, Cache-Control, or Expires headers specify excessively high values.
2025-04-11 15:40:32 -07:00
Frédéric Guillot 535fd050b7 feat: add proxy rotation functionality 2025-04-06 14:59:00 -07:00
Frédéric Guillot e342a4f143 fix: address minor issues detected by Go linters 2025-03-24 20:48:46 -07:00
telnet23 7e2b50efee feat: optionally fetch watch time from YouTube API instead of website 2024-12-07 16:00:35 -08:00
Finn 6feee555ba feat: allow customizing the display name of the OpenID Connect provider 2024-08-12 22:05:15 -07:00
Finn 770cc1dbb3 feat: Add option to disable local auth form 2024-08-12 19:27:08 -07:00
Qeynos bcbf9f4025 feat: add FETCH_BILIBILI_WATCH_TIME config option 2024-08-01 19:52:31 -07:00
Frédéric Guillot d048d59d39 fix: use BASE_URL instead of r.Host to generate absolute media proxy URL 2024-07-29 16:04:31 -07:00
fin444 a631bd527d options: add FETCH_NEBULA_WATCH_TIME 2024-05-02 16:30:01 -07:00
Frédéric Guillot c2311e316c Rename PROXY_* options to MEDIA_PROXY_* 2024-03-20 21:28:28 -07:00