Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions .github/workflows/snyk-container-scan.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
name: Snyk Container Scan

on:
push:
branches: [ main ]
pull_request:
branches: [ main ]

jobs:
snyk-container-scan:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Build Docker image
run: |
docker build -t my-app:ci .

- name: Run Snyk container scan
uses: snyk/actions/docker@v3
with:
image: my-app:ci
args: --file=Dockerfile --project-name=${{ github.repository }} --org=${{ secrets.SNYK_ORG_ID }}
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}

- name: Upload Snyk scan results to Snyk Web UI
if: always()
run: echo "Snyk scan results are automatically sent to the Snyk Web UI if SNYK_TOKEN is set."
98 changes: 80 additions & 18 deletions app.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

// mongoose setup
require('./mongoose-db');
require('./typeorm-db')
require('./typeorm-db');

var st = require('st');
var crypto = require('crypto');
Expand All @@ -13,7 +13,7 @@ var http = require('http');
var path = require('path');
var ejsEngine = require('ejs-locals');
var bodyParser = require('body-parser');
var session = require('express-session')
var session = require('express-session');
var methodOverride = require('method-override');
var logger = require('morgan');
var errorHandler = require('errorhandler');
Expand All @@ -23,11 +23,13 @@ var fileUpload = require('express-fileupload');
var dust = require('dustjs-linkedin');
var dustHelpers = require('dustjs-helpers');
var cons = require('consolidate');
const hbs = require('hbs')
const hbs = require('hbs');
const fs = require('fs');
const cp = require('child_process'); // Used for RCE

var app = express();
var routes = require('./routes');
var routesUsers = require('./routes/users.js')
var routesUsers = require('./routes/users.js');

// all environments
app.set('port', process.env.PORT || 3001);
Expand All @@ -42,17 +44,76 @@ app.use(methodOverride());
app.use(session({
secret: 'keyboard cat',
name: 'connect.sid',
cookie: { path: '/' }
}))
cookie: { path: '/', httpOnly: false, secure: false }

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  Sensitive Cookie in HTTPS Session Without 'Secure' Attribute

Cookie has the Secure attribute set to false. Set it to true to protect the cookie from man-in-the-middle attacks.

Line 47 | CWE-614 | Priority score 408
Data flow: 2 steps

Step 1 - 2

cookie: { path: '/', httpOnly: false, secure: false }

⚡ Fix this issue by replying with the following command: @snyk /fix

}));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(fileUpload());


app.post('/login', (req, res) => {
let { username, password } = req.body;
let sqlQuery = `SELECT * FROM users WHERE username = '${username}' AND password = '${password}'`;


console.log('Executing Query: ', sqlQuery);
res.send('Login attempt recorded.');
});


