Issues (1401)

Security Analysis    no request data  

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

client/includes/Hooks/UpdateRepoHookHandler.php (2 issues)

Labels
Severity

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
namespace Wikibase\Client\Hooks;
4
5
use Content;
6
use JobQueueGroup;
7
use LogEntry;
8
use MediaWiki\Hook\PageMoveCompleteHook;
9
use MediaWiki\Linker\LinkTarget;
10
use MediaWiki\Logger\LoggerFactory;
11
use MediaWiki\Page\Hook\ArticleDeleteCompleteHook;
12
use MediaWiki\Revision\RevisionRecord;
13
use MediaWiki\User\UserIdentity;
14
use MWException;
15
use Psr\Log\LoggerInterface;
16
use Title;
17
use User;
18
use Wikibase\Client\NamespaceChecker;
19
use Wikibase\Client\UpdateRepo\UpdateRepoOnDelete;
20
use Wikibase\Client\UpdateRepo\UpdateRepoOnMove;
21
use Wikibase\Client\WikibaseClient;
22
use Wikibase\Lib\Store\SiteLinkLookup;
23
use WikiPage;
24
25
/**
26
 * This class has a static interface for use with MediaWiki's hook mechanism; the static
27
 * handler functions will create a new instance of UpdateRepoHookHandlers and then call the
28
 * corresponding member function on that.
29
 *
30
 * @license GPL-2.0-or-later
31
 * @author Marius Hoch < [email protected] >
32
 */
