diff --git a/package-lock.json b/package-lock.json index 3d2ba976..96e00fa9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24,6 +24,7 @@ "concurrently": "^8.0.0", "connect-mongo": "^5.1.0", "cors": "^2.8.5", + "csv-parser": "^3.0.0", "diff2html": "^3.4.33", "express": "^4.18.2", "express-http-proxy": "^2.0.0", @@ -49,6 +50,7 @@ "react-router-dom": "6.26.2", "simple-git": "^3.25.0", "uuid": "^10.0.0", + "xlsx": "^0.18.5", "yargs": "^17.7.2" }, "bin": { @@ -3781,6 +3783,14 @@ "node": ">=4.0" } }, + "node_modules/adler-32": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/adler-32/-/adler-32-1.3.1.tgz", + "integrity": "sha512-ynZ4w/nUUv5rrsR8UUGoe1VC9hZj6V5hU9Qw1HlMDJGEJw5S7TfTErWTjMys6M7vr0YWcPqs3qAr4ss0nDfP+A==", + "engines": { + "node": ">=0.8" + } + }, "node_modules/aggregate-error": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", @@ -4549,6 +4559,18 @@ "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", "dev": true }, + "node_modules/cfb": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cfb/-/cfb-1.2.2.tgz", + "integrity": "sha512-KfdUZsSOw19/ObEWasvBP/Ac4reZvAGauZhs6S/gqNhXhI7cKwvlH7ulj+dOEYnca4bm4SGo8C1bTAQvnTjgQA==", + "dependencies": { + "adler-32": "~1.3.0", + "crc-32": "~1.2.0" + }, + "engines": { + "node": ">=0.8" + } + }, "node_modules/chai": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/chai/-/chai-4.5.0.tgz", @@ -4882,6 +4904,14 @@ "node": ">=6" } }, + "node_modules/codepage": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/codepage/-/codepage-1.15.0.tgz", + "integrity": "sha512-3g6NUTPd/YtuuGrhMnOMRjFc+LJw/bnMp3+0r/Wcz3IXUuCosKRJvMphm5+Q+bvTVGcJJuRvVLuYba+WojaFaA==", + "engines": { + "node": ">=0.8" + } + }, "node_modules/color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", @@ -5233,6 +5263,17 @@ "typescript": ">=4" } }, + "node_modules/crc-32": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", + "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", + "bin": { + "crc32": "bin/crc32.njs" + }, + "engines": { + "node": ">=0.8" + } + }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -5260,6 +5301,20 @@ "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.21.tgz", "integrity": "sha512-Z1PhmomIfypOpoMjRQB70jfvy/wxT50qW08YXO5lMIJkrdq4yOTR+AW7FqutScmB9NkLwxo+jU+kZLbofZZq/w==" }, + "node_modules/csv-parser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/csv-parser/-/csv-parser-3.0.0.tgz", + "integrity": "sha512-s6OYSXAK3IdKqYO33y09jhypG/bSDHPuyCme/IdEHfWpLf/jKcpitVFyOC6UemgGk8v7Q5u2XE0vvwmanxhGlQ==", + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "csv-parser": "bin/csv-parser" + }, + "engines": { + "node": ">= 10" + } + }, "node_modules/cypress": { "version": "13.14.2", "resolved": "https://registry.npmjs.org/cypress/-/cypress-13.14.2.tgz", @@ -7269,6 +7324,14 @@ "node": ">= 0.6" } }, + "node_modules/frac": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/frac/-/frac-1.1.2.tgz", + "integrity": "sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA==", + "engines": { + "node": ">=0.8" + } + }, "node_modules/fresh": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", @@ -9717,7 +9780,6 @@ "version": "1.2.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -12030,6 +12092,17 @@ "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", "dev": true }, + "node_modules/ssf": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/ssf/-/ssf-0.11.2.tgz", + "integrity": "sha512-+idbmIXoYET47hH+d7dfm2epdOMUDjqcB4648sTZ+t2JwoyBFL/insLfB/racrDmsKB3diwsDA696pZMieAC5g==", + "dependencies": { + "frac": "~1.1.2" + }, + "engines": { + "node": ">=0.8" + } + }, "node_modules/sshpk": { "version": "1.18.0", "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz", @@ -13123,6 +13196,22 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/wmf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wmf/-/wmf-1.0.2.tgz", + "integrity": "sha512-/p9K7bEh0Dj6WbXg4JG0xvLQmIadrner1bi45VMJTfnbVHsc7yIajZyoSoK60/dtVBs12Fm6WkUI5/3WAVsNMw==", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/word": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/word/-/word-0.3.0.tgz", + "integrity": "sha512-OELeY0Q61OXpdUfTp+oweA/vtLVg5VDOXh+3he3PNzLGG/y0oylSOC1xRVj0+l4vQ3tj/bB1HVHv1ocXkQceFA==", + "engines": { + "node": ">=0.8" + } + }, "node_modules/workerpool": { "version": "6.5.1", "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.5.1.tgz", @@ -13264,6 +13353,26 @@ "typedarray-to-buffer": "^3.1.5" } }, + "node_modules/xlsx": { + "version": "0.18.5", + "resolved": "https://registry.npmjs.org/xlsx/-/xlsx-0.18.5.tgz", + "integrity": "sha512-dmg3LCjBPHZnQp5/F/+nnTa+miPJxUXB6vtk42YjBBKayDNagxGEeIdWApkYPOf3Z3pm3k62Knjzp7lMeTEtFQ==", + "dependencies": { + "adler-32": "~1.3.0", + "cfb": "~1.2.1", + "codepage": "~1.15.0", + "crc-32": "~1.2.1", + "ssf": "~0.11.2", + "wmf": "~1.0.1", + "word": "~0.3.0" + }, + "bin": { + "xlsx": "bin/xlsx.njs" + }, + "engines": { + "node": ">=0.8" + } + }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", diff --git a/package.json b/package.json index 85baaed4..ceeb8cd9 100644 --- a/package.json +++ b/package.json @@ -45,6 +45,7 @@ "concurrently": "^8.0.0", "connect-mongo": "^5.1.0", "cors": "^2.8.5", + "csv-parser": "^3.0.0", "diff2html": "^3.4.33", "express": "^4.18.2", "express-http-proxy": "^2.0.0", @@ -70,6 +71,7 @@ "react-router-dom": "6.26.2", "simple-git": "^3.25.0", "uuid": "^10.0.0", + "xlsx": "^0.18.5", "yargs": "^17.7.2" }, "devDependencies": { diff --git a/proxy.config.json b/proxy.config.json index 14d016e4..35cd52a9 100644 --- a/proxy.config.json +++ b/proxy.config.json @@ -77,7 +77,8 @@ "block": { "literals": [], "patterns": [], - "providers": {} + "providers": {}, + "sensitiveFileTypes":[] } } }, diff --git a/src/proxy/chain.js b/src/proxy/chain.js index 11e6ae10..05b8c7e2 100644 --- a/src/proxy/chain.js +++ b/src/proxy/chain.js @@ -9,12 +9,14 @@ const pushActionChain = [ proc.push.checkIfWaitingAuth, proc.push.pullRemote, proc.push.writePack, - proc.push.getDiff, + proc.push.getDiff, + proc.push.checkSensitiveData, // checkSensitiveData added proc.push.clearBareClone, proc.push.scanDiff, proc.push.blockForAuth, ]; + const pullActionChain = [proc.push.checkRepoInAuthorisedList]; let pluginsInserted = false; diff --git a/src/proxy/processors/push-action/checkSensitiveData.js b/src/proxy/processors/push-action/checkSensitiveData.js new file mode 100644 index 00000000..0ea18679 --- /dev/null +++ b/src/proxy/processors/push-action/checkSensitiveData.js @@ -0,0 +1,171 @@ +const fs = require('fs'); +const csv = require('csv-parser'); +const XLSX = require('xlsx'); +const path = require('path'); +const Step = require('../../actions').Step; +const config = require('../../../config'); + +// const { exec: getDiffExec } = require('./getDiff'); +// Function to check for sensitive data patterns +const commitConfig = config.getCommitConfig(); +const checkForSensitiveData = (cell) => { + const sensitivePatterns = [ + /\d{3}-\d{2}-\d{4}/, // Social Security Number (SSN) + /\b\d{16}\b/, // Credit card numbers + /\b\d{5}-\d{4}\b/, // ZIP+4 codes + // Add more patterns as needed + ]; + return sensitivePatterns.some(pattern => { + if (pattern.test(String(cell))) { + console.log(`\x1b[31mDetected sensitive data: ${cell}\x1b[0m`); // Log the detected sensitive data in red + return true; + } + return false; + }); +}; +// Function to process CSV files +const processCSV = async (filePath) => { + return new Promise((resolve, reject) => { + let sensitiveDataFound = false; + fs.createReadStream(filePath) + .pipe(csv()) + .on('data', (row) => { + for (const [key, value] of Object.entries(row)) { + if (checkForSensitiveData(value)) { + console.log(`\x1b[33mSensitive data found in CSV: ${key}: ${value}\x1b[0m`); // Log in yellow + sensitiveDataFound = true; + } + } + }) + .on('end', () => { + if (!sensitiveDataFound) { + console.log('No sensitive data found in CSV.'); + } + resolve(sensitiveDataFound); // Resolve with the flag indicating if sensitive data was found + }) + .on('error', (err) => { + console.error(`Error reading CSV file: ${err.message}`); + reject(err); // Reject the promise on error + }); + }); +}; +// Function to process XLSX files +const processXLSX = async (filePath) => { + return new Promise((resolve, reject) => { + let sensitiveDataFound = false; + try { + const workbook = XLSX.readFile(filePath); + const sheetName = workbook.SheetNames[0]; + const sheet = workbook.Sheets[sheetName]; + const jsonData = XLSX.utils.sheet_to_json(sheet); + jsonData.forEach((row) => { + for (const [key, value] of Object.entries(row)) { + if (checkForSensitiveData(value)) { + console.log(`\x1b[33mSensitive data found in XLSX: ${key}: ${value}\x1b[0m`); // Log in yellow + sensitiveDataFound = true; + } + } + }); + if (!sensitiveDataFound) { + console.log('No sensitive data found in XLSX.'); + } + resolve(sensitiveDataFound); // Resolve with the flag indicating if sensitive data was found + } catch (error) { + console.error(`Error reading XLSX file: ${error.message}`); + reject(error); // Reject the promise on error + } + }); +}; +// Function to check for sensitive data in .log and .json files +const checkLogJsonFiles = async (filePath) => { + return new Promise((resolve, reject) => { + let sensitiveDataFound = false; + fs.readFile(filePath, 'utf8', (err, data) => { + if (err) { + console.error(`Error reading file ${filePath}: ${err.message}`); + return reject(err); + } + if (checkForSensitiveData(data)) { + console.log(`\x1b[Sensitive data found in ${filePath}\x1b[0m`); + sensitiveDataFound = true; + } + resolve(sensitiveDataFound); + }); + }); +}; +// Function to parse the file based on its extension +const parseFile = async (filePath) => { + + const ext = path.extname(filePath).toLowerCase(); + const FilestoCheck = commitConfig.diff.block.proxyFileTypes; + if(!FilestoCheck.includes(ext)){ + + console.log(`${ext} should be included in CommitConfig for proxy Check!`); + return false; + } + + switch (ext) { + case '.csv': + return await processCSV(filePath); + case '.xlsx': + return await processXLSX(filePath); + case '.log': + return await checkLogJsonFiles(filePath); + case '.json': + return await checkLogJsonFiles(filePath); + default: + // Skip unsupported file types without logging + return false; // Indicate that no sensitive data was found for unsupported types + } +}; +// Async exec function to handle actions +// Function to parse file paths from git diff content +const extractFilePathsFromDiff = (diffContent) => { + const filePaths = []; + const lines = diffContent.split('\n'); + + lines.forEach(line => { + const match = line.match(/^diff --git a\/(.+?) b\/(.+?)$/); + if (match) { + filePaths.push(match[1]); // Extract the file path from "a/" in the diff line + } + }); + + return filePaths; +}; + +const exec = async (req, action) => { + const diffStep = action.steps.find((s) => s.stepName === 'diff'); + const step = new Step('checksensitiveData'); + + if (diffStep && diffStep.content) { + console.log('Diff content:', diffStep.content); + + // Use the parsing function to get file paths + const filePaths = extractFilePathsFromDiff(diffStep.content); + + if (filePaths.length > 0) { + // Check for sensitive data in all files + const sensitiveDataFound = await Promise.all(filePaths.map(parseFile)); + const anySensitiveDataDetected = sensitiveDataFound.some(found => found); + + if (anySensitiveDataDetected) { + step.blocked= true; + step.error = true; + step.errorMessage = 'Your push has been blocked due to sensitive data detection.'; + console.log(step.errorMessage); + } + } else { + console.log('No file paths provided in the diff step.'); + } + } else { + console.log('No diff content available.'); + } + action.addStep(step); + return action; // Returning action for testing purposes +}; + + + +exec.displayName = 'logFileChanges.exec'; +exports.exec = exec; \ No newline at end of file diff --git a/src/proxy/processors/push-action/getDiff.js b/src/proxy/processors/push-action/getDiff.js index 0a91161f..09d69c18 100644 --- a/src/proxy/processors/push-action/getDiff.js +++ b/src/proxy/processors/push-action/getDiff.js @@ -2,6 +2,7 @@ const Step = require('../../actions').Step; const simpleGit = require('simple-git') + const exec = async (req, action) => { const step = new Step('diff'); diff --git a/src/proxy/processors/push-action/index.js b/src/proxy/processors/push-action/index.js index 72a97b33..927fd06f 100644 --- a/src/proxy/processors/push-action/index.js +++ b/src/proxy/processors/push-action/index.js @@ -11,3 +11,4 @@ exports.checkCommitMessages = require('./checkCommitMessages').exec; exports.checkAuthorEmails = require('./checkAuthorEmails').exec; exports.checkUserPushPermission = require('./checkUserPushPermission').exec; exports.clearBareClone = require('./clearBareClone').exec; +exports.checkSensitiveData = require('./checkSensitiveData').exec; \ No newline at end of file diff --git a/test/CheckSensitive.test.js b/test/CheckSensitive.test.js new file mode 100644 index 00000000..f51f79da --- /dev/null +++ b/test/CheckSensitive.test.js @@ -0,0 +1,101 @@ +// const path = require('path'); +const { exec } = require('../src/proxy/processors/push-action/checkSensitiveData.js'); // Adjust path as necessary +const sinon = require('sinon'); +const {Action}=require('../src/proxy/actions/Action.js') +const {Step}=require('../src/proxy/actions/Step.js') + + +describe('Sensitive Data Detection', () => { + let logStub; + + beforeEach(() => { + logStub = sinon.stub(console, 'log'); // Stub console.log before each test + }); + + afterEach(() => { + logStub.restore(); // Restore console.log after each test + }); + + const createDiffContent = (filePaths) => { + // Format file paths in diff format + return filePaths.map(filePath => `diff --git a/${filePath} b/${filePath}`).join('\n'); + }; +// make sure the file types are added in proxyfiletypes in proxy.config.json + it('should detect sensitive data in CSV file and block execution', async () => { + const action = new Action('action_id', 'push', 'create', Date.now(), 'owner/repo'); + const step = new Step('diff'); + + // Create diff content simulating sensitive data in CSV + step.setContent(createDiffContent(['test/test_data/sensitive_data.csv'])); + action.addStep(step) + + await exec(null, action); + sinon.assert.calledWith(logStub, sinon.match(/Your push has been blocked due to sensitive data detection/)); + }); + + it('should detect sensitive data in XLSX file and block execution', async () => { + const action = new Action('action_id', 'push', 'create', Date.now(), 'owner/repo'); + const step = new Step('diff'); + step.setContent(createDiffContent(['test/test_data/sensitive_data2.xlsx'])); + action.addStep(step); + + await exec(null, action); + sinon.assert.calledWith(logStub, sinon.match(/Your push has been blocked due to sensitive data detection/)); + }); + + it('should detect sensitive data in a log file and block execution', async () => { + + const action = new Action('action_id', 'push', 'create', Date.now(), 'owner/repo'); + const step = new Step('diff'); + step.setContent(createDiffContent(['test/test_data/sensitive_data3.log'])); + action.addStep(step); + await exec(null, action); + sinon.assert.calledWith(logStub, sinon.match(/Your push has been blocked due to sensitive data detection/)); + }); + + it('should detect sensitive data in a JSON file and block execution', async () => { + + + const action = new Action('action_id', 'push', 'create', Date.now(), 'owner/repo'); + const step = new Step('diff'); + step.setContent(createDiffContent(['test/test_data/sensitive_data4.json'])); + action.addStep(step); + await exec(null, action); + sinon.assert.calledWith(logStub, sinon.match(/Your push has been blocked due to sensitive data detection/)); + }); + + it('should allow execution if no sensitive data is found', async () => { + + + const action = new Action('action_id', 'push', 'create', Date.now(), 'owner/repo'); + const step = new Step('diff'); + step.setContent(createDiffContent(['test_data/no_sensitive_data.txt'])); + action.addStep(step); + await exec(null, action); + sinon.assert.neverCalledWith(logStub, sinon.match(/Your push has been blocked due to sensitive data detection/)); + }); + + it('should allow execution for an empty file', async () => { + + + const action = new Action('action_id', 'push', 'create', Date.now(), 'owner/repo'); + const step = new Step('diff'); + step.setContent(createDiffContent(['test_data/empty_file.txt'])); + action.addStep(step); + await exec(null, action); + sinon.assert.neverCalledWith(logStub, sinon.match(/Your push has been blocked due to sensitive data detection/)); + }); + + it('should handle file-not-found scenario gracefully', async () => { + + const action = new Action('action_id', 'push', 'create', Date.now(), 'owner/repo'); + const step = new Step('diff'); + step.setContent(createDiffContent(['test_data/non_existent_file.txt'])); + action.addStep(step); + try { + await exec(null, action); + } catch (error) { + sinon.assert.match(error.message, /ENOENT: no such file or directory/); + } + }); +}); diff --git a/test/CreateExcel.js b/test/CreateExcel.js new file mode 100644 index 00000000..ea9f9af0 --- /dev/null +++ b/test/CreateExcel.js @@ -0,0 +1,19 @@ +const XLSX = require('xlsx'); +const fs = require('fs'); +const path = require('path'); +// Example data with sensitive information +const data = [ + { Name: "John Doe", SSN: "123-45-6789", Email: "john@example.com" }, + { Name: "Jane Smith", SSN: "987-65-4321", Email: "jane@example.com" } +]; +const worksheet = XLSX.utils.json_to_sheet(data); +const workbook = XLSX.utils.book_new(); +XLSX.utils.book_append_sheet(workbook, worksheet, "SensitiveData"); +// Create the path to the test_data directory +const testDataPath = path.join(__dirname, 'test_data'); // Ensure this points to the correct directory +// Create the test_data directory if it doesn't exist +if (!fs.existsSync(testDataPath)){ + fs.mkdirSync(testDataPath, { recursive: true }); // Using recursive to ensure all directories are created +} +// Write the Excel file to the test_data directory +XLSX.writeFile(workbook, path.join(testDataPath, 'sensitive_data2.xlsx')); \ No newline at end of file diff --git a/test/chain.test.js b/test/chain.test.js index 33d5750a..beeea18a 100644 --- a/test/chain.test.js +++ b/test/chain.test.js @@ -2,6 +2,7 @@ const chai = require('chai'); const sinon = require('sinon'); const { PluginLoader } = require('../src/plugin'); + chai.should(); const expect = chai.expect; @@ -25,6 +26,7 @@ const mockPushProcessors = { pullRemote: sinon.stub(), writePack: sinon.stub(), getDiff: sinon.stub(), + checkSensitiveData : sinon.stub(), clearBareClone: sinon.stub(), scanDiff: sinon.stub(), blockForAuth: sinon.stub(), @@ -39,6 +41,7 @@ mockPushProcessors.checkIfWaitingAuth.displayName = 'checkIfWaitingAuth'; mockPushProcessors.pullRemote.displayName = 'pullRemote'; mockPushProcessors.writePack.displayName = 'writePack'; mockPushProcessors.getDiff.displayName = 'getDiff'; +mockPushProcessors.checkSensitiveData.displayName = 'checkSensitiveData'; mockPushProcessors.clearBareClone.displayName = 'clearBareClone'; mockPushProcessors.scanDiff.displayName = 'scanDiff'; mockPushProcessors.blockForAuth.displayName = 'blockForAuth'; @@ -106,6 +109,7 @@ describe('proxy chain', function () { mockPushProcessors.checkCommitMessages.resolves(continuingAction); mockPushProcessors.checkAuthorEmails.resolves(continuingAction); mockPushProcessors.checkUserPushPermission.resolves(continuingAction); + mockPushProcessors.checkSensitiveData.resolves(continuingAction); // this stops the chain from further execution mockPushProcessors.checkIfWaitingAuth.resolves({ type: 'push', continue: () => false, allowPush: false }); @@ -120,6 +124,7 @@ describe('proxy chain', function () { expect(mockPushProcessors.checkIfWaitingAuth.called).to.be.true; expect(mockPushProcessors.pullRemote.called).to.be.false; expect(mockPushProcessors.audit.called).to.be.true; + expect(mockPushProcessors.checkSensitiveData.called).to.be.false; expect(result.type).to.equal('push'); expect(result.allowPush).to.be.false; @@ -135,6 +140,7 @@ describe('proxy chain', function () { mockPushProcessors.checkCommitMessages.resolves(continuingAction); mockPushProcessors.checkAuthorEmails.resolves(continuingAction); mockPushProcessors.checkUserPushPermission.resolves(continuingAction); + mockPushProcessors.checkSensitiveData.resolves(continuingAction); // this stops the chain from further execution mockPushProcessors.checkIfWaitingAuth.resolves({ type: 'push', continue: () => true, allowPush: true }); const result = await chain.executeChain(req); @@ -148,6 +154,7 @@ describe('proxy chain', function () { expect(mockPushProcessors.checkIfWaitingAuth.called).to.be.true; expect(mockPushProcessors.pullRemote.called).to.be.false; expect(mockPushProcessors.audit.called).to.be.true; + expect(mockPushProcessors.checkSensitiveData.called).to.be.false; expect(result.type).to.equal('push'); expect(result.allowPush).to.be.true; @@ -170,6 +177,7 @@ describe('proxy chain', function () { mockPushProcessors.clearBareClone.resolves(continuingAction); mockPushProcessors.scanDiff.resolves(continuingAction); mockPushProcessors.blockForAuth.resolves(continuingAction); + mockPushProcessors.checkSensitiveData.resolves(continuingAction); const result = await chain.executeChain(req); @@ -187,6 +195,7 @@ describe('proxy chain', function () { expect(mockPushProcessors.scanDiff.called).to.be.true; expect(mockPushProcessors.blockForAuth.called).to.be.true; expect(mockPushProcessors.audit.called).to.be.true; + expect(mockPushProcessors.checkSensitiveData.called).to.be.true; expect(result.type).to.equal('push'); expect(result.allowPush).to.be.false; diff --git a/test/test_data/sensitive_data.csv b/test/test_data/sensitive_data.csv new file mode 100644 index 00000000..d0381fa0 --- /dev/null +++ b/test/test_data/sensitive_data.csv @@ -0,0 +1,3 @@ +Name,SSN,Email +John Doe,123-45-6789,john@example.com +Jane Smith,987-65-4321,jane@example.com diff --git a/test/test_data/sensitive_data2.xlsx b/test/test_data/sensitive_data2.xlsx new file mode 100644 index 00000000..3c9634cc Binary files /dev/null and b/test/test_data/sensitive_data2.xlsx differ diff --git a/test/test_data/sensitive_data4.json b/test/test_data/sensitive_data4.json new file mode 100644 index 00000000..50217f69 --- /dev/null +++ b/test/test_data/sensitive_data4.json @@ -0,0 +1,4 @@ +{ + "username": "johndoe", + "ssn": "123-45-6789" +}