├── .DS_Store
├── .babelrc
├── .gitignore
├── LICENSE
├── Logo.svg
├── README.md
├── assets
└── icons
│ ├── mac
│ └── icon.icns
│ ├── png
│ └── icon.png
│ └── win
│ └── icon.ico
├── main.js
├── package-lock.json
├── package.json
├── postcss.config.js
├── src
├── assets
│ └── css
│ │ ├── App.css
│ │ └── _example
│ │ └── example.css
├── components
│ ├── App.js
│ ├── material
│ │ ├── Accordion.js
│ │ ├── AccordionMult.js
│ │ ├── Card.js
│ │ ├── Dialog.js
│ │ ├── List.js
│ │ ├── OpenSelect.js
│ │ ├── SideNav.js
│ │ └── spinner
│ │ │ ├── Spinner.js
│ │ │ ├── index.js
│ │ │ └── spinner.css
│ └── pages
│ │ ├── About.js
│ │ ├── History.js
│ │ ├── Home.js
│ │ └── Settings.js
└── index.js
├── webpack.build.config.js
├── webpack.dev.config.js
└── yarn.lock
/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oslabs-beta/Breach/9392c2d9e2328a622fca4d176bb85f0c490e97a6/.DS_Store
--------------------------------------------------------------------------------
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["@babel/preset-env", ["@babel/preset-react"]]
3 | }
4 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | lerna-debug.log*
8 |
9 | # Diagnostic reports (https://nodejs.org/api/report.html)
10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
11 |
12 | # Runtime data
13 | pids
14 | *.pid
15 | *.seed
16 | *.pid.lock
17 |
18 | # Directory for instrumented libs generated by jscoverage/JSCover
19 | lib-cov
20 |
21 | # Coverage directory used by tools like istanbul
22 | coverage
23 | *.lcov
24 |
25 | # nyc test coverage
26 | .nyc_output
27 |
28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
29 | .grunt
30 |
31 | # Bower dependency directory (https://bower.io/)
32 | bower_components
33 |
34 | # node-waf configuration
35 | .lock-wscript
36 |
37 | # Compiled binary addons (https://nodejs.org/api/addons.html)
38 | build/Release
39 |
40 | # Dependency directories
41 | node_modules/
42 | jspm_packages/
43 |
44 | # TypeScript v1 declaration files
45 | typings/
46 |
47 | # TypeScript cache
48 | *.tsbuildinfo
49 |
50 | # Optional npm cache directory
51 | .npm
52 |
53 | # Optional eslint cache
54 | .eslintcache
55 |
56 | # Microbundle cache
57 | .rpt2_cache/
58 | .rts2_cache_cjs/
59 | .rts2_cache_es/
60 | .rts2_cache_umd/
61 |
62 | # Optional REPL history
63 | .node_repl_history
64 |
65 | # Output of 'npm pack'
66 | *.tgz
67 |
68 | # Yarn Integrity file
69 | .yarn-integrity
70 |
71 | # dotenv environment variables file
72 | .env
73 | .env.test
74 |
75 | # parcel-bundler cache (https://parceljs.org/)
76 | .cache
77 |
78 | # Next.js build output
79 | .next
80 |
81 | # Nuxt.js build / generate output
82 | .nuxt
83 | dist
84 |
85 | # Gatsby files
86 | .cache/
87 | # Comment in the public line in if your project uses Gatsby and *not* Next.js
88 | # https://nextjs.org/blog/next-9-1#public-directory-support
89 | # public
90 |
91 | # vuepress build output
92 | .vuepress/dist
93 |
94 | # Serverless directories
95 | .serverless/
96 |
97 | # FuseBox cache
98 | .fusebox/
99 |
100 | # DynamoDB Local files
101 | .dynamodb/
102 |
103 | # TernJS port file
104 | .tern-port
105 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 Breach
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Logo.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
185 |
186 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |      
4 |
5 | Visit the Breach website [here](https://breachapplication.netlify.app/)
6 |
7 | ## Table of Contents
8 | - About Breach
9 | - Getting Started
10 | - Demo
11 | - Scan URL
12 | - Results
13 | - History
14 | - Settings
15 | - Looking Ahead
16 | - Contributors
17 | - License
18 |
19 | ## About
20 |
21 | Breach is a Cybersecurity desktop application intended to keep front-ends safe without doing damage.
22 |
23 | • One click for URL security test.
24 |
25 | • Saves history of previous tests
26 |
27 | • Customizable settings on color and font sizes for better user experience.
28 |
29 | ## Getting Started
30 |
31 | ### Download [Breach](https://breachapplication.netlify.app/) and [BreachServer](https://github.com/tommyedmunds/breachServer)
32 |
33 | The application can be downloaded for [windows](https://drive.google.com/file/d/145yAP5TmEQ5Ti9ohv3nl3cAHoqawgV2Q/view?usp=sharing) or [mac](https://drive.google.com/file/d/1kRA23lBGhJ-vXaD8gVmvyWeAOaZuZmFR/view?usp=sharing) (Linux option for packaging from codebase is not confirmed.)
34 |
35 | - For Mac OSX, right click on the downloaded file and click open.
36 | - For Windows users, simply open the .exe file to begin.
37 |
38 | The server can be forked and cloned to your local machine. Once it has been cloned, navigate to the correct folder in your terminal and
39 |
40 | - Type the following:
41 |
42 | ```
43 |
44 | npm install
45 |
46 | npm start
47 |
48 | ```
49 | Once you have these two items up and running you can get started or use our demo to learn more. We suggest changing the color of the application to your preference first.
50 |
51 | ## Demo
52 |
53 | Once you have opened [Breach](https://breachapplication.netlify.app/) and [BreachServer](https://github.com/oslabs-beta/BreachServer)...
54 |
55 | ### Scan URL
56 | Upon entering a URL the app sends out a request to the server, running tests for instances of innerHTML in the code, cookies and some XSS tests.
57 | #### Writing the URL for testing XSS
58 | - The URL must be formatted for a search query (have "q=") in order for the XSS tests to be run.
59 |
60 | 
61 |
62 | #
63 | ### Results
64 | When the app is finished loading, it will print your results.
65 | - Click on the defend logo to learn more about how to defend your app.
66 |
67 | 
68 | #
69 | ### History
70 | - You may view the history of results, change how many are shown, delete history items, or check out how to defend from attacks in the History tab of the application.
71 |
72 | 
73 | #
74 | ### Settings
75 | - From the settings page you can change the color of the application to one of five different settings, as well as change the font size on the pages.
76 |
77 | 
78 |
79 | ## Looking Ahead
80 |
81 | Breach is currently in its first release. The features we would like to implement in the future are:
82 | - Testing for SQL injection and DOS susceptibility.
83 | - Ability to export data for future use.
84 | - Display of active ports running on the server.
85 | - Integrate server into app.
86 | - Linux installer.
87 |
88 | ## Contributors
89 |
90 | [Jason Yoon](https://www.linkedin.com/in/jason-t-yoon/) [@Jason Yoon](https://github.com/jasony779)
91 |
92 | [Tommy Edmunds](https://www.linkedin.com/in/tommy-edmunds-a91aa41a9/) [@Tommy Edmunds](https://github.com/tommyedmunds)
93 |
94 | [Michael Geismar](https://www.linkedin.com/in/michael-geismar) [@michaelgeismar](https://github.com/MichaelGeismar)
95 |
96 | ## License
97 |
98 | MIT -- see [LICENSE.md](https://github.com/oslabs-beta/Breach/blob/main/LICENSE) file for more details.
99 |
100 | #
101 | This product is accelerated by [OS Labs](https://opensourcelabs.io/).
102 |
--------------------------------------------------------------------------------
/assets/icons/mac/icon.icns:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oslabs-beta/Breach/9392c2d9e2328a622fca4d176bb85f0c490e97a6/assets/icons/mac/icon.icns
--------------------------------------------------------------------------------
/assets/icons/png/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oslabs-beta/Breach/9392c2d9e2328a622fca4d176bb85f0c490e97a6/assets/icons/png/icon.png
--------------------------------------------------------------------------------
/assets/icons/win/icon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oslabs-beta/Breach/9392c2d9e2328a622fca4d176bb85f0c490e97a6/assets/icons/win/icon.ico
--------------------------------------------------------------------------------
/main.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | const { app, BrowserWindow } = require('electron');
3 | const path = require('path');
4 | const url = require('url');
5 | const { ipcMain } = require('electron');
6 | const Store = require('electron-store');
7 | const store = new Store();
8 |
9 | //local storage working
10 |
11 | // Keep a global reference of the window object, if you don't, the window will
12 | // be closed automatically when the JavaScript object is garbage collected.
13 |
14 | let mainWindow;
15 |
16 | // Keep a reference for dev mode
17 | let dev = false;
18 |
19 | if (process.env.NODE_ENV !== undefined && process.env.NODE_ENV === 'development') {
20 | dev = true;
21 | }
22 |
23 | // Temporary fix broken high-dpi scale factor on Windows (125% scaling)
24 | if (process.platform === 'win32') {
25 | app.commandLine.appendSwitch('high-dpi-support', 'true');
26 | app.commandLine.appendSwitch('force-device-scale-factor', '1');
27 | }
28 |
29 | function createWindow() {
30 | // Create the browser window.
31 | mainWindow = new BrowserWindow({
32 | width: 1200,
33 | height: 1000,
34 | show: false,
35 | webPreferences: {
36 | nodeIntegration: true,
37 | contextIsolation: false,
38 | },
39 | });
40 |
41 | // and load the index.html of the app.
42 | let indexPath;
43 |
44 | if (dev && process.argv.indexOf('--noDevServer') === -1) {
45 | indexPath = url.format({
46 | protocol: 'http:',
47 | host: 'localhost:8080',
48 | pathname: 'index.html',
49 | slashes: true,
50 | });
51 | } else {
52 | indexPath = url.format({
53 | protocol: 'file:',
54 | //change back to "dist" and "index.html" after webpack rebuild or for production build
55 | pathname: path.join(__dirname, 'dist', 'index.html'),
56 | slashes: true,
57 | });
58 | }
59 |
60 | mainWindow.loadURL(indexPath);
61 |
62 | ipcMain.on('asynchronous-message', (event, arg) => {
63 | if (typeof arg.value === 'number' && arg.value.toString().length === 1) {
64 | arg.name = 'historyLength';
65 | } else {
66 | const regex = /\d/g;
67 |
68 | if (regex.test(arg.value)) {
69 | arg.name = 'fontSize';
70 | } else {
71 | arg.name = 'theme';
72 | }
73 | }
74 | store.set(arg.name, arg.value);
75 | event.reply('asynchronous-reply', 'pong');
76 | });
77 |
78 | if (!store.get('fontSize') || typeof store.get('fontSize') !== 'string')
79 | store.set('fontSize', '16px');
80 | if (!store.get('history')) store.set('history', []);
81 | if (!store.get('historyLength')) store.set('historyLength', 3);
82 | const dark = {
83 | overrides: {
84 | MuiCssBaseline: {
85 | '@global': {
86 | // MUI typography elements use REMs, so you can scale the global
87 | // font size by setting the font-size on the element.
88 | html: {
89 | fontSize: parseInt(store.get('fontSize').slice(0, 2)),
90 | },
91 | },
92 | },
93 | },
94 | palette: {
95 | type: 'dark',
96 | },
97 | };
98 | const light = {
99 | overrides: {
100 | MuiCssBaseline: {
101 | '@global': {
102 | html: {
103 | fontSize: parseInt(store.get('fontSize').slice(0, 2)),
104 | },
105 | },
106 | },
107 | text: {
108 | primary: 'rgba(0, 0, 0, 1)',
109 | secondary: 'rgba(255, 255, 255, 1)',
110 | disabled: 'rgba(255, 255, 255, 1)',
111 | hint: 'rgba(0, 0, 0, 0.38)',
112 | },
113 | },
114 | palette: {
115 | type: 'light',
116 | },
117 | };
118 | const blue = {
119 | overrides: {
120 | MuiCssBaseline: {
121 | '@global': {
122 | html: {
123 | fontSize: parseInt(store.get('fontSize').slice(0, 2)),
124 | },
125 | },
126 | },
127 | },
128 | palette: {
129 | common: { black: 'rgba(0, 0, 0, 1)', white: 'rgba(255, 255, 255, 1)' },
130 | background: {
131 | paper: 'rgba(25, 161, 200, 1)',
132 | default: 'rgba(42, 132, 157, 1)',
133 | },
134 | primary: {
135 | light: 'rgba(147, 159, 255, 1)',
136 | main: 'rgba(52, 72, 205, 1)',
137 | dark: 'rgba(1, 22, 155, 1)',
138 | contrastText: 'rgba(255, 255, 255, 1)',
139 | },
140 | secondary: {
141 | light: 'rgba(129, 182, 244, 1)',
142 | main: 'rgba(122, 178, 242, 1)',
143 | dark: 'rgba(0, 50, 110, 1)',
144 | contrastText: 'rgba(255, 255, 255, 1)',
145 | },
146 | error: {
147 | light: 'rgba(135, 188, 251, 1)',
148 | main: 'rgba(16, 64, 120, 1)',
149 | dark: 'rgba(22, 45, 73, 1)',
150 | contrastText: '#fff',
151 | },
152 | text: {
153 | primary: 'rgb(255, 255, 255, .9)',
154 | secondary: 'rgb(255, 255, 255, .7)',
155 | disabled: 'rgba(255, 255, 255, 1)',
156 | hint: 'rgba(0, 0, 0, 0.38)',
157 | },
158 | },
159 | };
160 | const purple = {
161 | overrides: {
162 | MuiCssBaseline: {
163 | '@global': {
164 | html: {
165 | fontSize: parseInt(store.get('fontSize').slice(0, 2)),
166 | },
167 | },
168 | },
169 | },
170 | palette: {
171 | common: { black: 'rgba(0, 0, 0, 1)', white: 'rgba(255, 255, 255, 1)' },
172 | background: {
173 | paper: 'rgb(172, 130, 234, 1)',
174 | default: 'rgba(149, 115, 215, 1)',
175 | },
176 | primary: {
177 | light: 'rgba(156, 0, 220, 1)',
178 | main: 'rgba(112, 0, 193, 1)',
179 | dark: 'rgba(76, 1, 125, 1)',
180 | contrastText: 'rgba(255, 255, 255, 1)',
181 | },
182 | secondary: {
183 | light: 'rgba(181, 94, 222, 1)',
184 | main: 'rgba(72, 0, 150, 1)',
185 | dark: 'rgba(78, 0, 110, 1)',
186 | contrastText: 'rgba(255, 255, 255, 1)',
187 | },
188 | error: {
189 | light: 'rgba(135, 188, 251, 1)',
190 | main: 'rgba(174, 98, 244, 1)',
191 | dark: 'rgba(22, 45, 73, 1)',
192 | contrastText: '#fff',
193 | },
194 | text: {
195 | primary: 'rgb(255, 255, 255, .9)',
196 | secondary: 'rgb(255, 255, 255, .7)',
197 | disabled: 'rgba(255, 255, 255, 0.38)',
198 | hint: 'rgba(255, 255, 255, 0.38)',
199 | },
200 | },
201 | };
202 | const green = {
203 | overrides: {
204 | MuiCssBaseline: {
205 | '@global': {
206 | html: {
207 | fontSize: parseInt(store.get('fontSize').slice(0, 2)),
208 | },
209 | },
210 | },
211 | },
212 | palette: {
213 | common: { black: 'rgba(0, 0, 0, 1)', white: 'rgba(255, 255, 255, 1)' },
214 | background: {
215 | paper: 'rgba(55, 158, 132, 1)',
216 | default: 'rgba(35, 138, 112, 1)',
217 | },
218 | primary: {
219 | light: 'rgba(151, 254, 32, 1)',
220 | main: 'rgba(21, 87, 63, 1)',
221 | dark: 'rgba(44, 81, 4, 1)',
222 | contrastText: 'rgba(255, 255, 255, 1)',
223 | },
224 | secondary: {
225 | light: 'rgba(85, 255, 196, 1)',
226 | main: 'rgba(0, 97, 63, 1)',
227 | dark: 'rgba(0, 95, 63, 1)',
228 | contrastText: 'rgba(255, 255, 255, 1)',
229 | },
230 | error: {
231 | light: 'rgba(0, 255, 167, 1)',
232 | main: 'rgba(0, 203, 133, 1)',
233 | dark: 'rgba(0, 112, 73, 1)',
234 | contrastText: '#fff',
235 | },
236 | text: {
237 | primary: 'rgb(255, 255, 255, .9)',
238 | secondary: 'rgb(255, 255, 255, .7)',
239 | disabled: 'rgba(255, 255, 255, 0.38)',
240 | hint: 'rgba(255, 255, 255, 0.38)',
241 | },
242 | },
243 | };
244 |
245 | if (!store.get('fontSize')) store.set('fontSize', '16px');
246 |
247 | ipcMain.on('load-data', function (event, arg) {
248 |
249 | if (arg && typeof arg.options[0] === 'number') {
250 | mainWindow.webContents.send('data-reply', store.store);
251 | } else {
252 | if (store.get('fontSize') === null || store.get('fontSize') === undefined) {
253 | dark.overrides.MuiCssBaseline['@global'].html.fontSize = 16;
254 | light.overrides.MuiCssBaseline['@global'].html.fontSize = 16;
255 | }
256 | const dark = {
257 | overrides: {
258 | MuiCssBaseline: {
259 | '@global': {
260 | html: {
261 | fontSize: parseInt(store.get('fontSize').slice(0, 2)),
262 | },
263 | },
264 | },
265 | },
266 | palette: {
267 | type: 'dark',
268 | },
269 | };
270 | const light = {
271 | overrides: {
272 | MuiCssBaseline: {
273 | '@global': {
274 | html: {
275 | fontSize: parseInt(store.get('fontSize').slice(0, 2)),
276 | },
277 | },
278 | },
279 | },
280 | palette: {
281 | type: 'light',
282 | },
283 | };
284 | const blue = {
285 | overrides: {
286 | MuiCssBaseline: {
287 | '@global': {
288 | html: {
289 | fontSize: parseInt(store.get('fontSize').slice(0, 2)),
290 | },
291 | },
292 | },
293 | },
294 | palette: {
295 | common: { black: 'rgba(0, 0, 0, 1)', white: 'rgba(255, 255, 255, 1)' },
296 | background: {
297 | paper: 'rgba(25, 161, 200, 1)',
298 | default: 'rgba(42, 132, 157, 1)',
299 | },
300 | primary: {
301 | light: 'rgba(147, 159, 255, 1)',
302 | main: 'rgba(52, 72, 205, 1)',
303 | dark: 'rgba(1, 22, 155, 1)',
304 | contrastText: 'rgba(255, 255, 255, 1)',
305 | },
306 | secondary: {
307 | light: 'rgba(129, 182, 244, 1)',
308 | main: 'rgba(122, 178, 242, 1)',
309 | dark: 'rgba(0, 50, 110, 1)',
310 | contrastText: 'rgba(255, 255, 255, 1)',
311 | },
312 | error: {
313 | light: 'rgba(135, 188, 251, 1)',
314 | main: 'rgba(16, 64, 120, 1)',
315 | dark: 'rgba(22, 45, 73, 1)',
316 | contrastText: '#fff',
317 | },
318 | text: {
319 | primary: 'rgb(255, 255, 255, .9)',
320 | secondary: 'rgb(255, 255, 255, .7)',
321 | disabled: 'rgba(255, 255, 255, 1)',
322 | hint: 'rgba(0, 0, 0, 0.38)',
323 | },
324 | },
325 | };
326 | const purple = {
327 | overrides: {
328 | MuiCssBaseline: {
329 | '@global': {
330 | html: {
331 | fontSize: parseInt(store.get('fontSize').slice(0, 2)),
332 | },
333 | },
334 | },
335 | },
336 | palette: {
337 | common: { black: 'rgba(0, 0, 0, 1)', white: 'rgba(255, 255, 255, 1)' },
338 | background: {
339 | paper: 'rgb(172, 130, 234, 1)',
340 | default: 'rgba(149, 115, 215, 1)',
341 | },
342 | primary: {
343 | light: 'rgba(156, 0, 220, 1)',
344 | main: 'rgba(112, 0, 193, 1)',
345 | dark: 'rgba(76, 1, 125, 1)',
346 | contrastText: 'rgba(255, 255, 255, 1)',
347 | },
348 | secondary: {
349 | light: 'rgba(181, 94, 222, 1)',
350 | main: 'rgba(72, 0, 150, 1)',
351 | dark: 'rgba(78, 0, 110, 1)',
352 | contrastText: 'rgba(255, 255, 255, 1)',
353 | },
354 | error: {
355 | light: 'rgba(135, 188, 251, 1)',
356 | main: 'rgba(174, 98, 244, 1)',
357 | dark: 'rgba(22, 45, 73, 1)',
358 | contrastText: '#fff',
359 | },
360 | text: {
361 | primary: 'rgb(255, 255, 255, .9)',
362 | secondary: 'rgb(255, 255, 255, .7)',
363 | disabled: 'rgba(255, 255, 255, 0.38)',
364 | hint: 'rgba(255, 255, 255, 0.38)',
365 | },
366 | },
367 | };
368 | const green = {
369 | overrides: {
370 | MuiCssBaseline: {
371 | '@global': {
372 | html: {
373 | fontSize: parseInt(store.get('fontSize').slice(0, 2)),
374 | },
375 | },
376 | },
377 | },
378 | palette: {
379 | common: { black: 'rgba(0, 0, 0, 1)', white: 'rgba(255, 255, 255, 1)' },
380 | background: {
381 | paper: 'rgba(55, 158, 132, 1)',
382 | default: 'rgba(35, 138, 112, 1)',
383 | },
384 | primary: {
385 | light: 'rgba(151, 254, 32, 1)',
386 | main: 'rgba(21, 87, 63, 1)',
387 | dark: 'rgba(44, 81, 4, 1)',
388 | contrastText: 'rgba(255, 255, 255, 1)',
389 | },
390 | secondary: {
391 | light: 'rgba(85, 255, 196, 1)',
392 | main: 'rgba(0, 97, 63, 1)',
393 | dark: 'rgba(0, 95, 63, 1)',
394 | contrastText: 'rgba(255, 255, 255, 1)',
395 | },
396 | error: {
397 | light: 'rgba(0, 255, 167, 1)',
398 | main: 'rgba(0, 203, 133, 1)',
399 | dark: 'rgba(0, 112, 73, 1)',
400 | contrastText: '#fff',
401 | },
402 | text: {
403 | primary: 'rgb(255, 255, 255, .9)',
404 | secondary: 'rgb(255, 255, 255, .7)',
405 | disabled: 'rgba(255, 255, 255, 0.38)',
406 | hint: 'rgba(255, 255, 255, 0.38)',
407 | },
408 | },
409 | };
410 |
411 | store.set('purple', purple);
412 |
413 | store.set('green', green);
414 |
415 | store.set('dark', dark);
416 |
417 | store.set('light', light);
418 |
419 | store.set('blue', blue);
420 |
421 | mainWindow.webContents.send('data-reply', store.store);
422 | }
423 | });
424 |
425 | // Don't show until we are ready and loaded
426 | mainWindow.once('ready-to-show', () => {
427 | mainWindow.show();
428 |
429 | // Open the DevTools automatically if developing
430 | if (dev) {
431 | const {
432 | default: installExtension,
433 | REACT_DEVELOPER_TOOLS,
434 | } = require('electron-devtools-installer');
435 |
436 | installExtension(REACT_DEVELOPER_TOOLS).catch((err) =>
437 | console.error('Error loading React DevTools: ', err)
438 | );
439 | mainWindow.webContents.openDevTools();
440 | }
441 | });
442 |
443 | // Emitted when the window is closed.
444 | mainWindow.on('closed', function () {
445 | // Dereference the window object, usually you would store windows
446 | // in an array if your app supports multi windows, this is the time
447 | // when you should delete the corresponding element.
448 | mainWindow = null;
449 | });
450 | }
451 |
452 | // This method will be called when Electron has finished
453 | // initialization and is ready to create browser windows.
454 | // Some APIs can only be used after this event occurs.
455 | app.on('ready', createWindow);
456 |
457 | // Quit when all windows are closed.
458 | app.on('window-all-closed', () => {
459 | // On macOS it is common for applications and their menu bar
460 | // to stay active until the user quits explicitly with Cmd + Q
461 | if (process.platform !== 'darwin') {
462 | app.quit();
463 | }
464 | });
465 |
466 | app.on('activate', () => {
467 | // On macOS it's common to re-create a window in the app when the
468 | // dock icon is clicked and there are no other windows open.
469 | if (mainWindow === null) {
470 | createWindow();
471 | }
472 | });
473 |
474 | ipcMain.on('url', function (event, arg) {
475 | // let test = {
476 | // url: arg,
477 | // cookieTest: '',
478 | // jqueryTest: false,
479 | // jsXSS: false,
480 | // };
481 |
482 | let history;
483 | store.get('history') ? (history = store.get('history')) : (history = []);
484 | history.unshift(arg);
485 | history.length >= 25 ? history.pop() : history;
486 | store.set('history', history);
487 | mainWindow.webContents.send('testOutput', arg);
488 | });
489 |
490 | ipcMain.on('clearHistory', function (event, arg) {
491 | store.set('history', []);
492 | mainWindow.webContents.send('historyCleared', store.get('history'));
493 | });
494 |
495 | ipcMain.on('clearItem', function (event, arg) {
496 | let newHistory = store.get('history');
497 | newHistory.splice(arg, 1);
498 | store.set('history', newHistory);
499 | mainWindow.webContents.send('itemCleared', store.get('history'));
500 | });
501 |
502 | ipcMain.on('getHistoryLength', function (event, arg) {
503 | if (!store.get('historyLength')) store.set('historyLength', 3);
504 | mainWindow.webContents.send('length', store.get('historyLength'));
505 | });
506 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Breach",
3 | "productName": "Breach",
4 | "version": "1.0.0",
5 | "description": "A cyber-sec tool to be used responsibly in identifying XSS vulnerabilities",
6 | "license": "MIT",
7 | "private": false,
8 | "repository": {
9 | "type": "git",
10 | "url": "https://github.com/oslabs-beta/Breach"
11 | },
12 | "author": {
13 | "name": "Jason Yoon, Michael Geismar, Tommy Edmunds",
14 | "email": "jasony779@gmail.com",
15 | "url": "https://github.com/oslabs-beta/Breach"
16 | },
17 | "keywords": [
18 | "app",
19 | "boilerplate",
20 | "electron",
21 | "open",
22 | "open-source",
23 | "postcss",
24 | "react",
25 | "reactjs",
26 | "source",
27 | "webpack"
28 | ],
29 | "engines": {
30 | "node": ">=9.0.0",
31 | "npm": ">=5.0.0",
32 | "yarn": ">=1.0.0"
33 | },
34 | "browserslist": [
35 | "last 4 versions"
36 | ],
37 | "main": "main.js",
38 | "scripts": {
39 | "prod": "cross-env NODE_ENV=production webpack --mode production --config webpack.build.config.js && electron --noDevServer .",
40 | "start": "cross-env NODE_ENV=development webpack serve --hot --host 0.0.0.0 --config=./webpack.dev.config.js --mode development",
41 | "build": "cross-env NODE_ENV=production webpack --config webpack.build.config.js --mode production",
42 | "dev": "concurrently \"cross-env NODE_ENV=development --config=./webpack.dev.config.js\" \"NODE_ENV=development webpack serve --open\"",
43 | "package": "npm run build",
44 | "postpackage": "electron-packager ./ --out=./builds",
45 | "package-mac": "electron-packager . --overwrite --platform=darwin --arch=x64 --icon=assets/icons/mac/icon.icns --prune=true --out=release-builds",
46 | "package-win": "electron-packager . --overwrite --asar --platform=win32 --arch=ia32 --icon=assets/icons/win/icon --prune=true --out=release-builds --version-string.CompanyName=CE --version-string.FileDescription=CE --version-string.ProductName=\"Breach\"",
47 | "package-linux": "electron-packager . electron-tutorial-app --overwrite --asar=true --platform=linux --arch=x64 --icon=Icons/png/icon.png --prune=true --out=release-builds"
48 | },
49 | "dependencies": {
50 | "@fortawesome/fontawesome-svg-core": "^1.2.35",
51 | "@fortawesome/free-brands-svg-icons": "^5.15.3",
52 | "@fortawesome/free-regular-svg-icons": "^5.15.3",
53 | "@fortawesome/free-solid-svg-icons": "^5.15.3",
54 | "@fortawesome/react-fontawesome": "^0.1.14",
55 | "@material-ui/core": "^4.12.1",
56 | "@material-ui/icons": "^4.11.2",
57 | "@types/react-transition-group": "^4.4.2",
58 | "axios": "^0.21.1",
59 | "concurrently": "^6.2.0",
60 | "electron-fetch": "^1.7.3",
61 | "electron-storage": "^1.0.7",
62 | "electron-store": "^8.0.0",
63 | "jsdom": "^16.6.0",
64 | "nodemon": "^2.0.12",
65 | "postcss": "^8.2.8",
66 | "puppeteer-core": "^10.1.0",
67 | "puppeteer-in-electron": "^3.0.5",
68 | "react": "^17.0.1",
69 | "react-axios": "^2.0.5",
70 | "react-dom": "^17.0.1",
71 | "react-loader-spinner": "^4.0.0",
72 | "react-promise-tracker": "^2.1.0",
73 | "react-router": "^5.2.0",
74 | "react-router-dom": "^5.2.0",
75 | "react-spinners": "^0.11.0"
76 | },
77 | "devDependencies": {
78 | "@babel/core": "^7.13.10",
79 | "@babel/preset-env": "^7.13.10",
80 | "@babel/preset-react": "^7.12.13",
81 | "@svgr/webpack": "^5.5.0",
82 | "babel-loader": "^8.2.2",
83 | "cross-env": "^7.0.3",
84 | "css-loader": "^5.1.1",
85 | "electron": "^12.0.15",
86 | "electron-devtools-installer": "^3.1.1",
87 | "electron-packager": "^15.2.0",
88 | "electron-reloader": "^1.2.1",
89 | "file-loader": "^6.2.0",
90 | "html-webpack-plugin": "^5.3.1",
91 | "mini-css-extract-plugin": "^1.3.9",
92 | "postcss-import": "^14.0.0",
93 | "postcss-loader": "^5.1.0",
94 | "postcss-nested": "^5.0.5",
95 | "postcss-preset-env": "^6.7.0",
96 | "postcss-pxtorem": "^5.1.1",
97 | "style-loader": "^2.0.0",
98 | "webpack": "^5.24.4",
99 | "webpack-cli": "^4.5.0",
100 | "webpack-dev-server": "^3.11.2"
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: {
3 | 'postcss-import': {},
4 | 'postcss-nested': {},
5 | 'postcss-preset-env': {},
6 | 'postcss-pxtorem': {
7 | rootValue: 16,
8 | unitPrecision: 5,
9 | propList: ['*'],
10 | selectorBlackList: ['html', 'body'],
11 | replace: true,
12 | mediaQuery: false,
13 | minPixelValue: 0
14 | }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/assets/css/App.css:
--------------------------------------------------------------------------------
1 | /* Main CSS file */
2 |
3 | @import '_example/example.css';
4 |
5 | .settingsDiv {
6 | margin-left: 30px;
7 | }
8 |
9 | .settingsDiv > button {
10 | margin-left: 1%;
11 | }
12 |
13 | #historyDiv {
14 | /* margin-left: 30px; */
15 | overflow: visible !important;
16 | }
17 |
18 | .fade-enter {
19 | opacity: 0;
20 | }
21 |
22 | .fade-enter.fade-enter-active {
23 | opacity: 1;
24 | transition: opacity 5ms ease-in;
25 | }
26 |
27 | body {
28 | margin: 2% 5% 0% 5% !important;
29 | }
30 |
31 | .home-button-margin {
32 | margin: 3%;
33 | }
34 |
35 | .results-grid-home {
36 | padding: 1%;
37 | margin: 1%;
38 | display: grid;
39 | grid-template-columns: 1fr 1fr;
40 | grid-template-rows: 1fr 1fr 1fr 1fr;
41 | gap: 10% 0%;
42 | justify-items: left;
43 | align-items: center;
44 | }
45 |
46 | /* if results in history dont fit well, make this a flex-box with set width and height and give it a flex wrap */
47 | .results-grid-history {
48 | padding: 1%;
49 | margin: 1%;
50 | display: grid;
51 | grid-template-columns: 1fr 1fr;
52 | grid-template-rows: 1fr 1fr 1fr 1fr;
53 | gap: 0.5% 0%;
54 | justify-items: left;
55 | align-items: center;
56 | }
57 |
58 | .historyCard {
59 | height: 80%;
60 | }
61 |
62 | .history-grid {
63 | padding: 0% 0% 5% 0px;
64 | display: grid;
65 | grid-template-columns: 50% 50%;
66 | gap: 2% 2%;
67 | }
68 |
69 | .accordion-column {
70 | display: flex;
71 | flex-direction: column;
72 | }
73 |
74 | .history-flex {
75 | display: flex;
76 | margin: 15px 10px;
77 | /* height: 22%; */
78 | flex-direction: row;
79 | align-items: center;
80 | align-content: center;
81 | justify-content: space-around;
82 | justify-items: baseline;
83 | }
84 |
85 | .history-button-margin {
86 | margin: 5px;
87 | }
88 |
89 | .history-bottom {
90 | width: fit-content;
91 | display: flex;
92 | justify-content: center;
93 | align-items: center;
94 | }
95 |
96 | #filled-basic {
97 | width: 50vw !important;
98 | }
99 |
100 | .settings-paper {
101 | display: flex;
102 | flex-direction: column;
103 | justify-content: center;
104 | align-items: center;
105 | padding: 3%;
106 | margin: 4% 15% !important;
107 | }
108 |
109 | .export-button {
110 | width: fit-content;
111 | margin: 0% 4.5%;
112 | }
113 |
114 | .about-paper {
115 | display: flex;
116 | flex-direction: column;
117 | margin: 5%;
118 | }
119 |
120 | .MuiPaper-elevation3 {
121 | /* margin: 2.5% 6%; */
122 | padding: 2%;
123 | margin: 20px 0px;
124 | display: flex;
125 | /* flex-direction: column;
126 | justify-content: center;
127 | align-items: center;
128 | align-content: center;
129 | justify-items: center; */
130 | }
131 |
132 | .lmargin-home {
133 | margin: 4% 6%;
134 | overflow: hidden;
135 | }
136 |
137 | .inside-paper {
138 | padding: 15px;
139 | width: 75%;
140 | /* height: 15vh; */
141 | /* margin: 0% 1% 0% 5%; */
142 | display: flex;
143 | align-items: center;
144 | align-content: center;
145 | justify-content: center;
146 | justify-items: center;
147 | /* padding: 1%; */
148 | }
149 |
150 | .inside-paper-bottom {
151 | /* margin: 0% 0% 0.5% 5%; */
152 | height: fit-content !important;
153 | display: flex;
154 | align-items: stretch;
155 | /* width: 70%; */
156 | }
157 |
158 | .MuiPaper-root {
159 | }
160 |
161 | .top-home {
162 | width: 50vw;
163 | }
164 |
165 | .MuiInputBase-input {
166 | width: 55vw;
167 | }
168 |
169 | .mainContainer {
170 | height: 100%;
171 | width: 100%;
172 | }
173 |
174 | .whole-cards {
175 | height: fit-content;
176 | }
177 |
178 | .top-div {
179 | display: flex;
180 | flex-direction: column;
181 | justify-content: center;
182 | align-items: center;
183 | width: fit-content;
184 | }
185 |
186 | .spin {
187 | padding-top: 10%;
188 | }
189 |
190 | .logo-top {
191 | width: 1.3in;
192 | fill: white;
193 | position: absolute;
194 | left: 5.75%;
195 | top: -3.1%;
196 | z-index: 1120;
197 | }
198 |
199 | .logo-top-sideNav {
200 | width: 1.3in;
201 | fill: white;
202 | position: absolute;
203 | left: 7.75%;
204 | top: -45%;
205 | z-index: 1120;
206 | }
207 |
208 | .logo-history {
209 | width: 80px;
210 | fill: white;
211 | /* margin-left: 38.6vw; */
212 | }
213 |
214 | .center-logo {
215 | display: flex;
216 | justify-content: center;
217 | align-items: center;
218 | }
219 |
220 | .logo-bottom {
221 | width: 13%;
222 | fill: white;
223 | /* position: absolute;
224 | left: 45.2%;
225 | top: 83vh; */
226 | }
227 |
228 | .logo-bottom-regular {
229 | width: 15%;
230 | /* background-color: #3f51b5; */
231 | fill: black;
232 | }
233 |
234 | /* @media screen and (max-width: 650px), (max-height: 820px) {
235 | body {
236 | overflow: auto !important;
237 | margin: 0% !important;
238 | }
239 |
240 | .MuiPaper-elevation3 {
241 | margin: 1% 0%;
242 |
243 | display: flex;
244 | }
245 |
246 | .lmargin-home {
247 | height: 100vh;
248 | width: 100vw;
249 | }
250 |
251 | .inside-paper {
252 | width: 95%;
253 | display: flex;
254 | align-items: center;
255 | align-content: center;
256 | justify-content: center;
257 | justify-items: center;
258 |
259 | }
260 |
261 | .inside-paper-bottom {
262 |
263 | height: 60vh !important;
264 | display: flex;
265 | align-items:stretch;
266 |
267 | }
268 |
269 | .results-grid {
270 | padding: 1%;
271 | margin: 1%;
272 | display: grid;
273 | grid-template-columns: 1fr 1fr;
274 | grid-template-rows: 1fr 1fr 1fr 1fr;
275 | gap: 10% 0%;
276 | justify-items: center;
277 | align-items: center;
278 | }
279 |
280 | } */
281 | /* @media screen and (max-width: 300px) and (max-height: 740px) {
282 | body {
283 | overflow: auto;
284 | }
285 | .MuiPaper-elevation3 {
286 | margin: 5% 5%;
287 | padding: 3%;
288 | display: flex;
289 | height: 900px;
290 | width: auto;
291 | }
292 |
293 | .inside-paper {
294 | width: auto;
295 | display: flex;
296 | align-items: center;
297 | align-content: center;
298 | justify-content: center;
299 | justify-items: center;
300 | }
301 |
302 | .inside-paper-bottom {
303 | height: 500px !important;
304 | display: flex;
305 | align-items:stretch;
306 | }
307 |
308 | .results-grid {
309 | padding: 1%;
310 | margin: 1%;
311 | display: grid;
312 | grid-template-columns: 1fr 1fr;
313 | grid-template-rows: 1fr 1fr 1fr 1fr;
314 | gap: 10% 0%;
315 | justify-items: center;
316 | align-items: center;
317 | }
318 | } */
319 |
--------------------------------------------------------------------------------
/src/assets/css/_example/example.css:
--------------------------------------------------------------------------------
1 | @import url('https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100;0,300;0,400;0,500;1,100&display=swap');
2 |
3 | @media screen and (prefers-color-scheme: light), screen and (prefers-color-scheme: no-preference) {
4 | Light theme
5 | body{
6 | color: #000;
7 | background-color: #fff;
8 | overflow: hidden;
9 | }
10 | }
11 |
12 | @media screen and (prefers-color-scheme: dark) {
13 | Dark theme
14 | body {
15 | color: #fff;
16 | background-color: #000;
17 | }
18 | }
19 |
20 | * {
21 | font-family: 'Roboto', sans-serif;;
22 | }
23 |
24 |
--------------------------------------------------------------------------------
/src/components/App.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import { Switch, Route, Redirect, useLocation } from 'react-router-dom';
3 |
4 | import '../assets/css/App.css';
5 | import PermanentDrawerLeft from './material/SideNav';
6 | import About from './pages/About';
7 | import History from './pages/History';
8 | import Home from './pages/Home';
9 | import Settings from './pages/Settings';
10 | import { TransitionGroup, CSSTransition } from 'react-transition-group';
11 |
12 | import { library } from '@fortawesome/fontawesome-svg-core';
13 | import { fab } from '@fortawesome/free-brands-svg-icons';
14 | import { faCheckSquare, faCoffee } from '@fortawesome/free-solid-svg-icons';
15 | import { fas } from '@fortawesome/free-solid-svg-icons';
16 |
17 | library.add(fab,fas,faCheckSquare, faCoffee)
18 |
19 | function App() {
20 | let location = useLocation();
21 |
22 | const RedirectToHome = () => {
23 | return