33
class UpdateRepoHookHandler implements PageMoveCompleteHook, ArticleDeleteCompleteHook {
34
35
	/**
36
	 * @var NamespaceChecker
37
	 */
38
	private $namespaceChecker;
39
40
	/**
41
	 * @var JobQueueGroup
42
	 */
43
	private $jobQueueGroup;
44
45
	/**
46
	 * @var SiteLinkLookup
47
	 */
48
	private $siteLinkLookup;
49
50
	/**
51
	 * @var LoggerInterface
52
	 */
53
	private $logger;
54
55
	/**
56
	 * @var string
57
	 */
58
	private $repoDatabase;
59
60
	/**
61
	 * @var string
62
	 */
63
	private $siteGlobalID;
64
65
	/**
66
	 * @var bool
67
	 */
68
	private $propagateChangesToRepo;
69
70
	/**
71
	 * @return self|null
72
	 */
73
	public static function factory() {
74
		$wikibaseClient = WikibaseClient::getDefaultInstance();
75
		$settings = $wikibaseClient->getSettings();
76
77
		$namespaceChecker = $wikibaseClient->getNamespaceChecker();
78
79
		$repoDB = $wikibaseClient->getDatabaseDomainNameOfLocalRepo();
80
		$jobQueueGroup = JobQueueGroup::singleton( $repoDB );
81
82
		if ( !$jobQueueGroup ) {
83
			wfLogWarning( "Failed to acquire a JobQueueGroup for $repoDB" );
84
			return null;
85
		}
86
87
		$siteLinkLookup = $wikibaseClient->getStore()->getSiteLinkLookup();
88
89
		return new self(
90
			$namespaceChecker,
91
			$jobQueueGroup,
92
			$siteLinkLookup,
93
			LoggerFactory::getInstance( 'UpdateRepo' ),
94
			$repoDB,
95
			$settings->getSetting( 'siteGlobalID' ),
96
			$settings->getSetting( 'propagateChangesToRepo' )
97
		);
98
	}
99
100
	/**
101
	 * @param NamespaceChecker $namespaceChecker
102
	 * @param JobQueueGroup $jobQueueGroup
103
	 * @param SiteLinkLookup $siteLinkLookup
104
	 * @param LoggerInterface $logger
105
	 * @param string $repoDatabase
106
	 * @param string $siteGlobalID
107
	 * @param bool $propagateChangesToRepo
108
	 */
109
	public function __construct(
110
		NamespaceChecker $namespaceChecker,
111
		JobQueueGroup $jobQueueGroup,
112
		SiteLinkLookup $siteLinkLookup,
113
		LoggerInterface $logger,
114
		$repoDatabase,
115
		$siteGlobalID,
116
		$propagateChangesToRepo
117
	) {
118
		$this->namespaceChecker = $namespaceChecker;
119
		$this->jobQueueGroup = $jobQueueGroup;
120
		$this->siteLinkLookup = $siteLinkLookup;
121
		$this->logger = $logger;
122
123
		$this->repoDatabase = $repoDatabase;
124
		$this->siteGlobalID = $siteGlobalID;
125
		$this->propagateChangesToRepo = $propagateChangesToRepo;
126
	}
127
128
	/**
129
	 * @see NamespaceChecker::isWikibaseEnabled
130
	 *
131
	 * @param int $namespace
132
	 *
133
	 * @return bool
134
	 */
135
	private function isWikibaseEnabled( $namespace ) {
136
		return $this->namespaceChecker->isWikibaseEnabled( $namespace );
137
	}
138
139
	/**
140
	 * After a page has been deleted also update the item on the repo.
141
	 * This only works if there's a user account with the same name on the repo.
142
	 *
143
	 * @see https://www.mediawiki.org/wiki/Manual:Hooks/ArticleDeleteComplete
144
	 *
145
	 * @param WikiPage $wikiPage WikiPage that was deleted
146
	 * @param User $user User that deleted the article
147
	 * @param string $reason Reason the article was deleted
148
	 * @param int $id ID of the article that was deleted
149
	 * @param Content|null $content Content of the deleted page (or null, when deleting a broken page)
150
	 * @param \ManualLogEntry $logEntry ManualLogEntry used to record the deletion
151
	 * @param int $archivedRevisionCount Number of revisions archived during the deletion
152
	 * @return bool|void True or no return value to continue or false to abort
153
	 */
154
	public function onArticleDeleteComplete(
155
		$wikiPage,
156
		$user,
157
		$reason,
158
		$id,
159
		$content,
160
		$logEntry,
161
		$archivedRevisionCount
162
	) {
163
		if ( $this->propagateChangesToRepo !== true ) {
164
			return true;
165
		}
166
167
		$updateRepo = new UpdateRepoOnDelete(
168
			$this->repoDatabase,
169
			$this->siteLinkLookup,
170
			$this->logger,
171
			$user,
172
			$this->siteGlobalID,
173
			$wikiPage->getTitle()
174
		);
175
176
		if ( !$updateRepo->isApplicable() ) {
177
			return true;
178
		}
179
180
		try {
181
			$updateRepo->injectJob( $this->jobQueueGroup );
182
183
			// To be able to find out about this in the ArticleDeleteAfter hook
184
			// @phan-suppress-next-line PhanUndeclaredProperty Dynamic property
185
			$wikiPage->getTitle()->wikibasePushedDeleteToRepo = true;
186
		} catch ( MWException $e ) {
0 ignored issues
show
The class MWException does not exist. Is this class maybe located in a folder that is not analyzed, or in a newer version of your dependencies than listed in your composer.lock/composer.json?
Loading history...
187
			// This is not a reason to let an exception bubble up, we just
188
			// show a message to the user that the Wikibase item needs to be
189
			// manually updated.
190
			wfLogWarning( $e->getMessage() );
191
192
			$this->logger->debug(
193
				'{method}: Failed to inject job: "{msg}"!',
194
				[
195
					'method' => __METHOD__,
196
					'msg' => $e->getMessage()
197
				]
198
			);
199
200
		}
201
202
		return true;
203
	}
204
205
	/**
206
	 * After a page has been moved also update the item on the repo.
207
	 * This only works if there's a user account with the same name on the repo.
208
	 *
209
	 * @see https://www.mediawiki.org/wiki/Manual:Hooks/PageMoveComplete
210
	 *
211
	 * @param LinkTarget $oldLinkTarget
212
	 * @param LinkTarget $newLinkTarget
213
	 * @param UserIdentity $userIdentity
214
	 * @param int $pageId database ID of the page that's been moved
215
	 * @param int $redirid ID of the created redirect
216
	 * @param string $reason
217
	 * @param RevisionRecord $revisionRecord revision created by the move
218
	 *
219
	 * @return bool
220
	 */
221
	public function onPageMoveComplete(
222
		$oldLinkTarget,
223
		$newLinkTarget,
224
		$userIdentity,
225
		$pageId,
226
		$redirid,
227
		$reason,
228
		$revisionRecord
229
	) {
230
		if ( !$this->isWikibaseEnabled( $newLinkTarget->getNamespace() ) ) {
231
			return true;
232
		}
233
234
		if ( $this->propagateChangesToRepo !== true ) {
235
			return true;
236
		}
237
238
		$old = Title::newFromLinkTarget( $oldLinkTarget );
239
		$nt = Title::newFromLinkTarget( $newLinkTarget );
240
		$user = User::newFromIdentity( $userIdentity );
241
242
		$updateRepo = new UpdateRepoOnMove(
243
			$this->repoDatabase,
244
			$this->siteLinkLookup,
245
			$this->logger,
246
			$user,
247
			$this->siteGlobalID,
248
			$old,
249
			$nt
250
		);
251
252
		if ( !$updateRepo->isApplicable() ) {
253
			return true;
254
		}
255
256
		try {
257
			$updateRepo->injectJob( $this->jobQueueGroup );
258
259
			// To be able to find out about this in the SpecialMovepageAfterMove hook
260
			// @phan-suppress-next-line PhanUndeclaredProperty Dynamic property
261
			$nt->wikibasePushedMoveToRepo = true;
262
		} catch ( MWException $e ) {
0 ignored issues
show
The class MWException does not exist. Is this class maybe located in a folder that is not analyzed, or in a newer version of your dependencies than listed in your composer.lock/composer.json?
Loading history...
263
			// This is not a reason to let an exception bubble up, we just
264
			// show a message to the user that the Wikibase item needs to be
265
			// manually updated.
266
			wfLogWarning( $e->getMessage() );
267
268
			$this->logger->debug(
269
				'{method}: Failed to inject job: "{msg}"!',
270
				[
271
					'method' => __METHOD__,
272
					'msg' => $e->getMessage()
273
				]
274
			);
275
		}
276
277
		return true;
278
	}
279
280
}
281