X-Git-Url: https://git.heureux-cyclage.org/?a=blobdiff_plain;f=includes%2Factions%2FRawAction.php;h=77a8b14e2c2c04a04e8e3df3528678ddef2d385e;hb=1d930860cc19513c1d6b3d4b325f77ab939c2973;hp=50eb28a3cfa0771fd8de4fb06faaa885d2d60093;hpb=8c96aec32cffaab96b2bd9dca206a99a13640545;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/actions/RawAction.php b/includes/actions/RawAction.php index 50eb28a3cf..77a8b14e2c 100644 --- a/includes/actions/RawAction.php +++ b/includes/actions/RawAction.php @@ -47,6 +47,9 @@ class RawAction extends FormlessAction { return false; } + /** + * @suppress SecurityCheck-XSS Non html mime type + */ function onView() { $this->getOutput()->disable(); $request = $this->getRequest(); @@ -126,6 +129,30 @@ class RawAction extends FormlessAction { } } + // Don't allow loading non-protected pages as javascript. + // In future we may further restrict this to only CONTENT_MODEL_JAVASCRIPT + // in NS_MEDIAWIKI or NS_USER, as well as including other config types, + // but for now be more permissive. Allowing protected pages outside of + // NS_USER and NS_MEDIAWIKI in particular should be considered a temporary + // allowance. + if ( + $contentType === 'text/javascript' && + !$title->isUserJsConfigPage() && + !$title->inNamespace( NS_MEDIAWIKI ) && + !in_array( 'sysop', $title->getRestrictions( 'edit' ) ) && + !in_array( 'editprotected', $title->getRestrictions( 'edit' ) ) + ) { + + $log = LoggerFactory::getInstance( "security" ); + $log->info( "Blocked loading unprotected JS {title} for {user}", + [ + 'user' => $this->getUser()->getName(), + 'title' => $title->getPrefixedDBKey(), + ] + ); + throw new HttpError( 403, wfMessage( 'unprotected-js' ) ); + } + $response->header( 'Content-type: ' . $contentType . '; charset=UTF-8' ); $text = $this->getRawText(); @@ -160,47 +187,35 @@ class RawAction extends FormlessAction { $title = $this->getTitle(); $request = $this->getRequest(); - // If it's a MediaWiki message we can just hit the message cache - if ( $request->getBool( 'usemsgcache' ) && $title->getNamespace() == NS_MEDIAWIKI ) { - // The first "true" is to use the database, the second is to use - // the content langue and the last one is to specify the message - // key already contains the language in it ("/de", etc.). - $text = MessageCache::singleton()->get( $title->getDBkey(), true, true, true ); - // If the message doesn't exist, return a blank - if ( $text === false ) { - $text = ''; - } - } else { - // Get it from the DB - $rev = Revision::newFromTitle( $title, $this->getOldId() ); - if ( $rev ) { - $lastmod = wfTimestamp( TS_RFC2822, $rev->getTimestamp() ); - $request->response()->header( "Last-modified: $lastmod" ); - - // Public-only due to cache headers - $content = $rev->getContent(); - - if ( $content === null ) { - // revision not found (or suppressed) + // Get it from the DB + $rev = Revision::newFromTitle( $title, $this->getOldId() ); + if ( $rev ) { + $lastmod = wfTimestamp( TS_RFC2822, $rev->getTimestamp() ); + $request->response()->header( "Last-modified: $lastmod" ); + + // Public-only due to cache headers + $content = $rev->getContent(); + + if ( $content === null ) { + // revision not found (or suppressed) + $text = false; + } elseif ( !$content instanceof TextContent ) { + // non-text content + wfHttpError( 415, "Unsupported Media Type", "The requested page uses the content model `" + . $content->getModel() . "` which is not supported via this interface." ); + die(); + } else { + // want a section? + $section = $request->getIntOrNull( 'section' ); + if ( $section !== null ) { + $content = $content->getSection( $section ); + } + + if ( $content === null || $content === false ) { + // section not found (or section not supported, e.g. for JS, JSON, and CSS) $text = false; - } elseif ( !$content instanceof TextContent ) { - // non-text content - wfHttpError( 415, "Unsupported Media Type", "The requested page uses the content model `" - . $content->getModel() . "` which is not supported via this interface." ); - die(); } else { - // want a section? - $section = $request->getIntOrNull( 'section' ); - if ( $section !== null ) { - $content = $content->getSection( $section ); - } - - if ( $content === null || $content === false ) { - // section not found (or section not supported, e.g. for JS, JSON, and CSS) - $text = false; - } else { - $text = $content->getNativeData(); - } + $text = $content->getNativeData(); } } }