├── .npmignore ├── dist ├── js │ ├── libraries │ │ ├── wappalyzer.js │ │ ├── VulnerableApplicationLibrary.js │ │ ├── Library.js │ │ ├── ApplicationLibrary.js │ │ └── showLibraries.js │ ├── models │ │ ├── contrastCredentials.js │ │ ├── DomainStorage.js │ │ ├── VulnerableTab.js │ │ ├── Application.js │ │ ├── ConnectedDomain.js │ │ ├── Vulnerability.js │ │ ├── ApplicationTable.js │ │ └── PopupTableRow.js │ ├── popup.js │ ├── index.js │ ├── queue.js │ ├── content-scripts │ │ ├── ContrastForms.js │ │ └── content-script.js │ ├── popupMethods.js │ └── background.js ├── img │ ├── icon.png │ ├── ring-alt.gif │ ├── contrast-on.png │ ├── contrast128.png │ ├── contrast16.png │ ├── contrast48.png │ ├── getStarted.png │ ├── contrast-off.png │ ├── 403Unauthorized.jpg │ ├── 404PageNotFound.jpg │ ├── glyphicons-cog.png │ ├── loginBackground.png │ ├── contrastLogoLarge.png │ ├── contrast-not-configured.png │ └── trash.svg ├── html │ └── background.html ├── manifest.json └── scripts │ ├── md5.min.js │ └── murmurHash3.min.js ├── test ├── spec │ ├── content-script-spec.js │ ├── models │ │ ├── ApplicationTable-spec.js │ │ ├── ContrastCredentials-spec.js │ │ ├── Application-spec.js │ │ └── Config-spec.js │ └── settings-spec.js ├── __setups__ │ └── chrome.js ├── mocks │ └── storageMock.js └── snapshots │ └── index.test.js ├── img ├── icon.png ├── ring-alt.gif ├── contrast-on.png ├── contrast128.png ├── contrast16.png ├── contrast48.png ├── getStarted.png ├── contrast-off.png ├── 403Unauthorized.jpg ├── 404PageNotFound.jpg ├── glyphicons-cog.png ├── loginBackground.png ├── contrastLogoLarge.png ├── contrast-not-configured.png └── trash.svg ├── .babelrc ├── .gitignore ├── .travis.yml ├── .prettierrc.json ├── html └── background.html ├── wapp-service ├── package.json └── index.js ├── setup.sh ├── scripts ├── deploy.sh ├── test.sh ├── pre_push.sh ├── bab.sh ├── md5.min.js └── murmurHash3.min.js ├── gulpfile.js ├── js ├── libraries │ ├── wappalyzer.js │ ├── VulnerableApplicationLibrary.js │ ├── Library.js │ ├── ApplicationLibrary.js │ └── showLibraries.js ├── models │ ├── contrastCredentials.js │ ├── DomainStorage.js │ ├── VulnerableTab.js │ ├── ConnectedDomain.js │ ├── Application.js │ ├── Vulnerability.js │ └── PopupTableRow.js ├── popup.js ├── queue.js ├── index.js ├── popupMethods.js └── content-scripts │ └── ContrastForms.js ├── lib ├── libraries │ ├── wappalyzer.js │ ├── VulnerableApplicationLibrary.js │ └── Library.js ├── models │ ├── contrastCredentials.js │ ├── DomainStorage.js │ ├── VulnerableTab.js │ ├── ConnectedDomain.js │ └── Application.js ├── popup.js ├── popupMethods.js ├── content-scripts │ └── ContrastForms.js └── index.js ├── package.json ├── manifest.json ├── README.md └── requirements.md /.npmignore: -------------------------------------------------------------------------------- 1 | wapp-service/ 2 | -------------------------------------------------------------------------------- /dist/js/libraries/wappalyzer.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/spec/content-script-spec.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/__setups__/chrome.js: -------------------------------------------------------------------------------- 1 | require('jest-webextension-mock'); 2 | -------------------------------------------------------------------------------- /img/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Contrast-Security-OSS/contrast-chrome-extension/master/img/icon.png -------------------------------------------------------------------------------- /img/ring-alt.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Contrast-Security-OSS/contrast-chrome-extension/master/img/ring-alt.gif -------------------------------------------------------------------------------- /dist/img/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Contrast-Security-OSS/contrast-chrome-extension/master/dist/img/icon.png -------------------------------------------------------------------------------- /img/contrast-on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Contrast-Security-OSS/contrast-chrome-extension/master/img/contrast-on.png -------------------------------------------------------------------------------- /img/contrast128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Contrast-Security-OSS/contrast-chrome-extension/master/img/contrast128.png -------------------------------------------------------------------------------- /img/contrast16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Contrast-Security-OSS/contrast-chrome-extension/master/img/contrast16.png -------------------------------------------------------------------------------- /img/contrast48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Contrast-Security-OSS/contrast-chrome-extension/master/img/contrast48.png -------------------------------------------------------------------------------- /img/getStarted.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Contrast-Security-OSS/contrast-chrome-extension/master/img/getStarted.png -------------------------------------------------------------------------------- /dist/img/ring-alt.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Contrast-Security-OSS/contrast-chrome-extension/master/dist/img/ring-alt.gif -------------------------------------------------------------------------------- /img/contrast-off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Contrast-Security-OSS/contrast-chrome-extension/master/img/contrast-off.png -------------------------------------------------------------------------------- /dist/img/contrast-on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Contrast-Security-OSS/contrast-chrome-extension/master/dist/img/contrast-on.png -------------------------------------------------------------------------------- /dist/img/contrast128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Contrast-Security-OSS/contrast-chrome-extension/master/dist/img/contrast128.png -------------------------------------------------------------------------------- /dist/img/contrast16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Contrast-Security-OSS/contrast-chrome-extension/master/dist/img/contrast16.png -------------------------------------------------------------------------------- /dist/img/contrast48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Contrast-Security-OSS/contrast-chrome-extension/master/dist/img/contrast48.png -------------------------------------------------------------------------------- /dist/img/getStarted.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Contrast-Security-OSS/contrast-chrome-extension/master/dist/img/getStarted.png -------------------------------------------------------------------------------- /img/403Unauthorized.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Contrast-Security-OSS/contrast-chrome-extension/master/img/403Unauthorized.jpg -------------------------------------------------------------------------------- /img/404PageNotFound.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Contrast-Security-OSS/contrast-chrome-extension/master/img/404PageNotFound.jpg -------------------------------------------------------------------------------- /img/glyphicons-cog.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Contrast-Security-OSS/contrast-chrome-extension/master/img/glyphicons-cog.png -------------------------------------------------------------------------------- /img/loginBackground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Contrast-Security-OSS/contrast-chrome-extension/master/img/loginBackground.png -------------------------------------------------------------------------------- /dist/img/contrast-off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Contrast-Security-OSS/contrast-chrome-extension/master/dist/img/contrast-off.png -------------------------------------------------------------------------------- /img/contrastLogoLarge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Contrast-Security-OSS/contrast-chrome-extension/master/img/contrastLogoLarge.png -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["env"], 3 | "plugins": [ 4 | "transform-runtime", 5 | "transform-async-to-generator" 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /dist/img/403Unauthorized.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Contrast-Security-OSS/contrast-chrome-extension/master/dist/img/403Unauthorized.jpg -------------------------------------------------------------------------------- /dist/img/404PageNotFound.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Contrast-Security-OSS/contrast-chrome-extension/master/dist/img/404PageNotFound.jpg -------------------------------------------------------------------------------- /dist/img/glyphicons-cog.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Contrast-Security-OSS/contrast-chrome-extension/master/dist/img/glyphicons-cog.png -------------------------------------------------------------------------------- /dist/img/loginBackground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Contrast-Security-OSS/contrast-chrome-extension/master/dist/img/loginBackground.png -------------------------------------------------------------------------------- /dist/img/contrastLogoLarge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Contrast-Security-OSS/contrast-chrome-extension/master/dist/img/contrastLogoLarge.png -------------------------------------------------------------------------------- /img/contrast-not-configured.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Contrast-Security-OSS/contrast-chrome-extension/master/img/contrast-not-configured.png -------------------------------------------------------------------------------- /dist/img/contrast-not-configured.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Contrast-Security-OSS/contrast-chrome-extension/master/dist/img/contrast-not-configured.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .nyc_output 3 | node_modules/ 4 | tests_output 5 | 6 | dist/* 7 | dist.zip 8 | !dist/.keep 9 | 10 | builds/* 11 | !builds/.keep 12 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | dist: trusty 2 | sudo: required 3 | language: node_js 4 | node_js: 5 | - '8' 6 | before_install: 7 | - npm install -g mocha eslint 8 | - npm install 9 | script: 10 | - npm run bab && eslint js/ 11 | -------------------------------------------------------------------------------- /img/trash.svg: -------------------------------------------------------------------------------- 1 | 5 | -------------------------------------------------------------------------------- /dist/img/trash.svg: -------------------------------------------------------------------------------- 1 | 5 | -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "semi": true, 3 | "singleQuote": false, 4 | "tabWidth": 2, 5 | "trailingComma": "es5", 6 | "bracketSpacing": true, 7 | "jsxBracketSameLine": true, 8 | "arrowParens": "always", 9 | "insertPragma": true, 10 | "printWidth": 80, 11 | "proseWrap": "always" 12 | } 13 | -------------------------------------------------------------------------------- /html/background.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /dist/html/background.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /wapp-service/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "wapp-service", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "express": "^4.16.3", 14 | "wappalyzer": "^5.5.1" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /dist/js/models/contrastCredentials.js: -------------------------------------------------------------------------------- 1 | import{CONTRAST_USERNAME,CONTRAST_SERVICE_KEY,CONTRAST_API_KEY,CONTRAST_ORG_UUID,TEAMSERVER_URL}from"../util.js";class ContrastCredentials{constructor(R){const{apiKey:t,orgUuid:E,teamServerUrl:T,serviceKey:_,profileEmail:r}=R;this[CONTRAST_API_KEY]=t,this[CONTRAST_ORG_UUID]=E,this[TEAMSERVER_URL]=T,this[CONTRAST_SERVICE_KEY]=_,this[CONTRAST_USERNAME]=r}}export default ContrastCredentials; -------------------------------------------------------------------------------- /setup.sh: -------------------------------------------------------------------------------- 1 | GIT_DIR=$(git rev-parse --git-dir) 2 | echo "Installing Git hooks for development..." 3 | # this command creates symlink to our pre-commit script 4 | if [ -L $GIT_DIR/hooks/pre-push ]; then 5 | echo "Git hooks found, skipping" 6 | else 7 | ln -s ../../scripts/pre_push.sh $GIT_DIR/hooks/pre-push 8 | chmod +x scripts/pre_push.sh 9 | fi 10 | 11 | # echo "Installing Wappalyzer service..." 12 | # cd wapp-service 13 | # npm install 14 | # node index.js & 15 | -------------------------------------------------------------------------------- /scripts/deploy.sh: -------------------------------------------------------------------------------- 1 | # !/bin/bash 2 | 3 | PROJECT_ROOT=$(pwd) 4 | DIST_DIR="$PROJECT_ROOT/dist" 5 | 6 | rm -rf $DIST_DIR 7 | mkdir -p $DIST_DIR 8 | mkdir -p $DIST_DIR/js 9 | 10 | # cp -r js $DIST_DIR 11 | npm run gulp 12 | cp -r img $DIST_DIR 13 | cp -r html $DIST_DIR 14 | cp -r scripts $DIST_DIR 15 | cp style.css $DIST_DIR 16 | cp manifest.json $DIST_DIR 17 | 18 | rm -rfv $DIST_DIR/scripts/*.sh 19 | 20 | timestamp=$(date +"%Y-%m-%d_%H-%M-%S") 21 | 22 | mkdir -p $PROJECT_ROOT/builds 23 | zip -r $PROJECT_ROOT/builds/contrast-${timestamp}.zip $DIST_DIR 24 | -------------------------------------------------------------------------------- /test/mocks/storageMock.js: -------------------------------------------------------------------------------- 1 | const storage = {}; 2 | const storageMock = { 3 | setItem: function(key, value) { 4 | storage[key] = value || ''; 5 | }, 6 | getItem: function(key) { 7 | return key in storage ? storage[key] : null; 8 | }, 9 | removeItem: function(key) { 10 | delete storage[key]; 11 | }, 12 | get length() { 13 | return Object.keys(storage).length; 14 | }, 15 | key: function(i) { 16 | var keys = Object.keys(storage); 17 | return keys[i] || null; 18 | } 19 | } 20 | 21 | module.exports = storageMock; 22 | -------------------------------------------------------------------------------- /dist/js/models/DomainStorage.js: -------------------------------------------------------------------------------- 1 | import{CONNECTED_APP_DOMAINS}from"../util.js";class DomainStorage{constructor(){const t=this._getDomainsFromStorage();this.domains=["http://localhost:*/*"].concat(t)}_getDomainsFromStorage(){const t=window.localStorage.getItem(CONNECTED_APP_DOMAINS);return t?"string"==typeof t?JSON.parse(t):t:[]}addDomainsToStorage(t){let o=this._getDomainsFromStorage();o=o.concat(t),this._setNewDomains(o)}removeDomainsFromStorage(t){let o=this._getDomainsFromStorage();o=o.filter(o=>!t.includes(o)),this._setNewDomains(o)}_setNewDomains(t){this.domains=t,window.localStorage.setItem(CONNECTED_APP_DOMAINS,JSON.stringify(t))}}export default DomainStorage; -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | const gulp = require('gulp'); 2 | // const uglify = require('gulp-uglify'); 3 | const uglify = require('gulp-uglify-es').default; 4 | const pump = require('pump'); 5 | 6 | console.log("Running Gulp"); 7 | 8 | gulp.task('default', ['compress']) 9 | 10 | gulp.task('compress', function (cb) { 11 | console.log("Gulp Compressing"); 12 | pump([ 13 | gulp.src('js/**/*.js'), 14 | uglify({ 15 | warnings: "verbose", 16 | }), 17 | gulp.dest('dist/js') 18 | ], 19 | cb 20 | ); 21 | }); 22 | 23 | // function callback() { 24 | // console.log("Gulp Callback"); 25 | // } 26 | // gulp.tasks.compress.fn(callback); 27 | -------------------------------------------------------------------------------- /js/libraries/wappalyzer.js: -------------------------------------------------------------------------------- 1 | // /*global 2 | // chrome, 3 | // */ 4 | // 5 | // import { WAPPALYZER_SERVICE } from "../util.js"; 6 | // 7 | // const wappalzye = async tab => { 8 | // const tabURL = new URL(tab.url); 9 | // const response = await fetch(WAPPALYZER_SERVICE + "?site=" + tabURL.href); 10 | // if (response.ok && response.status === 200) { 11 | // const json = await response.json(); 12 | // if (json.success) { 13 | // return json.libraries.applications; 14 | // } 15 | // return null; 16 | // } 17 | // // console.log("ERROR IN WAPPALYZE RESPONSE", response); 18 | // return null; 19 | // }; 20 | // 21 | // export { wappalzye }; 22 | -------------------------------------------------------------------------------- /lib/libraries/wappalyzer.js: -------------------------------------------------------------------------------- 1 | // /*global 2 | // chrome, 3 | // */ 4 | // 5 | // import { WAPPALYZER_SERVICE } from "../util.js"; 6 | // 7 | // const wappalzye = async tab => { 8 | // const tabURL = new URL(tab.url); 9 | // const response = await fetch(WAPPALYZER_SERVICE + "?site=" + tabURL.href); 10 | // if (response.ok && response.status === 200) { 11 | // const json = await response.json(); 12 | // if (json.success) { 13 | // return json.libraries.applications; 14 | // } 15 | // return null; 16 | // } 17 | // // console.log("ERROR IN WAPPALYZE RESPONSE", response); 18 | // return null; 19 | // }; 20 | // 21 | // export { wappalzye }; 22 | "use strict"; -------------------------------------------------------------------------------- /js/models/contrastCredentials.js: -------------------------------------------------------------------------------- 1 | import { 2 | CONTRAST_USERNAME, 3 | CONTRAST_SERVICE_KEY, 4 | CONTRAST_API_KEY, 5 | CONTRAST_ORG_UUID, 6 | TEAMSERVER_URL, 7 | } from '../util.js'; 8 | 9 | class ContrastCredentials { 10 | constructor(options) { 11 | const { 12 | apiKey, 13 | orgUuid, 14 | teamServerUrl, 15 | serviceKey, 16 | profileEmail, 17 | } = options; 18 | this[CONTRAST_API_KEY] = apiKey; 19 | this[CONTRAST_ORG_UUID] = orgUuid; 20 | this[TEAMSERVER_URL] = teamServerUrl; 21 | this[CONTRAST_SERVICE_KEY] = serviceKey; 22 | this[CONTRAST_USERNAME] = profileEmail; 23 | } 24 | } 25 | 26 | export default ContrastCredentials; 27 | -------------------------------------------------------------------------------- /test/spec/models/ApplicationTable-spec.js: -------------------------------------------------------------------------------- 1 | const chrome = require("sinon-chrome/extensions"); 2 | global.chrome = chrome; 3 | 4 | const url = require("url"); 5 | global.URL = url.URL; 6 | 7 | const jsdom = require("jsdom"); 8 | const { JSDOM } = jsdom; 9 | global.window = new JSDOM("
", { url: "http://localhost" }).window; 10 | global.document = global.window.document; 11 | 12 | const sinon = require("sinon"); 13 | const chai = require("chai"); 14 | const { expect } = chai; 15 | const util = require('../../../lib/util.js'); 16 | const testData = require('../../testData.js'); 17 | const ApplicationTable = require('../../../lib/models/ApplicationTable.js').default; 18 | -------------------------------------------------------------------------------- /scripts/test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | DIR=$(pwd) 4 | SNAP_DIR="__snapshots__" 5 | 6 | echo "$(tput setaf 2) Running Mocha tests...$(tput sgr0)" 7 | node ./node_modules/nyc/bin/nyc.js ./node_modules/mocha/bin/mocha ${DIR}/test/spec/* 8 | echo "" 9 | 10 | echo "$(tput setaf 2) Creating a new __snapshots__ folder in project root.$(tput sgr0)" 11 | mkdir -p ${DIR}/${SNAP_DIR} 12 | echo "" 13 | 14 | echo "$(tput setaf 2) Copying snapshot files from test dir to snapshot dir.$(tput sgr0)" 15 | cp -r ${DIR}/test/${SNAP_DIR}/ ${DIR}/${SNAP_DIR} 16 | echo "" 17 | 18 | echo "$(tput setaf 2) Running Snapshot tests...$(tput sgr0)" 19 | ./node_modules/mocha/bin/mocha test/snapshots/* 20 | echo "" 21 | 22 | echo "$(tput setaf 2) Cleaning up snapshot directory in project root. $(tput sgr0)" 23 | rm -rf ${DIR}/${SNAP_DIR} 24 | echo "" 25 | -------------------------------------------------------------------------------- /dist/js/popup.js: -------------------------------------------------------------------------------- 1 | import{getStorageVulnsAndRender,hideLoadingIcon}from"./popupMethods.js";import{STORED_APPS_KEY,getStoredCredentials,isCredentialed,getHostFromUrl,isEmptyObject,setElementDisplay}from"./util.js";function renderLoadingIcon(){document.getElementById("vulns-loading").style.display="block"}document.addEventListener("DOMContentLoaded",()=>{chrome.storage.local.get(STORED_APPS_KEY,e=>{chrome.tabs.query({active:!0,currentWindow:!0},t=>{if(!t[0])return;const n=t[0],o=new URL(n.url),r=getHostFromUrl(o),d=e[STORED_APPS_KEY],i=d?d.filter(e=>e[r])[0]:d;if(i&&!isEmptyObject(i))getStoredCredentials().then(e=>{if(!isCredentialed(e))throw new Error("Not Credentialed");renderLoadingIcon(),getStorageVulnsAndRender(e,i,n)}).catch(e=>new Error(e));else{const e=document.getElementById("vulnerabilities-found-on-page");setElementDisplay(e,"none"),hideLoadingIcon()}})})},!1); -------------------------------------------------------------------------------- /dist/js/index.js: -------------------------------------------------------------------------------- 1 | import{getStoredCredentials,isCredentialed}from"./util.js";import Application from"./models/Application.js";import ApplicationTable from"./models/ApplicationTable.js";import Config from"./models/Config.js";export function indexFunction(){chrome.tabs.query({active:!0,currentWindow:!0},e=>{const n=e[0],t=new URL(n.url);getStoredCredentials().then(async e=>{const o=isCredentialed(e),i=await Application.retrieveApplicationFromStorage(n),r=new Config(n,t,o,e,!!i);if(r.addListenerToConfigButton(),r.popupScreen(),o){if(o&&r._isContrastPage()){new ApplicationTable(t).renderApplicationsMenu(),r.setGearIcon(),r.renderContrastUsername()}else if(r.setGearIcon(),r.renderContrastUsername(),!r._isContrastPage()){const e=new ApplicationTable(t);e.renderActivityFeed(),r.hasApp&&e.renderApplicationsMenu()}}else console.log("Please Configure the Extension")}).catch(e=>new Error(e))})}document.addEventListener("DOMContentLoaded",indexFunction,!1); -------------------------------------------------------------------------------- /scripts/pre_push.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # NOTE: YOU MUST INSTALL GNU SED FIRST 4 | # With Homebrew: brew install gnu-sed 5 | 6 | # get files that have console.log 7 | # console_log_files=$(grep -lr 'console.log' js/*.js) 8 | 9 | # search lines with console.log in console_log_files and remove the line 10 | # for file in $console_log_files; do 11 | # echo "Removing console.logs from $file" 12 | # $(sed -i '/console.log/d' $file) 13 | # done 14 | 15 | # debugger_files=$(grep -lr 'debugger' js/*.js) 16 | # for file in $debugger_files; do 17 | # echo "Removing debuggers from $file" 18 | # $(sed -i '/debugger/d' $file) 19 | # done 20 | # 21 | # # search for localhost in utils file 22 | # localhost_file=$(grep -lr 'localhost' js/helpers/helpers.js) 23 | # for file in $localhost_file; do 24 | # echo "Removing localhost from $file" 25 | # $(sed -i '/localhost/d' $file) 26 | # done 27 | 28 | git add . 29 | 30 | echo $(git status) 31 | 32 | git commit --amend --no-edit 33 | 34 | npm run bab && node ./node_modules/eslint/bin/eslint.js js/ 35 | -------------------------------------------------------------------------------- /lib/models/contrastCredentials.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | 7 | var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); 8 | 9 | var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); 10 | 11 | var _util = require('../util.js'); 12 | 13 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 14 | 15 | var ContrastCredentials = function ContrastCredentials(options) { 16 | (0, _classCallCheck3.default)(this, ContrastCredentials); 17 | var apiKey = options.apiKey, 18 | orgUuid = options.orgUuid, 19 | teamServerUrl = options.teamServerUrl, 20 | serviceKey = options.serviceKey, 21 | profileEmail = options.profileEmail; 22 | 23 | this[_util.CONTRAST_API_KEY] = apiKey; 24 | this[_util.CONTRAST_ORG_UUID] = orgUuid; 25 | this[_util.TEAMSERVER_URL] = teamServerUrl; 26 | this[_util.CONTRAST_SERVICE_KEY] = serviceKey; 27 | this[_util.CONTRAST_USERNAME] = profileEmail; 28 | }; 29 | 30 | exports.default = ContrastCredentials; -------------------------------------------------------------------------------- /scripts/bab.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | 4 | DIR=$(pwd) 5 | SNAP_DIR="__snapshots__" 6 | 7 | echo "$(tput setaf 2) Running Babel, placing transpiled files into lib directory.$(tput sgr0)" 8 | babel ${DIR}/js --out-dir ${DIR}/lib 9 | echo "" 10 | 11 | echo "$(tput setaf 2) Running Mocha tests...$(tput sgr0)" 12 | node ./node_modules/nyc/bin/nyc.js node_modules/mocha/bin/mocha ${DIR}/test/spec/* 13 | echo "" 14 | 15 | echo "$(tput setaf 2) Creating a new __snapshots__ folder in project root.$(tput sgr0)" 16 | mkdir -p ${DIR}/${SNAP_DIR} 17 | mkdir -p ${DIR}/test/${SNAP_DIR} 18 | echo "" 19 | 20 | echo "$(tput setaf 2) Copying snapshot files from test dir to snapshot dir.$(tput sgr0)" 21 | cp -r ${DIR}/test/${SNAP_DIR}/* ${DIR}/${SNAP_DIR}/* 22 | echo "" 23 | 24 | echo "$(tput setaf 2) Running Snapshot tests...$(tput sgr0)" 25 | ./node_modules/mocha/bin/mocha test/snapshots/* 26 | echo "" 27 | 28 | echo "$(tput setaf 2) Copying Snapshots back to test directory $(tput sgr0)" 29 | cp -r ${DIR}/${SNAP_DIR} ${DIR}/test/${SNAP_DIR}/* 30 | 31 | echo "$(tput setaf 2) Cleaning up snapshot directory in project root. $(tput sgr0)" 32 | rm -rf ${DIR}/${SNAP_DIR} 33 | echo "" 34 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "repository": "https://github.com/Contrast-Security-OSS/contrast-chrome-extension", 3 | "scripts": { 4 | "test": "scripts/test.sh", 5 | "bab": "scripts/bab.sh", 6 | "lint": "eslint js/", 7 | "prettier": "prettier --config .prettierrc.json js/*", 8 | "build": "scripts/deploy.sh", 9 | "gulp": "gulp" 10 | }, 11 | "devDependencies": { 12 | "babel-cli": "^6.26.0", 13 | "babel-plugin-transform-async-to-generator": "^6.24.1", 14 | "babel-plugin-transform-runtime": "^6.23.0", 15 | "babel-preset-env": "^1.7.0", 16 | "btoa": "^1.2.1", 17 | "chai": "^4.1.2", 18 | "eslint": "^5.16.0", 19 | "gulp": "^3.9.1", 20 | "gulp-uglify": "^3.0.1", 21 | "gulp-uglify-es": "^1.0.4", 22 | "jest-webextension-mock": "^3.4.0", 23 | "jsdom": "^11.11.0", 24 | "mocha": "^6.1.4", 25 | "node-fetch": "^2.1.2", 26 | "nyc": "^12.0.2", 27 | "prettier": "1.14.2", 28 | "pump": "^3.0.0", 29 | "sinon": "^5.0.10", 30 | "sinon-chrome": "^2.3.2", 31 | "snap-shot-it": "^6.1.8" 32 | }, 33 | "jest": { 34 | "setupFiles": [ 35 | "./test/__setups__/chrome.js" 36 | ] 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /dist/js/models/VulnerableTab.js: -------------------------------------------------------------------------------- 1 | import{deDupeArray,murmur,isEmptyObject}from"../util.js";function VulnerableTabError(a,t,e){throw new Error(a,t,e)}function VulnerableTab(a,t,e=[]){this.traceIDs=e,this.path=a.split("?")[0],this.vulnTabId=murmur(this.path+"|"+t),this.appNameHash=murmur(t)}VulnerableTab.prototype.setTraceIDs=function(a){this.traceIDs=deDupeArray(this.traceIDs.concat(a))},VulnerableTab.prototype.storeTab=function(){return new Promise(async(a,t)=>{let e=await this.getApplicationTabs();e[this.appNameHash][this.vulnTabId]=this.traceIDs,chrome.storage.local.set(e,()=>{chrome.storage.local.get(this.appNameHash,e=>{e&&e[this.appNameHash]?a(e[this.appNameHash]):t(new VulnerableTabError("Error Storing Tab",this.vulnTabId,this.path))})})})},VulnerableTab.prototype.getApplicationTabs=function(){return new Promise(a=>{chrome.storage.local.get(this.appNameHash,t=>{t&&!isEmptyObject(t)||(t[this.appNameHash]={}),a(t)})})},VulnerableTab.prototype.getStoredTab=function(){return new Promise(a=>{chrome.storage.local.get(this.appNameHash,t=>{t&&t[this.appNameHash]?a(t[this.appNameHash]):a(null)})})},VulnerableTab.buildTabPath=function(a){const t=new URL(a);let e=t.pathname;return t.hash&&(e+=t.hash),e};export default VulnerableTab; -------------------------------------------------------------------------------- /manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "manifest_version": 2, 3 | "name": "Contrast", 4 | "description": "Allows the user to get information from Contrast conveniently in a Chrome extension", 5 | "version": "0.1", 6 | "browser_action": { 7 | "default_icon": "img/contrast-not-configured.png", 8 | "default_popup": "html/index.html" 9 | }, 10 | "background": { 11 | "page": "html/background.html", 12 | "persistent": true 13 | }, 14 | "content_scripts": [ 15 | { 16 | "matches": [ 17 | "http://*/*", 18 | "https://*/*" 19 | ], 20 | "js": [ 21 | "js/content-scripts/content-utils.js", 22 | "js/content-scripts/ContrastForms.js", 23 | "js/content-scripts/content-script.js" 24 | ] 25 | } 26 | ], 27 | "icons": { 28 | "16": "img/contrast16.png", 29 | "48": "img/contrast48.png", 30 | "128": "img/contrast128.png" 31 | }, 32 | "web_accessible_resources": [ 33 | "img/*.png", 34 | "test/*", 35 | "data/*" 36 | ], 37 | "permissions": [ 38 | "webRequest", 39 | "activeTab", 40 | "storage", 41 | "http://*/*", 42 | "https://*/*", 43 | "https://*.contrastsecurity.com/", 44 | "tabs", 45 | "background", 46 | "notifications" 47 | ] 48 | } 49 | -------------------------------------------------------------------------------- /dist/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "manifest_version": 2, 3 | "name": "Contrast", 4 | "description": "Allows the user to get information from Contrast conveniently in a Chrome extension", 5 | "version": "0.1", 6 | "browser_action": { 7 | "default_icon": "img/contrast-not-configured.png", 8 | "default_popup": "html/index.html" 9 | }, 10 | "background": { 11 | "page": "html/background.html", 12 | "persistent": true 13 | }, 14 | "content_scripts": [ 15 | { 16 | "matches": [ 17 | "http://*/*", 18 | "https://*/*" 19 | ], 20 | "js": [ 21 | "js/content-scripts/content-utils.js", 22 | "js/content-scripts/ContrastForms.js", 23 | "js/content-scripts/content-script.js" 24 | ] 25 | } 26 | ], 27 | "icons": { 28 | "16": "img/contrast16.png", 29 | "48": "img/contrast48.png", 30 | "128": "img/contrast128.png" 31 | }, 32 | "web_accessible_resources": [ 33 | "img/*.png", 34 | "test/*", 35 | "data/*" 36 | ], 37 | "permissions": [ 38 | "webRequest", 39 | "activeTab", 40 | "storage", 41 | "http://*/*", 42 | "https://*/*", 43 | "https://*.contrastsecurity.com/", 44 | "tabs", 45 | "background", 46 | "notifications" 47 | ] 48 | } 49 | -------------------------------------------------------------------------------- /js/models/DomainStorage.js: -------------------------------------------------------------------------------- 1 | /*eslint no-console: ["error", { allow: ["warn", "error", "log"] }] */ 2 | import { 3 | CONNECTED_APP_DOMAINS, 4 | } from '../util.js'; 5 | 6 | class DomainStorage { 7 | constructor() { 8 | const domains = this._getDomainsFromStorage(); 9 | this.domains = ["http://localhost:*/*"].concat(domains); 10 | } 11 | 12 | _getDomainsFromStorage() { // eslint-disable-line 13 | const domains = window.localStorage.getItem(CONNECTED_APP_DOMAINS); 14 | if (!domains) { 15 | return []; 16 | } else if (typeof domains === 'string') { 17 | return JSON.parse(domains); 18 | } 19 | return domains; 20 | } 21 | 22 | addDomainsToStorage(requestDomains) { 23 | let domains = this._getDomainsFromStorage(); 24 | domains = domains.concat(requestDomains); 25 | this._setNewDomains(domains); 26 | } 27 | 28 | removeDomainsFromStorage(requestDomains) { 29 | let domains = this._getDomainsFromStorage(); 30 | domains = domains.filter(d => !requestDomains.includes(d)); 31 | this._setNewDomains(domains); 32 | } 33 | 34 | _setNewDomains(domains) { 35 | this.domains = domains; 36 | window.localStorage.setItem(CONNECTED_APP_DOMAINS, JSON.stringify(domains)); 37 | } 38 | } 39 | 40 | export default DomainStorage; 41 | -------------------------------------------------------------------------------- /dist/js/libraries/VulnerableApplicationLibrary.js: -------------------------------------------------------------------------------- 1 | class VulnerableApplicationLibrary{constructor(e){this.name=e.name||e.parsedLibName,this.vulnerabilities=e.vulnerabilities,this.vulnerabilitiesCount=e.vulnerabilities.length,this.version=e.version}lowConfidenceVulnerabilities(){return{name:this.name,confidenceIsCorrectLibrary:"LOW",vulnerabilitiesCount:this.vulnerabilitiesCount,vulnerabilities:this.vulnerabilities.map(e=>{let i={};return e.atOrAbove&&(i.atOrAbove=e.atOrAbove),e.atOrBelow&&(i.atOrBelow=e.atOrBelow),e.above&&(i.above=e.above),e.below&&(i.below=e.below),{title:e.identifiers.summary,link:e.info[0],severity:e.severity,versions:i}})}}highConfidenceVulnerability(){let e=this._isCorrectVersion(this.vulnerabilities,this.version);return e?{name:this.name,severity:e.severity,title:e.identifiers.summary,link:e.info[0],confidenceIsCorrectLibrary:"HIGH",vulnerabilities:this.vulnerabilities,vulnerabilitiesCount:this.vulnerabilitiesCount}:e}_isCorrectVersion(e,i){if(!e||!i)return!1;for(let r=0,t=e.length;r>>0};t.x86.hash128=function(a,c){a=a||"";c=c||0;for(var b=a.length%16,p= 6 | a.length-b,d=c,e=c,f=c,h=c,m=0,n=0,g=0,q=0,k=0;k
>>0).toString(16)).slice(-8)+("00000000"+(e>>>0).toString(16)).slice(-8)+("00000000"+(f>>>0).toString(16)).slice(-8)+("00000000"+(h>>>0).toString(16)).slice(-8)};t.x64.hash128=function(a,c){a=a||"";c=c||0;for(var b=a.length%16,l=a.length-b,d=[0,c],e=[0,c],f=[0,0],h=[0,0],m=[2277735313,289559509],n=[1291169091,658871167],g=0;g >>0};t.x86.hash128=function(a,c){a=a||"";c=c||0;for(var b=a.length%16,p=
6 | a.length-b,d=c,e=c,f=c,h=c,m=0,n=0,g=0,q=0,k=0;k >>0).toString(16)).slice(-8)+("00000000"+(e>>>0).toString(16)).slice(-8)+("00000000"+(f>>>0).toString(16)).slice(-8)+("00000000"+(h>>>0).toString(16)).slice(-8)};t.x64.hash128=function(a,c){a=a||"";c=c||0;for(var b=a.length%16,l=a.length-b,d=[0,c],e=[0,c],f=[0,0],h=[0,0],m=[2277735313,289559509],n=[1291169091,658871167],g=0;g