From 7db1e3dc90404559ce3b495a3c0e53165d6057d3 Mon Sep 17 00:00:00 2001 From: Brian Wolff Date: Tue, 3 Nov 2015 00:10:59 -0700 Subject: [PATCH] Rewrite ?action=raw requests as api requests for better safety This avoids possibly leaking data from an authenticated request to the main site. Bug: T98313 --- js/graph.js | 34 ++++++++++++++++++++++++++++++++++ lib/vega.js | 17 +++++++++++------ 2 files changed, 45 insertions(+), 6 deletions(-) diff --git a/js/graph.js b/js/graph.js index e99c273..2fba9ad 100644 --- a/js/graph.js +++ b/js/graph.js @@ -44,6 +44,40 @@ } return url; }; + // Make sure ?action=raw access goes through API (T98313) + // Note: This does not translate oldid parameter. + // callback is a function taking an err and a resp parameter + vg.config.customXHRCallback = function( url, callback ) { + var matches = url.match( /^([^?]*)\/index\.php\?(?:|.*&)(?:title=([^&|]*)&(?:.*&)?action=raw|action=raw&(?:.*&)?title=([^&|]*))/ ), + page, + newUrl, + newCB; + if ( matches ) { + page = matches[2] === undefined ? matches[3] : matches[2]; + newUrl = matches[1] + '/api.php?action=query&prop=revisions&rvprop=content&format=json&formatversion=2&titles=' + page; + newCB = function( err, resp ) { + var jsonResp; + if ( resp ) { + jsonResp = JSON.parse( resp ); + if ( jsonResp && jsonResp.query && jsonResp.query.pages + && jsonResp.query.pages[0] + && jsonResp.query.pages[0].revisions + && jsonResp.query.pages[0].revisions[0] + && jsonResp.query.pages[0].revisions[0].content !== undefined + ) { + resp = jsonResp.query.pages[0].revisions[0].content; + } else { + return( "Error loading raw contents of Wikipage", null ); + } + } + return callback( err, resp ); + } + } else { + newUrl = url; + newCB = callback; + } + return [newUrl, newCB]; + } } $content.find( '.mw-wiki-graph' ).each( function () { diff --git a/lib/vega.js b/lib/vega.js index 456a0da..395928e 100644 --- a/lib/vega.js +++ b/lib/vega.js @@ -371,6 +371,9 @@ vg.config.isNode = false; // e.g., ['wikipedia.org', 'eff.org'] vg.config.domainWhiteList = false; +// Allow an extra layer of indirection when loading resources from web +vg.config.customXHRCallback = function( url, callback ) { return [url, callback]; } + // Allows additional headers to be sent to the server // when requesting data. This could be useful when // the graph definition is not trusted, and the server @@ -3041,18 +3044,20 @@ vg.data.size = function(size, group) { } function load(uri, callback) { - var url = vg.data.load.sanitizeUrl(uri); // allow sanitizer override + var customXHRCallbackRes = vg.config.customXHRCallback( uri, callback ), + url = vg.data.load.sanitizeUrl(customXHRCallbackRes[0]), // allow sanitizer override + finalCallback = customXHRCallbackRes[1]; if (!url) { - callback('Bad URL', null); + finalCallback('Bad URL', null); } else if (!vg.config.isNode) { // in browser, use xhr - xhr(url, callback); + xhr(url, finalCallback ); } else if (vg.startsWith(url, fileProtocol)) { // in node.js, if url starts with 'file://', strip it and load from file - file(url.slice(fileProtocol.length), callback); + file(url.slice(fileProtocol.length), finalCallback); } else { // for regular URLs in node.js - http(url, callback); + http(url, finalCallback); } } @@ -11000,4 +11005,4 @@ vg.headless.View.Factory = function(defs) { //--------------------------------------------------- // END code for this module //--------------------------------------------------- -})); \ No newline at end of file +})); -- 2.0.1