* Add SSRF mitigations using `filter_var` and `CURLOPT_RESOLVE`
The idea is to prevent FreshRSS from sending any HTTP requests to internal services, except for the ones that are explicitly allowed in the config.
Based on 6e82b46a48/lib/filelib.php (L3818) and https://github.com/symfony/symfony/blob/8.1/src/Symfony/Component/HttpClient/NoPrivateNetworkHttpClient.phphttps://github.com/FreshRSS/simplepie/pull/76https://github.com/FreshRSS/simplepie/pull/78
* Add allowlist setting in Web UI
* make readme
* Update app/i18n/fr/admin.php
Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>
* make readme again
* make readme
* Further work
Still WIP and needs testing etc.
* Readd previous if check for domain combination allowlist
* Turn POST to GET after redirect
* Improve
* Update config.default.php
Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>
* make readme
* Skip SSRF check if `CURLOPT_PROXY` is set
* make readme
* Fix `!empty()` mistake
* Respect max redirects feed option when fetching with `httpGet()`
* Respect max redirects during SimplePie fetching + fix bypass
bypass fix: `CURLOPT_FOLLOWLOCATION` was moved below so that emulated redirects are enforced.
* Avoid FreshRSS and Minz code in SimplePie
https://github.com/FreshRSS/FreshRSS/pull/8400#discussion_r2935375980
* Corrected hook code
* phpdoc wrong return type
* Add CIDR support in allowlist
* Implement simple DNS caching
* Suppress `dns_get_record()` warnings
* A bit of proof-reading
* Minor typo
* Fix proxy logic
* Fix HTTP POST redirect logic
* Proofread checkCIDR
Add fixes for several situations
* Remove credentials from URL in logs
* Ensure `CURLOPT_FOLLOWLOCATION` is `false` by setting it at the end
* Fix codesniffer long line
* Fix potential bypass due to wrong return value
If there were no records returned by `dns_get_record()`, no overrides to `CURLOPT_RESOLVE` would get passed,
and a potential bypass could occur, when cURL would try to resolve the domain by itself.
* Put the URL at the end in logs
* Add documentation and environment variable support
* make readme
* Fix wrong behavior in case of IP
* Fix duplicate selector in CSS
* Minor type check change
* i18n fr, en
* Minor type check change
* Fix whitespace i18n fr
* make fix-all
* Fix `$ips_ok` not being returned after domain records were cached
* make readme
* PHPStan fix
* make readme
* Minor syntax in SimplePie
* Only return `null` if no allowed IPs were found
* Add wildcard *, help message
* Consistent docs with help message
* i18n: pl
* SimplePie compatibility PHP 7.2
* make fix-all
* Sync SimplePie
* https://github.com/FreshRSS/simplepie/pull/76
* 💥 Breaking change in the Changelog
* Document `INTERNAL_HOST_ALLOWLIST` in Docker docs
* Remove `Cookie` and `Authorization` headers in `httpGet()` during cross-origin redirect
* Minor whitespace
And same comment convention than below
* Remove authentication headers and change POST to GET on redirect in SimplePie
* Remove .local in Docker example
* Fill in default ports when comparing URL origins
* Remove .local from other places than the Docker example
* Rewrite WebSub subscribe to use `httpGet()`
* make fix-all
* Also unset `CURLOPT_USERPWD` during redirects
* phpcs fix
* Always unset `CURLOPT_FOLLOWLOCATION`
* Bump SimplePie
https://github.com/FreshRSS/simplepie/pull/78
* Update logic for CURLOPT_FOLLOWLOCATION
* Fix PHPStan
* Changelog fix security section
* Update most common RSS Bridge case
https://hub.docker.com/r/rssbridge/rss-bridge
* Replace misleading 127.0.0.1:8080 example for Docker
This does not make sense for a Docker container
---------
Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>
Add an opt-in CLI that exports each user's database to
`data/users/<user>/sqlite-backups/<YYYYMMDDTHHMMSSZ>.sqlite` (UTC) and
prunes older files to a configured count. Gated by two new settings,
`auto_sqlite_export.enabled` and `auto_sqlite_export.retention`.
Kept separate from `cli/db-backup.php` / `cli/db-restore.php`, which
stay the fixed-filename migration tool. First step of #8183.
Co-authored-by: Bjørn A. Andersen <polybjorn@users.noreply.github.com>
* Use Pdo\Mysql for PHP 8.5+ (and update PHPStan)
fix https://github.com/FreshRSS/FreshRSS/issues/8525
Update PHPStan at the same time due to the need to add new ignore rules.
* Update additional PDO examples
* Show warning when unsafe CSP policy is in use
* Fix bare markdown URL
* i18n: fr
* Minor i18n: fr
* Add target="_blank" to i18n strings
---------
Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>
* Implement sudo mode / reauthentication
* i18n: fr
* generate flags
* Improvements
* Remove HMAC check
* Don't require reauth to access logs when signed in as admin
* Notify user of bad login via notification instead
---------
Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>
* Implement support for HTTP 429 Too Many Requests
Will obey the corresponding HTTP `Retry-After` header at domain level.
* Implement 503 Service Unavailable
* Sanitize Retry-After
* Reduce default value when Retry-After is absent
And make configuration parameter
* Retry-After also for favicons
Closes#3789, #6503
Icon setting when no custom icon is set yet:

