Преглед изворни кода

Security: public OPML should not contain cURL parameters (#9070)

* Security: public OPML should not contain cURL parameters
https://github.com/FreshRSS/FreshRSS/security/advisories/GHSA-w3xh-7jrp-3qp2
https://github.com/FreshRSS/FreshRSS/security/advisories/GHSA-wmcc-46r3-6q5f

* Simplify patch

* Minor wording
Alexandre Alapetite пре 6 дана
родитељ
комит
818bc986f7

+ 1 - 0
app/Models/View.php

@@ -32,6 +32,7 @@ class FreshRSS_View extends Minz_View {
 	/** @var array<string,array<string>> */
 	public array $tagsForEntries;
 	public bool $excludeMutedFeeds;
+	public bool $includeSensitiveCurlParams = false;
 
 	// Search
 	/** @var array<int,FreshRSS_Tag> where the key is the label ID */

+ 1 - 0
app/Services/ExportService.php

@@ -48,6 +48,7 @@ class FreshRSS_Export_Service {
 		$day = date('Y-m-d');
 		$view->categories = $this->category_dao->listCategories(prePopulateFeeds: true, details: true);
 		$view->excludeMutedFeeds = false;
+		$view->includeSensitiveCurlParams = true;
 
 		return [
 			"feeds_{$day}.opml.xml",

+ 5 - 4
app/views/helpers/export/opml.phtml

@@ -5,7 +5,7 @@ declare(strict_types=1);
  * @param array<FreshRSS_Feed> $feeds
  * @return list<array<string,string|bool|int>>
  */
-function feedsToOutlines(array $feeds, bool $excludeMutedFeeds = false): array {
+function feedsToOutlines(array $feeds, bool $excludeMutedFeeds = false, bool $includeSensitiveCurlParams = false): array {
 	$outlines = [];
 	foreach ($feeds as $feed) {
 		if ($feed->mute() && $excludeMutedFeeds) {
@@ -120,7 +120,8 @@ function feedsToOutlines(array $feeds, bool $excludeMutedFeeds = false): array {
 		}
 
 		$curl_params = FreshRSS_http_Util::sanitizeCurlParams($feed->attributeArray('curl_params') ?? []);
-		if (!empty($curl_params)) {
+		// NB: Only include sensitive cURL parameters for private exports, not for public shares
+		if ($includeSensitiveCurlParams && !empty($curl_params)) {
 			$outline['frss:CURLOPT_COOKIE'] = $curl_params[CURLOPT_COOKIE] ?? null;
 			$outline['frss:CURLOPT_COOKIEFILE'] = $curl_params[CURLOPT_COOKIEFILE] ?? null;
 			$outline['frss:CURLOPT_FOLLOWLOCATION'] = $curl_params[CURLOPT_FOLLOWLOCATION] ?? null;
@@ -172,7 +173,7 @@ if (!empty($this->categories)) {
 	foreach ($this->categories as $cat) {
 		$outline = [
 			'text' => htmlspecialchars_decode($cat->name(), ENT_QUOTES),
-			'@outlines' => feedsToOutlines($cat->feeds(), $this->excludeMutedFeeds),
+			'@outlines' => feedsToOutlines($cat->feeds(), $this->excludeMutedFeeds, $this->includeSensitiveCurlParams),
 		];
 
 		if ($cat->kind() === FreshRSS_Category::KIND_DYNAMIC_OPML) {
@@ -184,7 +185,7 @@ if (!empty($this->categories)) {
 }
 
 if (!empty($this->feeds)) {
-	$opml_array['body'] = array_merge($opml_array['body'], feedsToOutlines($this->feeds, $this->excludeMutedFeeds));
+	$opml_array['body'] = array_merge($opml_array['body'], feedsToOutlines($this->feeds, $this->excludeMutedFeeds, $this->includeSensitiveCurlParams));
 }
 
 $libopml = new \marienfressinaud\LibOpml\LibOpml(strict: false);

+ 1 - 0
app/views/index/opml.phtml

@@ -1,4 +1,5 @@
 <?php
 declare(strict_types=1);
 /** @var FreshRSS_View $this */
+$this->includeSensitiveCurlParams = false;	// Public OPML must not include sensitive parameters
 $this->renderHelper('export/opml');