-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'release/3.8.0' into customer
- Loading branch information
Showing
15 changed files
with
381 additions
and
43 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
CWD=`dirname $0:A` | ||
|
||
alias mocli="${CWD}/mocli.sh" | ||
alias mocli="${CWD}/mocli.sh" | ||
mocli gen-cmp |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
import '../common/config'; | ||
|
||
import xhr from 'xhr'; | ||
|
||
/** | ||
* Metadefender Cloud Endpoint for url check | ||
*/ | ||
const safeRedirectEndpoint = `${MCL.config.mclDomain}/safe-redirect/`; | ||
|
||
/** | ||
* A list of urls that are currently redirecting. | ||
*/ | ||
const activeRedirects = new Set(); | ||
|
||
/** | ||
* A list of urls that are infected. | ||
*/ | ||
const infectedUrls = new Set(); | ||
|
||
/** | ||
* A list of urls that are not infected. | ||
* Used to speed-up navigation after fist check. | ||
*/ | ||
const cleanUrls = new Set(); | ||
|
||
/** | ||
* Removes old urls that were marked as clean | ||
*/ | ||
const removeOldUrls = () => { | ||
if (cleanUrls.size > MCL.config.maxCleanUrls) { | ||
const firstValue = cleanUrls.values().next().value; | ||
cleanUrls.delete(firstValue); | ||
} | ||
}; | ||
|
||
/** | ||
* Save the url as infected or not. | ||
* @param {string} testUrl the url to be tested | ||
* @param {string} urlValidator test endpoint | ||
*/ | ||
const handleUrlValidatorResponse = (testUrl, err, res) => { | ||
if (err) { | ||
cleanUrls.add(testUrl); | ||
return; | ||
} | ||
|
||
try { | ||
if (res.headers.status === '400') { | ||
infectedUrls.add(testUrl); | ||
} | ||
else { | ||
cleanUrls.add(testUrl); | ||
} | ||
} | ||
catch (e) { | ||
cleanUrls.add(testUrl); | ||
} | ||
removeOldUrls(); | ||
}; | ||
|
||
const isSafeUrl = (testUrl, urlValidator) => { | ||
xhr.get(urlValidator, {sync: true, headers: {noredirect: true}}, (err, res) => handleUrlValidatorResponse(testUrl, err, res)); | ||
}; | ||
|
||
/** | ||
* Intercept web request before the request is made | ||
* and redirect valid urls to safe-redirect endpoint. | ||
* | ||
* @param {string} safeRedirectEndpoint | ||
* @param {*} details chrome.webRequest event details | ||
* @returns a BlockingResponse https://developer.chrome.com/extensions/webRequest | ||
*/ | ||
const doSafeRedirect = (details) => { | ||
const tabUrl = details.url || ''; | ||
|
||
if (!tabUrl.startsWith(safeRedirectEndpoint)) { | ||
const shortUrl = tabUrl.split('?')[0]; | ||
if (!activeRedirects.has(shortUrl) && details.initiator !== 'null') { | ||
if (!cleanUrls.has(shortUrl)) { | ||
const safeUrl = safeRedirectEndpoint + encodeURIComponent(tabUrl); | ||
isSafeUrl(shortUrl, safeUrl); | ||
if (infectedUrls.has(shortUrl)) { | ||
activeRedirects.add(shortUrl); | ||
return { | ||
redirectUrl: safeUrl | ||
}; | ||
} | ||
} | ||
} | ||
activeRedirects.delete(shortUrl); | ||
if (infectedUrls.has(shortUrl)) { | ||
infectedUrls.delete(shortUrl); | ||
} | ||
} | ||
}; | ||
|
||
/** | ||
* Verifies urls using metadefender cloud safe-redirect feature. | ||
*/ | ||
class SafeUrl { | ||
constructor() { | ||
this.enabled = false; | ||
this.toggle = this.toggle.bind(this); | ||
|
||
this._infectedUrls = infectedUrls; | ||
this._cleanUrls = cleanUrls; | ||
this._doSafeRedirect = doSafeRedirect; | ||
this._handleUrlValidatorResponse = handleUrlValidatorResponse; | ||
} | ||
|
||
toggle(enable) { | ||
if (this.enabled === enable) { | ||
return; | ||
} | ||
|
||
this.enabled = enable; | ||
if (this.enabled) { | ||
chrome.webRequest.onBeforeRequest.addListener(doSafeRedirect, { | ||
urls: ['http://*/*', 'https://*/*'], | ||
types: ['main_frame'] | ||
}, ['blocking']); | ||
} | ||
else { | ||
chrome.webRequest.onBeforeRequest.removeListener(doSafeRedirect); | ||
} | ||
|
||
return this.enabled; | ||
} | ||
} | ||
|
||
export default new SafeUrl(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
import chrome from 'sinon-chrome'; | ||
import sinon from 'sinon'; | ||
import xhr from 'xhr'; | ||
import SafeUrl from './safe-url'; | ||
|
||
describe('app/scripts/background/safe-url.js', () => { | ||
|
||
beforeAll(() => { | ||
global.chrome = chrome; | ||
}); | ||
|
||
describe('enabled', () => { | ||
|
||
it('should be disabled by default', () => { | ||
expect(SafeUrl.enabled).toBeFalsy(); | ||
}); | ||
}); | ||
|
||
describe('toggle', () => { | ||
|
||
it('should enable safe url', () => { | ||
chrome.webRequest.onBeforeRequest.addListener.resetHistory(); | ||
|
||
SafeUrl.enabled = false; | ||
const enabled = SafeUrl.toggle(true); | ||
const callArgs = chrome.webRequest.onBeforeRequest.addListener.getCall(0).args; | ||
|
||
expect(enabled).toBeTruthy(); | ||
expect(callArgs.length).toEqual(3); | ||
expect(typeof callArgs[0]).toBe('function'); | ||
expect(callArgs[1]).toEqual({urls: ['http://*/*', 'https://*/*'], types: ['main_frame']}); | ||
expect(callArgs[2]).toEqual(['blocking']); | ||
}); | ||
|
||
it('shold not change enabled state', () => { | ||
SafeUrl.enabled = false; | ||
expect(typeof SafeUrl.toggle(false)).toBe('undefined'); | ||
}); | ||
|
||
it('should disable safe url', () => { | ||
chrome.webRequest.onBeforeRequest.removeListener.resetHistory(); | ||
|
||
SafeUrl.enabled = true; | ||
const enabled = SafeUrl.toggle(false); | ||
const callArgs = chrome.webRequest.onBeforeRequest.removeListener.getCall(0).args; | ||
|
||
expect(enabled).toBeFalsy(); | ||
expect(callArgs.length).toEqual(1); | ||
expect(typeof callArgs[0]).toBe('function'); | ||
}); | ||
|
||
}); | ||
|
||
describe('_handleUrlValidatorResponse', () => { | ||
|
||
it('should mark url as infected', () => { | ||
SafeUrl._handleUrlValidatorResponse('a1', 'error', {}); | ||
expect(SafeUrl._cleanUrls.has('a1')).toBeTruthy(); | ||
|
||
SafeUrl._handleUrlValidatorResponse('a2', '', {headers: {status: '200'}}); | ||
expect(SafeUrl._cleanUrls.has('a2')).toBeTruthy(); | ||
|
||
SafeUrl._handleUrlValidatorResponse('a3', '', {headers: {status: '404'}}); | ||
expect(SafeUrl._cleanUrls.has('a3')).toBeTruthy(); | ||
}); | ||
|
||
it('should mark the url as infected', () => { | ||
SafeUrl._handleUrlValidatorResponse('b1', '', {headers: {status: '400'}}); | ||
expect(SafeUrl._infectedUrls.has('b1')).toBeTruthy(); | ||
}); | ||
|
||
}); | ||
|
||
describe('_doSafeRedirect', () => { | ||
|
||
it('should not redirect metadefender safe redirect endpoint', () => { | ||
expect(typeof SafeUrl._doSafeRedirect({type: 'main_frame', url: `${MCL.config.mclDomain}/safe-redirect/`})).toBe('undefined'); | ||
}); | ||
|
||
it('should not redirect clean URLs', () => { | ||
const testUrl = 'http://metadefender.opswat.com'; | ||
const details = { | ||
url: testUrl | ||
}; | ||
sinon.stub(xhr, 'get').callsFake(() => SafeUrl._handleUrlValidatorResponse(testUrl, 'error', {})); | ||
|
||
const redirect = SafeUrl._doSafeRedirect(details); | ||
expect(typeof redirect).toBe('undefined'); | ||
|
||
xhr.get.restore(); | ||
}); | ||
|
||
it('should redirect infected URLs', () => { | ||
const testUrl = 'http://infected.url'; | ||
const details = { | ||
url: testUrl | ||
}; | ||
sinon.stub(xhr, 'get').callsFake(() => SafeUrl._handleUrlValidatorResponse(testUrl, '', {headers: {status: '400'}})); | ||
|
||
const redirect = SafeUrl._doSafeRedirect(details); | ||
expect(typeof redirect.redirectUrl).toBe('string'); | ||
expect(redirect.redirectUrl.startsWith(`${MCL.config.mclDomain}/safe-redirect/`)).toBeTruthy(); | ||
expect(redirect.redirectUrl.endsWith(encodeURIComponent(testUrl))).toBeTruthy(); | ||
|
||
xhr.get.restore(); | ||
}); | ||
|
||
it('should not redirect infected URLs on second access', () => { | ||
const testUrl = 'http://infected.url/access'; | ||
const details = { | ||
url: testUrl | ||
}; | ||
sinon.stub(xhr, 'get').callsFake(() => SafeUrl._handleUrlValidatorResponse(testUrl, '', {headers: {status: '400'}})); | ||
|
||
SafeUrl._doSafeRedirect(details); | ||
expect(typeof SafeUrl._doSafeRedirect(details)).toBe('undefined'); | ||
|
||
xhr.get.restore(); | ||
}); | ||
}); | ||
|
||
}); |
Oops, something went wrong.