- `Change...` button opens a file dialog, and after selecting a file shows the chosen icon in the preview on the left. `Submit` must be clicked after selecting the icon.
- `Reset to default` changes the preview icon to the default one, and also requires `Submit` to be clicked to apply the changes.
Full list of changes:
- CSP now includes `blob:` in `img-src` for
- `indexAction()` and `feedAction()` in `subscriptionController.php`
- all of the view actions in `indexController.php`
- Introduce new attribute `customFavicon (boolean)` for feeds that indicates if the feed has a custom favicon
- `hashFavicon()` in `Feed.php` is dependent on this attribute
- `hashFavicon()` has a new parameter called `skipCache (boolean)` that allows the reset of the favicon hash for the Feed object
- `resetFaviconHash()` just calls `hashFavicon(skipCache: true)`
- `f.php` URLs now have the format of `/f.php?h=XXXXX&t=cachebuster`, where the `t` parameter is only used for serving custom favicons
- if `t` parameter is set, `f.php` returns a `Cache-Control: immutable` header
- `stripos` and `strpos` were changed to `str_contains` in various places (refactor)
- JS for handling the custom favicon configuration logic is in `extra.js` inside `init_update_feed()` which is called when feed configuration is opened from the aside or when the subscription management page with the feed is loaded
- Server-side code for uploading the icon in `subscriptionController.php` under `feedAction()`
- Errors that may occur during the setting of a custom favicon:
- Unsupported image file type (handled only server-side with `isImgMime()`)
- When the file is bigger than 1 MiB (default), handled both client-side and server-side
- Standard feed error when `updateFeed()` fails
- JS vars `javascript_vars.phtml` are no longer escaped with `htmlspecialchars()`, instead with json encoding,
- CSS for disabled buttons was added
- Max favicon file size is configurable with the `max_favicon_upload_size` option in `config.php` (not exposed via UI)
- Custom favicons are currently deleted only when they are either reset to the default icon, or the feed gets deleted. They do not get deleted when the user deletes their account without removing their feeds first.
- ` faviconPrepare()` and `faviconRebuild()` are not allowed to be called when the `customFavicon` attribute is `true`
- New i18n strings:
- `'sub.feed.icon' => 'Icon'`
- `'sub.feed.change_favicon' => 'Change…'`
- `'sub.feed.reset_favicon' => 'Reset to default'`
- `'sub.feed.favicon_changed_by_ext' => 'The icon has been set by the <b>%s</b> extension.'`
- `'feedback.sub.feed.favicon.too_large' => 'Uploaded icon is too large. The maximum file size is <em>%s</em>.'`
- `'feedback.sub.feed.favicon.unsupported_format' => 'Unsupported image file format!'`
- Extension hook `custom_favicon_hash`
- `setCustomFavicon()` method
- `resetCustomFavicon()` method
- `customFaviconExt` and `customFaviconDisallowDel` attributes
- example of usage: https://github.com/FreshRSS/Extensions/pull/337
- Extension hook `custom_favicon_btn_url`
- Allows extensions to implement a button for setting a custom favicon for individual feeds by providing an URL. The URL will be sent a POST request with the `extAction` field set to either `query_icon_info` or `update_icon`, along with an `id` field which describes the feed's ID.
* Pass PHPStan level 8
And prepare for PHPStan level 9 https://phpstan.org/user-guide/rule-levels
* Revert wrong replace in comment
* Fix PHPStan level 8
* Update PHPStan and other dev dependencies
* Remove obsolete comment
* noVariableVariables and towards bleedingEdge
https://github.com/phpstan/phpstan-strict-ruleshttps://phpstan.org/blog/what-is-bleeding-edge
* More bleedingEdge
* A bit more PHPStan level 9
* More PHPStan level 9
* Prepare for booleansInConditions
Ignore int and null
* Revert wrong line
* More fixes
* Fix keep_max_n_unread
* Stricter attribute functions
* Stricter callHooks and more PHPStan level 9
* More typing
* A tiny more
* Increase maximum HTTP request timeout from 2 minutes to 15 minutes;
* Reason: I have some RSS Bridge generating feeds, which can take several minutes.
* Increase default HTTP request timeout from 15 to 20s.
* Reason: I regularly observe feeds, which are slow to answer.
* Custom logo HTML
Add option for custom HTML logo/title in the main Web UI view.
Can potentially be different per user.
#fix https://github.com/FreshRSS/FreshRSS/pull/3830/files#r850472247
* logo_html in main config
With new `./data/config.custom.php` to provide custom values before install
* Docker documentation
* whitespace
* Auto relax CSP to allow images for HTML logo
* Documentation
* Allow many (20k+) feeds
Fix errors such as `SQL error listWhereRaw: ERROR: value "42926" is out of range for type smallint`
Start of UI performance improvements accordingly.
* add HTTP_REMOTE_USER header for auth
* add ip whitelist for HTTP_REMOTE_USER header
* add IPv6 support for header auth
* fix formatting
* A few fixes
* Add some default trusted sources
* Fix IPv6 doc
* More standard header names
Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>
* Use typographic quotes
* A few fixes
* Fix
* Fix not saved
* Implement feedback
* Detail
* Revert spoken English fixes
Left for a future dedicated discussion
* More reverts
* Final reverts
* Final minor
* bump default logout from 30 to 365 days
* * Change cookie duration to constant
* Change cookie duration to three months
* use class
* use 90 days (otherwise login form says 91.3 days)
* change class
* also this works now
Co-authored-by: Martin Rys <martin@rys.pw>
Co-authored-by: Frans de Jonge <fransdejonge@gmail.com>
* Add auto-registration when using http_auth
* Document HTTP auth auto-registration
* Check email variable for HTTP auth auto-registration
* Auto-create HTTP users by default
* Fix Context init
(I will provide in another PR a better fix requiring a bit of global refactoring)
* Init language
Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>
* Add an email field to the profile page
I reuse the `mail_login` from the configuration. I'm not sure if it's
useful today (I would say it was used when Persona login was available).
A good improvement would be to rename `mail_login` into `email` so it
would be more intuitive to use.
* Add boolean to the conf to force email validation
This commit only adds a configuration item.
* Add email during registration if email must be validated
* Set email token to validate when email changes
* Block access to FreshRSS if email is not validated
* Send email when address is changed
* Allow to resend the validation email
* Allow the user to change its email while blocked
* Document the email validation feature
* fixup! Allow the user to change its email while blocked
* tec: Autoload PHPMailer lib
* Validate email address format
* Add feedback on validation email resend action
* Allow to logout when user is blocked
* fix: Change default email "from"
* Reorganize i18n keys
* Complete all the locales with default english
* Hide sidebar (profile page) if email is not validated
* Check email requirements on registration
* Allow admin to specify email when creating users
* Don't check email format if value is empty
* Remove trailing comma in userController
Co-Authored-By: Alexandre Alapetite <alexandre@alapetite.fr>
* Set PHPMailer validator to html5 before sending email
* fixup! Remove trailing comma in userController
* Add Minz_View::_path method (replace change_view)
The `_path` method is more powerful since it allows to choose the file
extension. It is also Minz_Request-agnostic, which is useful to reuse
the Minz_View class in other places.
`change_view` is now deprecated and a warning is logged if we use it.
* Provide a Minz_Mailer to send emails
It uses PHPMailer under the hood and only supports PHP >= 5.5
* New extension event + Tumblr GDPR
https://github.com/FreshRSS/FreshRSS/issues/1894
simplepie_before_init event
* Refactor extension enabling + Tumblr GDPR enabled by default
Add possibility for extensions to be enabled by default, and disabled
back by users.
* Minor whitespace