Filter file scheme; disable http, https and ftp entirely
parent
96bbc9d738
commit
e2d044e02b
@ -0,0 +1,59 @@
|
|||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
const FILE_SCHEME = /^file:\/\//;
|
||||||
|
const WINDOWS_PREFIX = /^\/[A-Z]:/;
|
||||||
|
function _urlToPath(targetUrl) {
|
||||||
|
let withoutScheme = targetUrl.replace(FILE_SCHEME, '');
|
||||||
|
if (WINDOWS_PREFIX.test(withoutScheme)) {
|
||||||
|
withoutScheme = withoutScheme.slice(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const withoutQuerystring = withoutScheme.replace(/\?.*$/, '');
|
||||||
|
const withoutHash = withoutQuerystring.replace(/#.*$/, '');
|
||||||
|
|
||||||
|
return decodeURIComponent(withoutHash);
|
||||||
|
}
|
||||||
|
|
||||||
|
function _createFileHandler({ userDataPath, installPath }) {
|
||||||
|
return (request, callback) => {
|
||||||
|
// normalize() is primarily useful here for switching / to \ on windows
|
||||||
|
const target = path.normalize(_urlToPath(request.url));
|
||||||
|
|
||||||
|
if (!path.isAbsolute(target)) {
|
||||||
|
return callback();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!target.startsWith(userDataPath) && !target.startsWith(installPath)) {
|
||||||
|
console.log(`Warning: denying request to ${target}`);
|
||||||
|
return callback();
|
||||||
|
}
|
||||||
|
|
||||||
|
return callback({
|
||||||
|
path: target,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function installFileHandler({ protocol, userDataPath, installPath }) {
|
||||||
|
protocol.interceptFileProtocol(
|
||||||
|
'file',
|
||||||
|
_createFileHandler({ userDataPath, installPath })
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Turn off all browser web requests since we do all web requests via Node.js
|
||||||
|
function _webHandler(request, callback) {
|
||||||
|
return callback();
|
||||||
|
}
|
||||||
|
|
||||||
|
function installWebHandler({ protocol }) {
|
||||||
|
protocol.interceptFileProtocol('http', _webHandler);
|
||||||
|
protocol.interceptFileProtocol('https', _webHandler);
|
||||||
|
protocol.interceptFileProtocol('ftp', _webHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
_urlToPath,
|
||||||
|
installFileHandler,
|
||||||
|
installWebHandler,
|
||||||
|
};
|
@ -0,0 +1,83 @@
|
|||||||
|
const { expect } = require('chai');
|
||||||
|
|
||||||
|
const { _urlToPath } = require('../../app/protocol_filter');
|
||||||
|
|
||||||
|
describe('Protocol Filter', () => {
|
||||||
|
describe('_urlToPath', () => {
|
||||||
|
it('returns proper file path for unix style file URI with hash', () => {
|
||||||
|
const path =
|
||||||
|
'file:///Users/someone/Development/signal/electron/background.html#first-page';
|
||||||
|
const expected =
|
||||||
|
'/Users/someone/Development/signal/electron/background.html';
|
||||||
|
|
||||||
|
const actual = _urlToPath(path);
|
||||||
|
expect(actual).to.equal(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns proper file path for unix style file URI with querystring', () => {
|
||||||
|
const path =
|
||||||
|
'file:///Users/someone/Development/signal/electron/background.html?name=Signal&locale=en&version=2.4.0';
|
||||||
|
const expected =
|
||||||
|
'/Users/someone/Development/signal/electron/background.html';
|
||||||
|
|
||||||
|
const actual = _urlToPath(path);
|
||||||
|
expect(actual).to.equal(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns proper file path for unix style file URI with hash and querystring', () => {
|
||||||
|
const path =
|
||||||
|
'file:///Users/someone/Development/signal/electron/background.html#somewhere?name=Signal';
|
||||||
|
const expected =
|
||||||
|
'/Users/someone/Development/signal/electron/background.html';
|
||||||
|
|
||||||
|
const actual = _urlToPath(path);
|
||||||
|
expect(actual).to.equal(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns proper file path for windows style file URI', () => {
|
||||||
|
const path =
|
||||||
|
'file:///C:/Users/Someone/dev/desktop/background.html?name=Signal&locale=en&version=2.4.0';
|
||||||
|
const expected = 'C:/Users/Someone/dev/desktop/background.html';
|
||||||
|
|
||||||
|
const actual = _urlToPath(path, { isWindows: true });
|
||||||
|
expect(actual).to.equal(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('translates from URL format to filesystem format', () => {
|
||||||
|
const path =
|
||||||
|
'file:///Users/someone/Development%20Files/signal/electron/background.html';
|
||||||
|
const expected =
|
||||||
|
'/Users/someone/Development Files/signal/electron/background.html';
|
||||||
|
|
||||||
|
const actual = _urlToPath(path);
|
||||||
|
expect(actual).to.equal(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('translates from URL format to filesystem format', () => {
|
||||||
|
const path =
|
||||||
|
'file:///Users/someone/Development%20Files/signal/electron/background.html';
|
||||||
|
const expected =
|
||||||
|
'/Users/someone/Development Files/signal/electron/background.html';
|
||||||
|
|
||||||
|
const actual = _urlToPath(path);
|
||||||
|
expect(actual).to.equal(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
// this seems to be the only way to get a relative path through Electron
|
||||||
|
it('handles SMB share path', () => {
|
||||||
|
const path = 'file://relative/path';
|
||||||
|
const expected = 'relative/path';
|
||||||
|
|
||||||
|
const actual = _urlToPath(path);
|
||||||
|
expect(actual).to.equal(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('hands back a path with .. in it', () => {
|
||||||
|
const path = 'file://../../..';
|
||||||
|
const expected = '../../..';
|
||||||
|
|
||||||
|
const actual = _urlToPath(path);
|
||||||
|
expect(actual).to.equal(expected);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
Loading…
Reference in New Issue