// Do not allow private modules to be loaded from the web.
// This is a security issue, see T36907.
if ( $module->getGroup() === 'private' ) {
+ // Not a serious error, just means something is trying to access it (T101806)
$this->logger->debug( "Request for private module '$name' denied" );
- $this->errors[] = "Cannot show private module \"$name\"";
+ $this->errors[] = "Cannot build private module \"$name\"";
continue;
}
$modules[$name] = $module;
dependencies.forEach( function ( module ) {
// Only queue modules that are still in the initial 'registered' state
- // (not ones already loading, ready or error).
+ // (e.g. not ones already loading or loaded etc.).
if ( registry[ module ].state === 'registered' && queue.indexOf( module ) === -1 ) {
- // Private modules must be embedded in the page. Don't bother queuing
- // these as the server will deny them anyway (T101806).
- if ( registry[ module ].group === 'private' ) {
- setAndPropagate( module, 'error' );
- } else {
- queue.push( module );
- }
+ queue.push( module );
}
} );
$rl->respond( $context );
}
+ /**
+ * Refuse requests for private modules.
+ *
+ * @covers ResourceLoader::respond
+ */
+ public function testRespondErrorPrivate() {
+ $rl = $this->getMockBuilder( EmptyResourceLoader::class )
+ ->setMethods( [
+ 'measureResponseTime',
+ 'tryRespondNotModified',
+ 'sendResponseHeaders',
+ ] )
+ ->getMock();
+ $rl->register( [
+ 'foo' => [ 'class' => ResourceLoaderTestModule::class ],
+ 'bar' => [ 'class' => ResourceLoaderTestModule::class, 'group' => 'private' ],
+ ] );
+ $context = $this->getResourceLoaderContext(
+ [ 'modules' => 'foo|bar', 'only' => null ],
+ $rl
+ );
+
+ $this->expectOutputRegex( '/^\/\*.+Cannot build private module/s' );
+ $rl->respond( $context );
+ }
+
/**
* @covers ResourceLoader::respond
*/