Files
FreshRSS/app/i18n/fa/admin.php
Inverle dcec27c69d Add SSRF mitigations using filter_var and CURLOPT_RESOLVE (#8400)
* 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.php

https://github.com/FreshRSS/simplepie/pull/76
https://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>
2026-06-28 18:51:04 +02:00

166 lines
8.4 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
/******************************************************************************
* Each entry of that file can be associated with a comment to indicate its *
* state. When there is no comment, it means the entry is fully translated. *
* The recognized comments are (comment matching is case-insensitive): *
* + TODO: the entry has never been translated. *
* + DIRTY: the entry has been translated but needs to be updated. *
* + IGNORE: the entry does not need to be translated. *
* When a comment is not recognized, it is discarded. *
******************************************************************************/
return array(
'auth' => array(
'allow_anonymous' => ' اجازه خواندن ناشناس مقالات کاربر پیش‌فرض (%s)',
'allow_anonymous_refresh' => ' اجازه بازخوانی ناشناس مقالات را بدهید',
'api_enabled' => 'اجازه دسترسی به <abbr>API</abbr> <small>(برای برنامه‌های موبایل و اشتراک‌گذاری پرس‌وجوهای کاربر لازم است)</small>',
'form' => 'فرم وب (سنتی، نیازمند JavaScript)',
'http' => 'HTTP (پیشرفته: مدیریت‌شده توسط وب‌سرور، OIDC، SSO و...)',
'none' => ' هیچ (خطرناک)',
'title' => ' احراز هویت',
'token' => 'توکن اصلی احراز هویت',
'token_help' => 'اجازه دسترسی به همه خروجی‌های RSS کاربر و به‌روزرسانی فیدها را بدون احراز هویت می‌دهد:',
'type' => ' روش احراز هویت',
),
'extensions' => array(
'author' => ' نویسنده',
'community' => ' افزونه‌های جامعه کاربری موجود',
'description' => ' توضیحات',
'disabled' => 'غیرفعال',
'empty_list' => 'هیچ افزونه‌ای نصب نشده است',
'empty_list_help' => 'لاگ‌ها را بررسی کنید تا دلیل خالی بودن لیست افزونه‌ها مشخص شود',
'enabled' => ' فعال است',
'is_compatible' => 'سازگار است',
'latest' => 'نصب‌شده',
'name' => ' نام',
'no_configure_view' => ' این برنامه افزودنی قابل پیکربندی نیست.',
'system' => array(
'_' => 'افزونه‌های سیستم',
'no_rights' => 'افزونه سیستم (شما مجوزهای لازم را ندارید)',
),
'title' => 'افزونه‌ها',
'update' => 'به‌روزرسانی موجود است',
'user' => 'افزونه‌های کاربر',
'version' => ' نسخه',
),
'stats' => array(
'_' => 'آمار',
'all_feeds' => ' همه فیدها',
'category' => ' دسته',
'date_published' => 'تاریخ انتشار',
'date_received' => 'تاریخ دریافت',
'entry_count' => ' تعداد ورودی',
'entry_per_category' => ' ورودی در هر دسته',
'entry_per_day' => ' ورودی در روز (30 روز گذشته)',
'entry_per_day_of_week' => 'در هر روز هفته (میانگین: %.2f پیام)',
'entry_per_hour' => 'در هر ساعت (میانگین: %.2f پیام)',
'entry_per_month' => 'در هر ماه (میانگین: %.2f پیام)',
'entry_repartition' => 'توزیع مقاله‌ها',
'feed' => ' خوراک',
'feed_per_category' => ' فید در هر دسته',
'idle' => 'فیدهای غیرفعال',
'main' => ' آمار اصلی',
'main_stream' => ' جریان اصلی',
'nb_unreads' => 'تعداد مقاله‌های خوانده‌نشده',
'no_idle' => 'هیچ فید غیرفعالی وجود ندارد!',
'number_entries' => ' %d مقاله',
'overview' => 'بررسی اجمالی',
'percent_of_total' => 'درصد از کل',
'repartition' => 'توزیع مقاله‌ها: %s',
'status_favorites' => ' موارد دلخواه',
'status_read' => 'خوانده‌شده',
'status_total' => ' مجموع',
'status_unread' => 'خوانده‌نشده',
'title' => 'آمار',
'top_feed' => ' ده فید برتر',
'unread_dates' => 'تاریخ‌هایی با بیشترین مقاله خوانده‌نشده',
),
'system' => array(
'_' => ' پیکربندی سیستم',
'auto-update-url' => 'نشانی سرور به‌روزرسانی خودکار',
'base-url' => array(
'_' => 'آدرس پایه',
'recommendation' => 'توصیه: <kbd>%s</kbd>',
),
'closed_registration_message' => 'پیام هنگام بسته بودن ثبت‌نام',
'cookie-duration' => array(
'help' => ' در ثانیه',
'number' => ' مدت زمان ورود به سیستم',
),
'default_closed_registration_message' => 'این سرور در حال حاضر ثبت‌نام جدید نمی‌پذیرد.',
'force_email_validation' => ' اعتبارسنجی آدرس ایمیل اجباری',
'instance-name' => ' نام نمونه',
'internal-host-allowlist' => array(
'_' => 'Internal host allowlist', // TODO
'help' => 'One entry per line:<ul><li>A <code>host:port</code>. For instance <code>127.0.0.1:8080</code> or <code>rss-bridge:80</code></li><li>A CIDR notation. For instance <code>0.0.0.0/0</code> to allow any IPv4, <code>::/0</code> to allow any IPv6</li><li>A <code>*</code> to allow any host (unsafe)</li></ul>', // TODO
),
'max-categories' => ' حداکثر تعداد دسته ها برای هر کاربر',
'max-feeds' => ' حداکثر تعداد فید برای هر کاربر',
'override-by-env-var' => 'This setting is set by the environment variable <kbd>%s</kbd>.', // TODO
'registration' => array(
'number' => ' حداکثر تعداد حساب ها',
'select' => array(
'label' => ' فرم ثبت نام',
'option' => array(
'noform' => 'غیرفعال: بدون فرم ثبت‌نام',
'nolimit' => 'فعال: بدون محدودیت تعداد حساب‌ها',
'setaccountsnumber' => 'فعال: با حداکثر تعداد حساب‌ها',
),
),
'status' => array(
'disabled' => ' فرم غیرفعال است',
'enabled' => ' فرم فعال است',
),
'title' => 'فرم ثبت نام کاربر',
),
'sensitive-parameter' => 'پارامتر حساس. به صورت دستی در <kbd>./data/config.php</kbd> ویرایش کنید',
'tos' => array(
'disabled' => ' داده نشده است',
'enabled' => ' <a href="./?a=tos">فعال است</a>',
'help' => ' نحوه <a href="https://freshrss.github.io/FreshRSS/en/admins/12_User_management.html#enable-terms-of-service-tos" target="_blank">فعال کردن شرایط خدمات </a>',
),
'websub' => array(
'help' => 'درباره <a href="https://freshrss.github.io/FreshRSS/en/users/WebSub.html" target="_blank">WebSub</a>',
),
),
'update' => array(
'_' => 'به‌روزرسانی FreshRSS',
'apply' => 'شروع به‌روزرسانی',
'changelog' => ' تغییرات',
'check' => 'بررسی به‌روزرسانی‌های جدید',
'copiedFromURL' => 'update.php از %s به ./data کپی شد',
'current_version' => ' نسخه نصب شده فعلی',
'last' => ' آخرین بررسی',
'loading' => 'در حال به‌روزرسانی…',
'none' => 'به‌روزرسانی در دسترس نیست',
'releaseChannel' => array(
'_' => ' کانال انتشار',
'edge' => 'انتشار پیوسته («edge»)',
'latest' => 'انتشار پایدار («latest»)',
),
'title' => 'به‌روزرسانی FreshRSS',
'viaGit' => 'به‌روزرسانی از طریق git و GitHub.com شروع شد',
),
'user' => array(
'admin' => ' مدیر',
'article_count' => ' مقالات',
'back_to_manage' => ' ← بازگشت به لیست کاربران',
'create' => ' ایجاد کاربر جدید',
'database_size' => ' اندازه پایگاه داده',
'email' => ' آدرس ایمیل',
'enabled' => ' فعال است',
'feed_count' => ' فیدها',
'is_admin' => ' مدیر است',
'language' => ' زبان',
'last_user_activity' => ' آخرین فعالیت کاربر',
'list' => ' لیست کاربران',
'number' => ' %d حساب ایجاد شده است',
'numbers' => ' %d حساب ایجاد شده است',
'password_form' => 'رمز عبور<br /><small>(برای روش ورود با فرم وب)</small>',
'password_format' => ' حداقل 7 کاراکتر',
'title' => ' مدیریت کاربران',
'username' => ' نام کاربری',
),
);