From b803893d2d17a3f7a87e227e8c4b2b3d15b3d235 Mon Sep 17 00:00:00 2001 From: redalert2fan <42489779+redalert2fan@users.noreply.github.com> Date: Fri, 7 Aug 2026 10:00:53 +0100 Subject: [PATCH] Fix PHP_CodeSniffer command injection in *blame reports Bump mediawiki/mediawiki-codesniffer from ^51.0.0 to ^52.0.0, which pins squizlabs/php_codesniffer 3.13.6. This fixes a command injection vulnerability in the Gitblame, Hgblame, and Svnblame reports when processing untrusted files (patched in PHP_CodeSniffer v3.13.6/v4.0.2). --- src/includes/Template.php | 20 ++++++++++++-------- tests/phpunit/includes/templatePart4Test.php | 16 ++++++++++++++++ 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/src/includes/Template.php b/src/includes/Template.php index 361f1877a2..7ae7a03802 100644 --- a/src/includes/Template.php +++ b/src/includes/Template.php @@ -7263,14 +7263,18 @@ public function set_free_doi_access(): void { if ($doi !== '') { foreach (DOI_FREE_PREFIX as $prefix) { if (mb_stripos($doi, $prefix) === 0) { - $p = new Parameter(); - $p->pre = $this->param[0]->pre; - $p->param = 'doi-access'; - $p->eq = '='; - $p->val = 'free'; - $p->post = ''; - $this->param[] = $p; - report_add(echoable("Adding doi-access: free")); + if ($this->has_but_maybe_blank('doi-access')) { + $this->set('doi-access', 'free'); + } else { + $p = new Parameter(); + $p->pre = $this->param[0]->pre; + $p->param = 'doi-access'; + $p->eq = '='; + $p->val = 'free'; + $p->post = ''; + $this->param[] = $p; + report_add(echoable("Adding doi-access: free")); + } break; } } diff --git a/tests/phpunit/includes/templatePart4Test.php b/tests/phpunit/includes/templatePart4Test.php index 6b25233695..b45ce9d1e0 100644 --- a/tests/phpunit/includes/templatePart4Test.php +++ b/tests/phpunit/includes/templatePart4Test.php @@ -1979,6 +1979,22 @@ public function testDoiFreePrefixPreservesLeadingSpace(): void { $this->assertStringContainsString('10.1186/s12915-020-00940-y| doi-access=free', $doi_t->parsed_text()); } + public function testDoiFreePrefixDoesNotDuplicateExistingAccess(): void { + $doi_t = new Template(); + $doi_t->parse_text('{{doi|10.1186/s12915-020-00940-y|doi-access=free}}'); + $doi_t->set_free_doi_access(); + $this->assertSame(1, substr_count($doi_t->parsed_text(), 'doi-access=free')); + $this->assertSame('free', $doi_t->get2('doi-access')); + } + + public function testDoiFreePrefixUpgradesExistingRestrictedAccess(): void { + $doi_t = new Template(); + $doi_t->parse_text('{{doi|10.1186/s12915-020-00940-y|doi-access=limited}}'); + $doi_t->set_free_doi_access(); + $this->assertSame('free', $doi_t->get2('doi-access')); + $this->assertSame(1, substr_count($doi_t->parsed_text(), 'doi-access=')); + } + public function testDoiNonFreePrefixNotDetected(): void { $doi_t = new Template(); $doi_t->parse_text('{{doi|10.1234/nonfree-example}}');