app.post('/upload', (req, res) => {
if (!req.files || Object.keys(req.files).length === 0) {
return res.status(400).send('No files were uploaded.');
}

let uploadedFile = req.files.file;
let uploadPath = './uploads/' + uploadedFile.name;

// **Save the file without validating its type**
uploadedFile.mv(uploadPath, function (err) {

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  Path Traversal

Unsanitized input from an uploaded file flows into mv, where it is used as a path. This may result in a Path Traversal vulnerability and allow an attacker to delete arbitrary files.

Line 73 | CWE-23 | Priority score 808 | Learn more about this vulnerability
Data flow: 12 steps

Step 1 - 5

let uploadedFile = req.files.file;

Step 6 - 10 app.js#L70

Step 11 - 12

uploadedFile.mv(uploadPath, function (err) {

⚡ Fix this issue by replying with the following command: @snyk /fix

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  Path Traversal

Unsanitized input from an uploaded file flows into mv, where it is used as a path. This may result in a Path Traversal vulnerability and allow an attacker to delete arbitrary files.

Line 73 | CWE-23 | Priority score 808 | Learn more about this vulnerability
Data flow: 12 steps

Step 1 - 5

let uploadedFile = req.files.file;

Step 6 - 10 app.js#L70

Step 11 - 12

uploadedFile.mv(uploadPath, function (err) {

if (err) return res.status(500).send(err);

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  Cross-site Scripting (XSS)

Unsanitized input from an uploaded file flows into send, where it is used to render an HTML page returned to the user. This may result in a Cross-Site Scripting attack (XSS).

Line 74 | CWE-79 | Priority score 815 | Learn more about this vulnerability
Data flow: 9 steps

Step 1 - 5

let uploadedFile = req.files.file;

Step 6 - 7 app.js#L73

Step 8 - 9

if (err) return res.status(500).send(err);

⚡ Fix this issue by replying with the following command: @snyk /fix

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  Cross-site Scripting (XSS)

Unsanitized input from an uploaded file flows into send, where it is used to render an HTML page returned to the user. This may result in a Cross-Site Scripting attack (XSS).

Line 74 | CWE-79 | Priority score 815 | Learn more about this vulnerability
Data flow: 9 steps

Step 1 - 5

let uploadedFile = req.files.file;

Step 6 - 7 app.js#L73

Step 8 - 9

if (err) return res.status(500).send(err);



cp.exec(`node ${uploadPath}`, (error, stdout, stderr) => {

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  Command Injection

Unsanitized input from an uploaded file flows into child_process.exec, where it is used to build a shell command. This may result in a Command Injection vulnerability.

Line 77 | CWE-78 | Priority score 808 | Learn more about this vulnerability
Data flow: 13 steps

Step 1 - 5

let uploadedFile = req.files.file;

Step 6 - 10 app.js#L70

Step 11 - 13

cp.exec(`node ${uploadPath}`, (error, stdout, stderr) => {

⚡ Fix this issue by replying with the following command: @snyk /fix

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  Command Injection

Unsanitized input from an uploaded file flows into child_process.exec, where it is used to build a shell command. This may result in a Command Injection vulnerability.

Line 77 | CWE-78 | Priority score 808 | Learn more about this vulnerability
Data flow: 13 steps

Step 1 - 5

let uploadedFile = req.files.file;

Step 6 - 10 app.js#L70

Step 11 - 13

cp.exec(`node ${uploadPath}`, (error, stdout, stderr) => {

if (error) {
return res.send('Execution failed');
}
res.send('File uploaded and executed: ' + stdout);
});
});
});


app.get('/profile', (req, res) => {
let username = req.query.username || 'Guest';


res.send(`<h1>Welcome, ${username}</h1><script>alert('XSS!');</script>`);

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  Cross-site Scripting (XSS)

Unsanitized input from an HTTP parameter flows into send, where it is used to render an HTML page returned to the user. This may result in a Cross-Site Scripting attack (XSS).

Line 91 | CWE-79 | Priority score 815 | Learn more about this vulnerability
Data flow: 10 steps

Step 1 - 7

let username = req.query.username || 'Guest';

Step 8 - 10

res.send(`<h1>Welcome, ${username}</h1><script>alert('XSS!');</script>`);

⚡ Fix this issue by replying with the following command: @snyk /fix

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  Cross-site Scripting (XSS)

Unsanitized input from an HTTP parameter flows into send, where it is used to render an HTML page returned to the user. This may result in a Cross-Site Scripting attack (XSS).

Line 91 | CWE-79 | Priority score 815 | Learn more about this vulnerability
Data flow: 10 steps

Step 1 - 7

let username = req.query.username || 'Guest';

Step 8 - 10

res.send(`<h1>Welcome, ${username}</h1><script>alert('XSS!');</script>`);

});


app.post('/pollute', (req, res) => {
Object.assign({}, req.body);
res.send('Prototype pollution executed.');
});


app.post('/chat', (req, res) => {
let url = req.body.url;


require('http').get(url, (response) => {

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  Server-Side Request Forgery (SSRF)

Unsanitized input from the HTTP request body flows into http.get, where it is used as an URL to perform a request. This may result in a Server-Side Request Forgery vulnerability.

Line 105 | CWE-918 | Priority score 808 | Learn more about this vulnerability
Data flow: 7 steps

Step 1 - 5

let url = req.body.url;

Step 6 - 7

require('http').get(url, (response) => {

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  Server-Side Request Forgery (SSRF)

Unsanitized input from the HTTP request body flows into http.get, where it is used as an URL to perform a request. This may result in a Server-Side Request Forgery vulnerability.

Line 105 | CWE-918 | Priority score 808 | Learn more about this vulnerability
Data flow: 7 steps

Step 1 - 5

let url = req.body.url;

Step 6 - 7

require('http').get(url, (response) => {

let data = '';
response.on('data', (chunk) => { data += chunk; });
response.on('end', () => { res.send(data); });
}).on('error', (err) => {
res.status(500).send('Request failed');
});
});

// Routes
app.use(routes.current_user);
app.get('/', routes.index);
app.get('/login', routes.login);
app.post('/login', routes.loginHandler);
app.get('/admin', routes.isLoggedIn, routes.admin);
app.get('/account_details', routes.isLoggedIn, routes.get_account_details);
app.post('/account_details', routes.isLoggedIn, routes.save_account_details);
Expand All @@ -63,26 +124,27 @@ app.get('/edit/:id', routes.edit);
app.post('/update/:id', routes.update);
app.post('/import', routes.import);
app.get('/about_new', routes.about_new);
app.get('/chat', routes.chat.get);
app.put('/chat', routes.chat.add);
app.delete('/chat', routes.chat.delete);
app.use('/users', routesUsers)
app.use('/users', routesUsers);

// Static
app.use(st({ path: './public', url: '/public' }));

// Add the option to output (sanitized!) markdown
marked.setOptions({ sanitize: true });

const CSP = "script-src * 'unsafe-inline' 'unsafe-eval'; img-src *";
app.use((req, res, next) => {
res.setHeader('Content-Security-Policy', CSP);
next();
});

// Add the option to output markdown
marked.setOptions({ sanitize: false });
app.locals.marked = marked;

// development only
// Development only
if (app.get('env') == 'development') {
app.use(errorHandler());
}

var token = 'SECRET_TOKEN_f8ed84e8f41e4146403dd4a6bbcea5e418d23a9';
console.log('token: ' + token);

http.createServer(app).listen(app.get('port'), function () {
console.log('Express server listening on port ' + app.get('port'));
});