Merge branch 'main' into htmlReg

This commit is contained in:
Erik Krogh Kristensen
2021-11-04 12:58:42 +01:00
450 changed files with 15060 additions and 5288 deletions

View File

@@ -0,0 +1,185 @@
nodes
| check-domain.js:16:9:16:27 | url |
| check-domain.js:16:15:16:27 | req.query.url |
| check-domain.js:16:15:16:27 | req.query.url |
| check-domain.js:17:13:17:15 | url |
| check-domain.js:17:13:17:15 | url |
| check-domain.js:26:15:26:27 | req.query.url |
| check-domain.js:26:15:26:27 | req.query.url |
| check-domain.js:26:15:26:27 | req.query.url |
| check-middleware.js:9:13:9:43 | "test.c ... tainted |
| check-middleware.js:9:13:9:43 | "test.c ... tainted |
| check-middleware.js:9:27:9:43 | req.query.tainted |
| check-middleware.js:9:27:9:43 | req.query.tainted |
| check-path.js:19:13:19:43 | 'test.c ... tainted |
| check-path.js:19:13:19:43 | 'test.c ... tainted |
| check-path.js:19:27:19:43 | req.query.tainted |
| check-path.js:19:27:19:43 | req.query.tainted |
| check-path.js:22:13:22:63 | 'test.c ... ainted) |
| check-path.js:22:13:22:63 | 'test.c ... ainted) |
| check-path.js:22:27:22:63 | encodeU ... ainted) |
| check-path.js:22:46:22:62 | req.query.tainted |
| check-path.js:22:46:22:62 | req.query.tainted |
| check-path.js:23:13:23:45 | `/addre ... inted}` |
| check-path.js:23:13:23:45 | `/addre ... inted}` |
| check-path.js:23:27:23:43 | req.query.tainted |
| check-path.js:23:27:23:43 | req.query.tainted |
| check-path.js:24:13:24:65 | `/addre ... nted)}` |
| check-path.js:24:13:24:65 | `/addre ... nted)}` |
| check-path.js:24:27:24:63 | encodeU ... ainted) |
| check-path.js:24:46:24:62 | req.query.tainted |
| check-path.js:24:46:24:62 | req.query.tainted |
| check-path.js:33:15:33:45 | 'test.c ... tainted |
| check-path.js:33:15:33:45 | 'test.c ... tainted |
| check-path.js:33:29:33:45 | req.query.tainted |
| check-path.js:33:29:33:45 | req.query.tainted |
| check-path.js:37:15:37:45 | 'test.c ... tainted |
| check-path.js:37:15:37:45 | 'test.c ... tainted |
| check-path.js:37:29:37:45 | req.query.tainted |
| check-path.js:37:29:37:45 | req.query.tainted |
| check-path.js:45:13:45:44 | `${base ... inted}` |
| check-path.js:45:13:45:44 | `${base ... inted}` |
| check-path.js:45:26:45:42 | req.query.tainted |
| check-path.js:45:26:45:42 | req.query.tainted |
| check-regex.js:24:15:24:42 | baseURL ... tainted |
| check-regex.js:24:15:24:42 | baseURL ... tainted |
| check-regex.js:24:25:24:42 | req.params.tainted |
| check-regex.js:24:25:24:42 | req.params.tainted |
| check-regex.js:31:15:31:45 | "test.c ... tainted |
| check-regex.js:31:15:31:45 | "test.c ... tainted |
| check-regex.js:31:29:31:45 | req.query.tainted |
| check-regex.js:31:29:31:45 | req.query.tainted |
| check-regex.js:34:15:34:42 | baseURL ... tainted |
| check-regex.js:34:15:34:42 | baseURL ... tainted |
| check-regex.js:34:25:34:42 | req.params.tainted |
| check-regex.js:34:25:34:42 | req.params.tainted |
| check-regex.js:41:13:41:43 | "test.c ... tainted |
| check-regex.js:41:13:41:43 | "test.c ... tainted |
| check-regex.js:41:27:41:43 | req.query.tainted |
| check-regex.js:41:27:41:43 | req.query.tainted |
| check-validator.js:15:15:15:45 | "test.c ... tainted |
| check-validator.js:15:15:15:45 | "test.c ... tainted |
| check-validator.js:15:29:15:45 | req.query.tainted |
| check-validator.js:15:29:15:45 | req.query.tainted |
| check-validator.js:27:15:27:45 | "test.c ... tainted |
| check-validator.js:27:15:27:45 | "test.c ... tainted |
| check-validator.js:27:29:27:45 | req.query.tainted |
| check-validator.js:27:29:27:45 | req.query.tainted |
| check-validator.js:50:15:50:45 | "test.c ... tainted |
| check-validator.js:50:15:50:45 | "test.c ... tainted |
| check-validator.js:50:29:50:45 | req.query.tainted |
| check-validator.js:50:29:50:45 | req.query.tainted |
| check-validator.js:54:9:54:37 | numberURL |
| check-validator.js:54:21:54:37 | req.query.tainted |
| check-validator.js:54:21:54:37 | req.query.tainted |
| check-validator.js:59:15:59:45 | "test.c ... tainted |
| check-validator.js:59:15:59:45 | "test.c ... tainted |
| check-validator.js:59:29:59:45 | req.query.tainted |
| check-validator.js:59:29:59:45 | req.query.tainted |
| check-validator.js:62:15:62:37 | "test.c ... mberURL |
| check-validator.js:62:15:62:37 | "test.c ... mberURL |
| check-validator.js:62:29:62:37 | numberURL |
| check-validator.js:68:15:68:45 | "test.c ... tainted |
| check-validator.js:68:15:68:45 | "test.c ... tainted |
| check-validator.js:68:29:68:45 | req.query.tainted |
| check-validator.js:68:29:68:45 | req.query.tainted |
edges
| check-domain.js:16:9:16:27 | url | check-domain.js:17:13:17:15 | url |
| check-domain.js:16:9:16:27 | url | check-domain.js:17:13:17:15 | url |
| check-domain.js:16:15:16:27 | req.query.url | check-domain.js:16:9:16:27 | url |
| check-domain.js:16:15:16:27 | req.query.url | check-domain.js:16:9:16:27 | url |
| check-domain.js:26:15:26:27 | req.query.url | check-domain.js:26:15:26:27 | req.query.url |
| check-middleware.js:9:27:9:43 | req.query.tainted | check-middleware.js:9:13:9:43 | "test.c ... tainted |
| check-middleware.js:9:27:9:43 | req.query.tainted | check-middleware.js:9:13:9:43 | "test.c ... tainted |
| check-middleware.js:9:27:9:43 | req.query.tainted | check-middleware.js:9:13:9:43 | "test.c ... tainted |
| check-middleware.js:9:27:9:43 | req.query.tainted | check-middleware.js:9:13:9:43 | "test.c ... tainted |
| check-path.js:19:27:19:43 | req.query.tainted | check-path.js:19:13:19:43 | 'test.c ... tainted |
| check-path.js:19:27:19:43 | req.query.tainted | check-path.js:19:13:19:43 | 'test.c ... tainted |
| check-path.js:19:27:19:43 | req.query.tainted | check-path.js:19:13:19:43 | 'test.c ... tainted |
| check-path.js:19:27:19:43 | req.query.tainted | check-path.js:19:13:19:43 | 'test.c ... tainted |
| check-path.js:22:27:22:63 | encodeU ... ainted) | check-path.js:22:13:22:63 | 'test.c ... ainted) |
| check-path.js:22:27:22:63 | encodeU ... ainted) | check-path.js:22:13:22:63 | 'test.c ... ainted) |
| check-path.js:22:46:22:62 | req.query.tainted | check-path.js:22:27:22:63 | encodeU ... ainted) |
| check-path.js:22:46:22:62 | req.query.tainted | check-path.js:22:27:22:63 | encodeU ... ainted) |
| check-path.js:23:27:23:43 | req.query.tainted | check-path.js:23:13:23:45 | `/addre ... inted}` |
| check-path.js:23:27:23:43 | req.query.tainted | check-path.js:23:13:23:45 | `/addre ... inted}` |
| check-path.js:23:27:23:43 | req.query.tainted | check-path.js:23:13:23:45 | `/addre ... inted}` |
| check-path.js:23:27:23:43 | req.query.tainted | check-path.js:23:13:23:45 | `/addre ... inted}` |
| check-path.js:24:27:24:63 | encodeU ... ainted) | check-path.js:24:13:24:65 | `/addre ... nted)}` |
| check-path.js:24:27:24:63 | encodeU ... ainted) | check-path.js:24:13:24:65 | `/addre ... nted)}` |
| check-path.js:24:46:24:62 | req.query.tainted | check-path.js:24:27:24:63 | encodeU ... ainted) |
| check-path.js:24:46:24:62 | req.query.tainted | check-path.js:24:27:24:63 | encodeU ... ainted) |
| check-path.js:33:29:33:45 | req.query.tainted | check-path.js:33:15:33:45 | 'test.c ... tainted |
| check-path.js:33:29:33:45 | req.query.tainted | check-path.js:33:15:33:45 | 'test.c ... tainted |
| check-path.js:33:29:33:45 | req.query.tainted | check-path.js:33:15:33:45 | 'test.c ... tainted |
| check-path.js:33:29:33:45 | req.query.tainted | check-path.js:33:15:33:45 | 'test.c ... tainted |
| check-path.js:37:29:37:45 | req.query.tainted | check-path.js:37:15:37:45 | 'test.c ... tainted |
| check-path.js:37:29:37:45 | req.query.tainted | check-path.js:37:15:37:45 | 'test.c ... tainted |
| check-path.js:37:29:37:45 | req.query.tainted | check-path.js:37:15:37:45 | 'test.c ... tainted |
| check-path.js:37:29:37:45 | req.query.tainted | check-path.js:37:15:37:45 | 'test.c ... tainted |
| check-path.js:45:26:45:42 | req.query.tainted | check-path.js:45:13:45:44 | `${base ... inted}` |
| check-path.js:45:26:45:42 | req.query.tainted | check-path.js:45:13:45:44 | `${base ... inted}` |
| check-path.js:45:26:45:42 | req.query.tainted | check-path.js:45:13:45:44 | `${base ... inted}` |
| check-path.js:45:26:45:42 | req.query.tainted | check-path.js:45:13:45:44 | `${base ... inted}` |
| check-regex.js:24:25:24:42 | req.params.tainted | check-regex.js:24:15:24:42 | baseURL ... tainted |
| check-regex.js:24:25:24:42 | req.params.tainted | check-regex.js:24:15:24:42 | baseURL ... tainted |
| check-regex.js:24:25:24:42 | req.params.tainted | check-regex.js:24:15:24:42 | baseURL ... tainted |
| check-regex.js:24:25:24:42 | req.params.tainted | check-regex.js:24:15:24:42 | baseURL ... tainted |
| check-regex.js:31:29:31:45 | req.query.tainted | check-regex.js:31:15:31:45 | "test.c ... tainted |
| check-regex.js:31:29:31:45 | req.query.tainted | check-regex.js:31:15:31:45 | "test.c ... tainted |
| check-regex.js:31:29:31:45 | req.query.tainted | check-regex.js:31:15:31:45 | "test.c ... tainted |
| check-regex.js:31:29:31:45 | req.query.tainted | check-regex.js:31:15:31:45 | "test.c ... tainted |
| check-regex.js:34:25:34:42 | req.params.tainted | check-regex.js:34:15:34:42 | baseURL ... tainted |
| check-regex.js:34:25:34:42 | req.params.tainted | check-regex.js:34:15:34:42 | baseURL ... tainted |
| check-regex.js:34:25:34:42 | req.params.tainted | check-regex.js:34:15:34:42 | baseURL ... tainted |
| check-regex.js:34:25:34:42 | req.params.tainted | check-regex.js:34:15:34:42 | baseURL ... tainted |
| check-regex.js:41:27:41:43 | req.query.tainted | check-regex.js:41:13:41:43 | "test.c ... tainted |
| check-regex.js:41:27:41:43 | req.query.tainted | check-regex.js:41:13:41:43 | "test.c ... tainted |
| check-regex.js:41:27:41:43 | req.query.tainted | check-regex.js:41:13:41:43 | "test.c ... tainted |
| check-regex.js:41:27:41:43 | req.query.tainted | check-regex.js:41:13:41:43 | "test.c ... tainted |
| check-validator.js:15:29:15:45 | req.query.tainted | check-validator.js:15:15:15:45 | "test.c ... tainted |
| check-validator.js:15:29:15:45 | req.query.tainted | check-validator.js:15:15:15:45 | "test.c ... tainted |
| check-validator.js:15:29:15:45 | req.query.tainted | check-validator.js:15:15:15:45 | "test.c ... tainted |
| check-validator.js:15:29:15:45 | req.query.tainted | check-validator.js:15:15:15:45 | "test.c ... tainted |
| check-validator.js:27:29:27:45 | req.query.tainted | check-validator.js:27:15:27:45 | "test.c ... tainted |
| check-validator.js:27:29:27:45 | req.query.tainted | check-validator.js:27:15:27:45 | "test.c ... tainted |
| check-validator.js:27:29:27:45 | req.query.tainted | check-validator.js:27:15:27:45 | "test.c ... tainted |
| check-validator.js:27:29:27:45 | req.query.tainted | check-validator.js:27:15:27:45 | "test.c ... tainted |
| check-validator.js:50:29:50:45 | req.query.tainted | check-validator.js:50:15:50:45 | "test.c ... tainted |
| check-validator.js:50:29:50:45 | req.query.tainted | check-validator.js:50:15:50:45 | "test.c ... tainted |
| check-validator.js:50:29:50:45 | req.query.tainted | check-validator.js:50:15:50:45 | "test.c ... tainted |
| check-validator.js:50:29:50:45 | req.query.tainted | check-validator.js:50:15:50:45 | "test.c ... tainted |
| check-validator.js:54:9:54:37 | numberURL | check-validator.js:62:29:62:37 | numberURL |
| check-validator.js:54:21:54:37 | req.query.tainted | check-validator.js:54:9:54:37 | numberURL |
| check-validator.js:54:21:54:37 | req.query.tainted | check-validator.js:54:9:54:37 | numberURL |
| check-validator.js:59:29:59:45 | req.query.tainted | check-validator.js:59:15:59:45 | "test.c ... tainted |
| check-validator.js:59:29:59:45 | req.query.tainted | check-validator.js:59:15:59:45 | "test.c ... tainted |
| check-validator.js:59:29:59:45 | req.query.tainted | check-validator.js:59:15:59:45 | "test.c ... tainted |
| check-validator.js:59:29:59:45 | req.query.tainted | check-validator.js:59:15:59:45 | "test.c ... tainted |
| check-validator.js:62:29:62:37 | numberURL | check-validator.js:62:15:62:37 | "test.c ... mberURL |
| check-validator.js:62:29:62:37 | numberURL | check-validator.js:62:15:62:37 | "test.c ... mberURL |
| check-validator.js:68:29:68:45 | req.query.tainted | check-validator.js:68:15:68:45 | "test.c ... tainted |
| check-validator.js:68:29:68:45 | req.query.tainted | check-validator.js:68:15:68:45 | "test.c ... tainted |
| check-validator.js:68:29:68:45 | req.query.tainted | check-validator.js:68:15:68:45 | "test.c ... tainted |
| check-validator.js:68:29:68:45 | req.query.tainted | check-validator.js:68:15:68:45 | "test.c ... tainted |
#select
| check-domain.js:17:13:17:15 | url | check-domain.js:16:15:16:27 | req.query.url | check-domain.js:17:13:17:15 | url | The URL of this request depends on a user-provided value |
| check-domain.js:26:15:26:27 | req.query.url | check-domain.js:26:15:26:27 | req.query.url | check-domain.js:26:15:26:27 | req.query.url | The URL of this request depends on a user-provided value |
| check-middleware.js:9:13:9:43 | "test.c ... tainted | check-middleware.js:9:27:9:43 | req.query.tainted | check-middleware.js:9:13:9:43 | "test.c ... tainted | The URL of this request depends on a user-provided value |
| check-path.js:19:13:19:43 | 'test.c ... tainted | check-path.js:19:27:19:43 | req.query.tainted | check-path.js:19:13:19:43 | 'test.c ... tainted | The URL of this request depends on a user-provided value |
| check-path.js:22:13:22:63 | 'test.c ... ainted) | check-path.js:22:46:22:62 | req.query.tainted | check-path.js:22:13:22:63 | 'test.c ... ainted) | The URL of this request depends on a user-provided value |
| check-path.js:23:13:23:45 | `/addre ... inted}` | check-path.js:23:27:23:43 | req.query.tainted | check-path.js:23:13:23:45 | `/addre ... inted}` | The URL of this request depends on a user-provided value |
| check-path.js:24:13:24:65 | `/addre ... nted)}` | check-path.js:24:46:24:62 | req.query.tainted | check-path.js:24:13:24:65 | `/addre ... nted)}` | The URL of this request depends on a user-provided value |
| check-path.js:33:15:33:45 | 'test.c ... tainted | check-path.js:33:29:33:45 | req.query.tainted | check-path.js:33:15:33:45 | 'test.c ... tainted | The URL of this request depends on a user-provided value |
| check-path.js:37:15:37:45 | 'test.c ... tainted | check-path.js:37:29:37:45 | req.query.tainted | check-path.js:37:15:37:45 | 'test.c ... tainted | The URL of this request depends on a user-provided value |
| check-path.js:45:13:45:44 | `${base ... inted}` | check-path.js:45:26:45:42 | req.query.tainted | check-path.js:45:13:45:44 | `${base ... inted}` | The URL of this request depends on a user-provided value |
| check-regex.js:24:15:24:42 | baseURL ... tainted | check-regex.js:24:25:24:42 | req.params.tainted | check-regex.js:24:15:24:42 | baseURL ... tainted | The URL of this request depends on a user-provided value |
| check-regex.js:31:15:31:45 | "test.c ... tainted | check-regex.js:31:29:31:45 | req.query.tainted | check-regex.js:31:15:31:45 | "test.c ... tainted | The URL of this request depends on a user-provided value |
| check-regex.js:34:15:34:42 | baseURL ... tainted | check-regex.js:34:25:34:42 | req.params.tainted | check-regex.js:34:15:34:42 | baseURL ... tainted | The URL of this request depends on a user-provided value |
| check-regex.js:41:13:41:43 | "test.c ... tainted | check-regex.js:41:27:41:43 | req.query.tainted | check-regex.js:41:13:41:43 | "test.c ... tainted | The URL of this request depends on a user-provided value |
| check-validator.js:15:15:15:45 | "test.c ... tainted | check-validator.js:15:29:15:45 | req.query.tainted | check-validator.js:15:15:15:45 | "test.c ... tainted | The URL of this request depends on a user-provided value |
| check-validator.js:27:15:27:45 | "test.c ... tainted | check-validator.js:27:29:27:45 | req.query.tainted | check-validator.js:27:15:27:45 | "test.c ... tainted | The URL of this request depends on a user-provided value |
| check-validator.js:50:15:50:45 | "test.c ... tainted | check-validator.js:50:29:50:45 | req.query.tainted | check-validator.js:50:15:50:45 | "test.c ... tainted | The URL of this request depends on a user-provided value |
| check-validator.js:59:15:59:45 | "test.c ... tainted | check-validator.js:59:29:59:45 | req.query.tainted | check-validator.js:59:15:59:45 | "test.c ... tainted | The URL of this request depends on a user-provided value |
| check-validator.js:62:15:62:37 | "test.c ... mberURL | check-validator.js:54:21:54:37 | req.query.tainted | check-validator.js:62:15:62:37 | "test.c ... mberURL | The URL of this request depends on a user-provided value |
| check-validator.js:68:15:68:45 | "test.c ... tainted | check-validator.js:68:29:68:45 | req.query.tainted | check-validator.js:68:15:68:45 | "test.c ... tainted | The URL of this request depends on a user-provided value |

View File

@@ -0,0 +1 @@
./experimental/Security/CWE-918/SSRF.ql

View File

@@ -0,0 +1,34 @@
// native modules
const url = require('url');
// dependencies
const axios = require('axios');
const express = require('express');
// constants
const VALID_DOMAINS = ['example.com', 'example-2.com'];
// start
const app = express();
app.get('/check-with-axios', req => {
// without validation
const url = req.query.url;
axios.get(url); //SSRF
// validating domain only
const decodedURI = decodeURIComponent(req.query.url);
const { hostname } = url.parse(decodedURI);
const { hostname } = url.parse(decodedURI);
if (isValidDomain(hostname, validDomains)) {
axios.get(req.query.url); //SSRF
}
});
const isValidDomain = (hostname, validDomains) => (
validDomains.some(domain => (
hostname === domain || hostname.endsWith(`.${domain}`))
)
);

View File

@@ -0,0 +1,19 @@
// dependencies
const axios = require('axios');
const express = require('express');
// start
const app = express();
app.get('/check-with-axios', validationMiddleware, req => {
axios.get("test.com/" + req.query.tainted); // OK is sanitized by the middleware - False Positive
});
const validationMiddleware = (req, res, next) => {
if (!Number.isInteger(req.query.tainted)) {
return res.sendStatus(400);
}
next();
}

View File

@@ -0,0 +1,57 @@
// native modules
const path = require('path');
const url = require('url');
// dependencies
const axios = require('axios');
const express = require('express');
// constants
const VALID_PATHS = ['/api/users/me', '/help', '/system/health'];
// start
const app = express();
app.get('/check-with-axios', req => {
const hardcoded = 'hardcodeado';
axios.get('test.com/' + hardcoded); // OK
axios.get('test.com/' + req.query.tainted); // SSRF
axios.get('test.com/' + Number(req.query.tainted)); // OK
axios.get('test.com/' + req.user.id); // OK
axios.get('test.com/' + encodeURIComponent(req.query.tainted)); // SSRF
axios.get(`/addresses/${req.query.tainted}`); // SSRF
axios.get(`/addresses/${encodeURIComponent(req.query.tainted)}`); // SSRF
if (Number.isInteger(req.query.tainted)) {
axios.get('test.com/' + req.query.tainted); // OK
}
if (isValidInput(req.query.tainted)){
axios.get('test.com/' + req.query.tainted); // OK
} else {
axios.get('test.com/' + req.query.tainted); // SSRF
}
if (doesntCheckAnything(req.query.tainted)) {
axios.get('test.com/' + req.query.tainted); // SSRF
}
if (isValidPath(req.query.tainted, VALID_PATHS)) {
axios.get('test.com/' + req.query.tainted) // OK
}
let baseURL = require('config').base
axios.get(`${baseURL}${req.query.tainted}`); // SSRF
if(!isValidInput(req.query.tainted)) {
return;
}
axios.get("test.com/" + req.query.tainted); // OK
});
const isValidPath = (path, validPaths) => validPaths.includes(path);
const isValidInput = (path) => Number.isInteger(path);
const doesntCheckAnything = (path) => true;

View File

@@ -0,0 +1,46 @@
// dependencies
const axios = require('axios');
const express = require('express');
// start
const app = express();
app.get('/check-with-axios', req => {
if (req.query.tainted.match(/^[0-9a-z]+$/)) { // letters and numbers
axios.get("test.com/" + req.query.tainted); // OK
}
if (req.query.tainted.match(/^[0-9a-z\-_]+$/)) { // letters, numbers, - and _
axios.get("test.com/" + req.query.tainted); // OK
}
if (req.query.tainted.match(/^.*$/)) { // anything
axios.get("test.com/" + req.query.tainted); // SSRF - False Negative
}
const baseURL = "test.com/"
if (isValidPath(req.params.tainted) ) {
axios.get(baseURL + req.params.tainted); // OK
}
if (!isValidPath(req.params.tainted) ) {
axios.get(baseURL + req.params.tainted); // SSRF
} else {
axios.get(baseURL + req.params.tainted); // OK
}
// Blacklists are not safe
if (!req.query.tainted.match(/^[/\.%]+$/)) {
axios.get("test.com/" + req.query.tainted); // SSRF
}
if (!isInBlacklist(req.params.tainted) ) {
axios.get(baseURL + req.params.tainted); // SSRF
}
if (!isValidPath(req.params.tainted)) {
return;
}
axios.get("test.com/" + req.query.tainted); // OK - False Positive
});
const isValidPath = path => path.match(/^[0-9a-z]+$/);
const isInBlackList = path => path.match(/^[/\.%]+$/);

View File

@@ -0,0 +1,98 @@
// dependencies
const axios = require('axios');
const express = require('express');
const validator = require('validator');
// start
const app = express();
app.get("/check-with-axios", req => {
// alphanumeric
if (validator.isAlphanumeric(req.query.tainted)) {
axios.get("test.com/" + req.query.tainted); // OK
}
if (isAlphanumeric(req.query.tainted)) {
axios.get("test.com/" + req.query.tainted); // SSRF
}
if (validAlphanumeric(req.query.tainted)) {
axios.get("test.com/" + req.query.tainted); // OK
}
if (validAlpha(req.query.tainted)) {
axios.get("test.com/" + req.query.tainted); // OK
}
if (validNumber(req.query.tainted)) {
axios.get("test.com/" + req.query.tainted); // OK
}
if (wrongValidation(req.query.tainted)) {
axios.get("test.com/" + req.query.tainted); // SSRF
}
// numbers
if (validHexadecimal(req.query.tainted)) {
axios.get("test.com/" + req.query.tainted); // OK
}
if (validHexaColor(req.query.tainted)) {
axios.get("test.com/" + req.query.tainted); // OK
}
if (validDecimal(req.query.tainted)) {
axios.get("test.com/" + req.query.tainted); // OK
}
if (validFloat(req.query.tainted)) {
axios.get("test.com/" + req.query.tainted); // OK
}
if (validInt(req.query.tainted)) {
axios.get("test.com/" + req.query.tainted); // OK
}
if (validOctal(req.query.tainted)) {
axios.get("test.com/" + req.query.tainted); // OK
}
if (validHexa(req.query.tainted)) {
axios.get("test.com/" + req.query.tainted); // OK. False Positive
}
// with simple assignation
const numberURL = req.query.tainted;
if (validNumber(numberURL)) {
axios.get("test.com/" + numberURL); // OK
}
if (validNumber(numberURL)) {
axios.get("test.com/" + req.query.tainted); // OK. False Positive
}
if (validNumber(req.query.tainted)) {
axios.get("test.com/" + numberURL); // OK. False Positive
}
if (validHexadecimal(req.query.tainted) || validHexaColor(req.query.tainted) ||
validDecimal(req.query.tainted) || validFloat(req.query.tainted) || validInt(req.query.tainted) ||
validNumber(req.query.tainted) || validOctal(req.query.tainted)) {
axios.get("test.com/" + req.query.tainted); // OK. False Positive
}
});
// safe validators
const validAlphanumeric = url => validator.isAlphanumeric(url);
const validAlpha = url => validator.isAlpha(url);
const validDecimal = url => validator.isDecimal(url);
const validFloat = url => validator.isFloat(url);
const validInt = url => validator.isInt(url);
const validNumber = url => validator.isNumeric(url);
const validOctal = url => validator.isOctal(url);
const validHexa = url => validator.isHexadecimal(url) || validator.isHexColor(url);
const validHexadecimal = url => validator.isHexadecimal(url);
const validHexaColor = url => validator.isHexColor(url);
const validUUID = url => validator.isUUID(url);
// unsafe validators
const wrongValidation = url => validator.isByteLength(url, {min:4,max:8});
const isAlphanumeric = url => true;

View File

@@ -0,0 +1,182 @@
const express = require('express');
const app = express();
app.use(express.json());
app.get('/direct-ternary-operator', function (req, res) {
let taintedURL = req.params.url
let v = req.params.url ? req.params.url == "someURL" : false
if (v) {
req_frontend_restclient.get(req.params.url) // OK
}
let v1 = taintedURL ? taintedURL == "someURL" : false
if (v1) {
req_frontend_restclient.get(taintedURL) // OK
}
let v2 = taintedURL ? valid(taintedURL) : false
if (v2) {
req_frontend_restclient.get(taintedURL) // OK
}
let v3 = req.params.url ? valid(req.params.url) : false
if (v3) {
req_frontend_restclient.get(req.params.url) // OK
}
let v4 = req.params.url == undefined ? false : valid(req.params.url)
if (v4) {
req_frontend_restclient.get(req.params.url) // OK
}
let v5 = req.params.url == undefined ? true : valid(req.params.url)
if (v5) {
req_frontend_restclient.get(req.params.url) // SSRF
}
let v6 = req.params.url ? valid(req.params.url) : true
if (v6) {
req_frontend_restclient.get(req.params.url) // SSRF
}
let f = false
let v7 = req.params.url ? valid(req.params.url) : true
if (v7) {
req_frontend_restclient.get(req.params.url) // SSRF
}
let v8 = req.params.url == undefined ? false : valid(req.params.url)
if (!v8) {
return
}
req_frontend_restclient.get(req.params.url) // OK
})
app.get('/functions', function (req, res) {
let taintedURL = req.params.url
if (valid2(taintedURL)) {
req_frontend_restclient.get(taintedURL) // OK
}
if (!invalid(taintedURL)) {
req_frontend_restclient.get(taintedURL) // False positive
}
if (valid2(req.params.url)){
req_frontend_restclient.get(req.params.url) // OK
}
if (!assertAlphanumeric(req.params.url)) {
return
}
req_frontend_restclient.get(req.params.url); // OK
})
app.get('/normal-use-of-ternary-operator', function (req, res) {
let taintedURL = req.params.url
let url = valid(req.params.url) ? req.params.url : undefined
req_frontend_restclient.get(url) // OK
let url = valid(taintedURL) ? taintedURL : undefined
req_frontend_restclient.get(url) // OK
let url4 = req.params.url.match(/^[\w.-]+$/) ? req.params.url : undefined
req_frontend_restclient.get(url4) // OK
})
app.get('/throw-errors', function (req, res) {
req_frontend_restclient.get(valid3(req.params.url)) // False positive
req_frontend_restclient.get(assertOther(req.params.url)); // False positive
req_frontend_restclient.get(assertOther2(req.params.url)); // False positive
});
app.get('/bad-endpoint', function (req, res) {
req_frontend_restclient.get(req.params.url); // SSRF
const valid = req.params.url ? req.params.url == "someURL" : false
if (!valid) {
throw new Error(`Invalid parameter: "${req.params.url}", must be alphanumeric`);
}
req_frontend_restclient.get(req.params.url); // OK
})
app.get('/bad-endpoint-variable', function (req, res) {
let taintedURL = req.params.url
req_frontend_restclient.get(taintedURL); // SSRF
const valid = taintedURL ? taintedURL == "someURL" : false
if (!valid) {
return
}
req_frontend_restclient.get(taintedURL); // False positive
})
app.get('/not-invalid', function (req, res) {
const invalidParam = req.params.url ? !Number.isInteger(req.params.url) : false
if (invalidParam) {
return
}
req_frontend_restclient.get(req.params.url); // False positive
})
app.get('/bad-endpoint-2', function (req, res) {
other(req.params.url)
})
function other(taintedURL) {
req_frontend_restclient.get(taintedURL); // SSRF
const valid = taintedURL ? taintedURL == "someURL" : false
if (!valid) {
return
}
req_frontend_restclient.get(taintedURL); // False positive
}
function assertAlphanumeric(value) {
return value ? value.match(/^[\w.-]+$/) : false;
}
function assertOther(value) {
const valid = value ? !!value.match(/^[\w.-]+$/) : false;
if (!valid) {
throw new Error(`Invalid parameter: "${value}", must be alphanumeric`);
}
return value;
}
function assertOther2(value) {
const valid = value ? value.match(/^[\w.-]+$/) : false;
if (!valid) {
throw new Error(`Invalid parameter: "${value}", must be alphanumeric`);
}
return value;
}
function invalid(value) {
return value ? !Number.isInteger(value) : true
}
function valid(value) {
return value.match(/^[\w.-]+$/)
}
function valid2(value) {
return value ? value == "someURL" : false
}
function valid3(value) {
const valid = value ? value == "someURL" : false
if (!valid) {
throw new Error(`Invalid parameter: "${value}", must be alphanumeric`);
}
return value;
}

View File

@@ -4,5 +4,5 @@ from ClassDefinition class_, FieldDefinition field
where
class_.getAField() = field and
field.isStatic() and
field.getInit().getFirstControlFlowNode().getAPredecessor*() = class_.(ControlFlowNode)
field.getInit().getFirstControlFlowNode().getAPredecessor*() = class_
select field, "Field initializer occurs after its class is created"

View File

@@ -4,4 +4,4 @@ from FunctionWithAnalyzedParameters f, SimpleParameter p, AnalyzedVarDef var
where
f.argumentPassing(p, _) and
var.getAVariable() = p.getVariable()
select p, var.(AnalyzedVarDef).getAnAssignedValue()
select p, var.getAnAssignedValue()

View File

@@ -0,0 +1,8 @@
abstract class Q {
abstract test();
static test() {}
method() {
this.test(); // OK
}
}

View File

@@ -68,6 +68,35 @@ nodes
| json-schema-validator.js:59:22:59:26 | query |
| json-schema-validator.js:61:22:61:26 | query |
| json-schema-validator.js:61:22:61:26 | query |
| ldap.js:20:7:20:34 | q |
| ldap.js:20:11:20:34 | url.par ... , true) |
| ldap.js:20:21:20:27 | req.url |
| ldap.js:20:21:20:27 | req.url |
| ldap.js:22:7:22:33 | username |
| ldap.js:22:18:22:18 | q |
| ldap.js:22:18:22:24 | q.query |
| ldap.js:22:18:22:33 | q.query.username |
| ldap.js:25:13:25:57 | `(\|(nam ... ame}))` |
| ldap.js:25:24:25:31 | username |
| ldap.js:25:46:25:53 | username |
| ldap.js:28:30:28:34 | opts1 |
| ldap.js:28:30:28:34 | opts1 |
| ldap.js:32:5:32:61 | { filte ... e}))` } |
| ldap.js:32:5:32:61 | { filte ... e}))` } |
| ldap.js:32:15:32:59 | `(\|(nam ... ame}))` |
| ldap.js:32:26:32:33 | username |
| ldap.js:32:48:32:55 | username |
| ldap.js:63:9:65:3 | parsedFilter |
| ldap.js:63:24:65:3 | ldap.pa ... ))`\\n ) |
| ldap.js:64:5:64:49 | `(\|(nam ... ame}))` |
| ldap.js:64:16:64:23 | username |
| ldap.js:64:38:64:45 | username |
| ldap.js:66:30:66:53 | { filte ... ilter } |
| ldap.js:66:30:66:53 | { filte ... ilter } |
| ldap.js:66:40:66:51 | parsedFilter |
| ldap.js:68:27:68:42 | `cn=${username}` |
| ldap.js:68:27:68:42 | `cn=${username}` |
| ldap.js:68:33:68:40 | username |
| marsdb-flow-to.js:10:9:10:18 | query |
| marsdb-flow-to.js:10:17:10:18 | {} |
| marsdb-flow-to.js:11:17:11:24 | req.body |
@@ -444,6 +473,37 @@ edges
| json-schema-validator.js:50:23:50:48 | JSON.pa ... y.data) | json-schema-validator.js:50:15:50:48 | query |
| json-schema-validator.js:50:34:50:47 | req.query.data | json-schema-validator.js:50:23:50:48 | JSON.pa ... y.data) |
| json-schema-validator.js:50:34:50:47 | req.query.data | json-schema-validator.js:50:23:50:48 | JSON.pa ... y.data) |
| ldap.js:20:7:20:34 | q | ldap.js:22:18:22:18 | q |
| ldap.js:20:11:20:34 | url.par ... , true) | ldap.js:20:7:20:34 | q |
| ldap.js:20:21:20:27 | req.url | ldap.js:20:11:20:34 | url.par ... , true) |
| ldap.js:20:21:20:27 | req.url | ldap.js:20:11:20:34 | url.par ... , true) |
| ldap.js:22:7:22:33 | username | ldap.js:25:24:25:31 | username |
| ldap.js:22:7:22:33 | username | ldap.js:25:46:25:53 | username |
| ldap.js:22:7:22:33 | username | ldap.js:32:26:32:33 | username |
| ldap.js:22:7:22:33 | username | ldap.js:32:48:32:55 | username |
| ldap.js:22:7:22:33 | username | ldap.js:64:16:64:23 | username |
| ldap.js:22:7:22:33 | username | ldap.js:64:38:64:45 | username |
| ldap.js:22:7:22:33 | username | ldap.js:68:33:68:40 | username |
| ldap.js:22:18:22:18 | q | ldap.js:22:18:22:24 | q.query |
| ldap.js:22:18:22:24 | q.query | ldap.js:22:18:22:33 | q.query.username |
| ldap.js:22:18:22:33 | q.query.username | ldap.js:22:7:22:33 | username |
| ldap.js:25:13:25:57 | `(\|(nam ... ame}))` | ldap.js:28:30:28:34 | opts1 |
| ldap.js:25:13:25:57 | `(\|(nam ... ame}))` | ldap.js:28:30:28:34 | opts1 |
| ldap.js:25:24:25:31 | username | ldap.js:25:13:25:57 | `(\|(nam ... ame}))` |
| ldap.js:25:46:25:53 | username | ldap.js:25:13:25:57 | `(\|(nam ... ame}))` |
| ldap.js:32:15:32:59 | `(\|(nam ... ame}))` | ldap.js:32:5:32:61 | { filte ... e}))` } |
| ldap.js:32:15:32:59 | `(\|(nam ... ame}))` | ldap.js:32:5:32:61 | { filte ... e}))` } |
| ldap.js:32:26:32:33 | username | ldap.js:32:15:32:59 | `(\|(nam ... ame}))` |
| ldap.js:32:48:32:55 | username | ldap.js:32:15:32:59 | `(\|(nam ... ame}))` |
| ldap.js:63:9:65:3 | parsedFilter | ldap.js:66:40:66:51 | parsedFilter |
| ldap.js:63:24:65:3 | ldap.pa ... ))`\\n ) | ldap.js:63:9:65:3 | parsedFilter |
| ldap.js:64:5:64:49 | `(\|(nam ... ame}))` | ldap.js:63:24:65:3 | ldap.pa ... ))`\\n ) |
| ldap.js:64:16:64:23 | username | ldap.js:64:5:64:49 | `(\|(nam ... ame}))` |
| ldap.js:64:38:64:45 | username | ldap.js:64:5:64:49 | `(\|(nam ... ame}))` |
| ldap.js:66:40:66:51 | parsedFilter | ldap.js:66:30:66:53 | { filte ... ilter } |
| ldap.js:66:40:66:51 | parsedFilter | ldap.js:66:30:66:53 | { filte ... ilter } |
| ldap.js:68:33:68:40 | username | ldap.js:68:27:68:42 | `cn=${username}` |
| ldap.js:68:33:68:40 | username | ldap.js:68:27:68:42 | `cn=${username}` |
| marsdb-flow-to.js:10:9:10:18 | query | marsdb-flow-to.js:14:17:14:21 | query |
| marsdb-flow-to.js:10:9:10:18 | query | marsdb-flow-to.js:14:17:14:21 | query |
| marsdb-flow-to.js:10:17:10:18 | {} | marsdb-flow-to.js:10:9:10:18 | query |
@@ -852,6 +912,10 @@ edges
| json-schema-validator.js:55:22:55:26 | query | json-schema-validator.js:50:34:50:47 | req.query.data | json-schema-validator.js:55:22:55:26 | query | This query depends on $@. | json-schema-validator.js:50:34:50:47 | req.query.data | a user-provided value |
| json-schema-validator.js:59:22:59:26 | query | json-schema-validator.js:50:34:50:47 | req.query.data | json-schema-validator.js:59:22:59:26 | query | This query depends on $@. | json-schema-validator.js:50:34:50:47 | req.query.data | a user-provided value |
| json-schema-validator.js:61:22:61:26 | query | json-schema-validator.js:50:34:50:47 | req.query.data | json-schema-validator.js:61:22:61:26 | query | This query depends on $@. | json-schema-validator.js:50:34:50:47 | req.query.data | a user-provided value |
| ldap.js:28:30:28:34 | opts1 | ldap.js:20:21:20:27 | req.url | ldap.js:28:30:28:34 | opts1 | This query depends on $@. | ldap.js:20:21:20:27 | req.url | a user-provided value |
| ldap.js:32:5:32:61 | { filte ... e}))` } | ldap.js:20:21:20:27 | req.url | ldap.js:32:5:32:61 | { filte ... e}))` } | This query depends on $@. | ldap.js:20:21:20:27 | req.url | a user-provided value |
| ldap.js:66:30:66:53 | { filte ... ilter } | ldap.js:20:21:20:27 | req.url | ldap.js:66:30:66:53 | { filte ... ilter } | This query depends on $@. | ldap.js:20:21:20:27 | req.url | a user-provided value |
| ldap.js:68:27:68:42 | `cn=${username}` | ldap.js:20:21:20:27 | req.url | ldap.js:68:27:68:42 | `cn=${username}` | This query depends on $@. | ldap.js:20:21:20:27 | req.url | a user-provided value |
| marsdb-flow-to.js:14:17:14:21 | query | marsdb-flow-to.js:11:17:11:24 | req.body | marsdb-flow-to.js:14:17:14:21 | query | This query depends on $@. | marsdb-flow-to.js:11:17:11:24 | req.body | a user-provided value |
| marsdb.js:16:12:16:16 | query | marsdb.js:13:17:13:24 | req.body | marsdb.js:16:12:16:16 | query | This query depends on $@. | marsdb.js:13:17:13:24 | req.body | a user-provided value |
| minimongo.js:18:12:18:16 | query | minimongo.js:15:17:15:24 | req.body | minimongo.js:18:12:18:16 | query | This query depends on $@. | minimongo.js:15:17:15:24 | req.body | a user-provided value |

View File

@@ -0,0 +1,71 @@
const http = require("http");
const url = require("url");
const ldap = require("ldapjs");
const client = ldap.createClient({
url: "ldap://127.0.0.1:1389",
});
// https://github.com/vesse/node-ldapauth-fork/commit/3feea43e243698bcaeffa904a7324f4d96df60e4
const sanitizeInput = function (input) {
return input
.replace(/\*/g, "\\2a")
.replace(/\(/g, "\\28")
.replace(/\)/g, "\\29")
.replace(/\\/g, "\\5c")
.replace(/\0/g, "\\00")
.replace(/\//g, "\\2f");
};
const server = http.createServer((req, res) => {
let q = url.parse(req.url, true);
let username = q.query.username;
var opts1 = {
filter: `(|(name=${username})(username=${username}))`,
};
client.search("o=example", opts1, function (err, res) {}); // NOT OK
client.search(
"o=example",
{ filter: `(|(name=${username})(username=${username}))` }, // NOT OK
function (err, res) {}
);
// GOOD
client.search(
"o=example",
{ // OK
filter: `(|(name=${sanitizeInput(username)})(username=${sanitizeInput(
username
)}))`,
},
function (err, res) {}
);
// GOOD (https://github.com/ldapjs/node-ldapjs/issues/181)
let f = new OrFilter({
filters: [
new EqualityFilter({
attribute: "name",
value: username,
}),
new EqualityFilter({
attribute: "username",
value: username,
}),
],
});
client.search("o=example", { filter: f }, function (err, res) {});
const parsedFilter = ldap.parseFilter(
`(|(name=${username})(username=${username}))`
);
client.search("o=example", { filter: parsedFilter }, function (err, res) {}); // NOT OK
const dn = ldap.parseDN(`cn=${username}`, function (err, dn) {}); // NOT OK
});
server.listen(389, () => {});

View File

@@ -0,0 +1,20 @@
| tst-httpOnly.js:11:9:15:2 | session ... BAD\\n}) | Sensitive server cookie is missing 'httpOnly' flag. |
| tst-httpOnly.js:29:9:29:21 | session(sess) | Sensitive server cookie is missing 'httpOnly' flag. |
| tst-httpOnly.js:38:9:38:22 | session(sess2) | Sensitive server cookie is missing 'httpOnly' flag. |
| tst-httpOnly.js:47:9:47:22 | session(sess3) | Sensitive server cookie is missing 'httpOnly' flag. |
| tst-httpOnly.js:51:9:55:2 | session ... BAD\\n}) | Sensitive server cookie is missing 'httpOnly' flag. |
| tst-httpOnly.js:68:5:73:10 | res.coo ... }) | Sensitive server cookie is missing 'httpOnly' flag. |
| tst-httpOnly.js:78:5:81:10 | res.coo ... }) | Sensitive server cookie is missing 'httpOnly' flag. |
| tst-httpOnly.js:101:5:101:43 | res.coo ... ptions) | Sensitive server cookie is missing 'httpOnly' flag. |
| tst-httpOnly.js:109:5:109:43 | res.coo ... ptions) | Sensitive server cookie is missing 'httpOnly' flag. |
| tst-httpOnly.js:118:5:118:43 | res.coo ... ptions) | Sensitive server cookie is missing 'httpOnly' flag. |
| tst-httpOnly.js:137:5:137:43 | res.coo ... ptions) | Sensitive server cookie is missing 'httpOnly' flag. |
| tst-httpOnly.js:148:5:148:41 | res.coo ... ptions) | Sensitive server cookie is missing 'httpOnly' flag. |
| tst-httpOnly.js:159:5:159:43 | res.coo ... ptions) | Sensitive server cookie is missing 'httpOnly' flag. |
| tst-httpOnly.js:170:5:170:40 | res.coo ... ptions) | Sensitive server cookie is missing 'httpOnly' flag. |
| tst-httpOnly.js:209:37:209:51 | "authKey=ninja" | Sensitive server cookie is missing 'httpOnly' flag. |
| tst-httpOnly.js:229:38:229:52 | "authKey=ninja" | Sensitive server cookie is missing 'httpOnly' flag. |
| tst-httpOnly.js:289:37:289:59 | `authKe ... {attr}` | Sensitive server cookie is missing 'httpOnly' flag. |
| tst-httpOnly.js:303:9:307:2 | session ... BAD\\n}) | Sensitive server cookie is missing 'httpOnly' flag. |
| tst-httpOnly.js:320:9:324:2 | session ... tter\\n}) | Sensitive server cookie is missing 'httpOnly' flag. |
| tst-httpOnly.js:330:37:330:68 | "sessio ... onKey() | Sensitive server cookie is missing 'httpOnly' flag. |

View File

@@ -0,0 +1 @@
Security/CWE-1004/ClientExposedCookie.ql

View File

@@ -1,20 +0,0 @@
| test_cookie-session.js:12:9:16:2 | session ... BAD\\n}) | Cookie attribute 'HttpOnly' is not set to true for this sensitive cookie. |
| test_cookie-session.js:30:9:30:21 | session(sess) | Cookie attribute 'HttpOnly' is not set to true for this sensitive cookie. |
| test_cookie-session.js:39:9:39:22 | session(sess2) | Cookie attribute 'HttpOnly' is not set to true for this sensitive cookie. |
| test_cookie-session.js:48:9:48:22 | session(sess3) | Cookie attribute 'HttpOnly' is not set to true for this sensitive cookie. |
| test_cookie-session.js:52:9:56:2 | session ... BAD\\n}) | Cookie attribute 'HttpOnly' is not set to true for this sensitive cookie. |
| test_express-session.js:11:9:15:2 | session ... BAD\\n}) | Cookie attribute 'HttpOnly' is not set to true for this sensitive cookie. |
| test_express-session.js:28:9:32:2 | session ... tter\\n}) | Cookie attribute 'HttpOnly' is not set to true for this sensitive cookie. |
| test_httpserver.js:7:37:7:48 | "auth=ninja" | Cookie attribute 'HttpOnly' is not set to true for this sensitive cookie. |
| test_httpserver.js:27:37:27:70 | ["auth= ... cript"] | Cookie attribute 'HttpOnly' is not set to true for this sensitive cookie. |
| test_httpserver.js:57:37:57:80 | ["auth= ... cript"] | Cookie attribute 'HttpOnly' is not set to true for this sensitive cookie. |
| test_httpserver.js:87:37:87:59 | `sessio ... {attr}` | Cookie attribute 'HttpOnly' is not set to true for this sensitive cookie. |
| test_responseCookie.js:15:5:20:10 | res.coo ... }) | Cookie attribute 'HttpOnly' is not set to true for this sensitive cookie. |
| test_responseCookie.js:25:5:28:10 | res.coo ... }) | Cookie attribute 'HttpOnly' is not set to true for this sensitive cookie. |
| test_responseCookie.js:48:5:48:43 | res.coo ... ptions) | Cookie attribute 'HttpOnly' is not set to true for this sensitive cookie. |
| test_responseCookie.js:56:5:56:43 | res.coo ... ptions) | Cookie attribute 'HttpOnly' is not set to true for this sensitive cookie. |
| test_responseCookie.js:65:5:65:43 | res.coo ... ptions) | Cookie attribute 'HttpOnly' is not set to true for this sensitive cookie. |
| test_responseCookie.js:84:5:84:43 | res.coo ... ptions) | Cookie attribute 'HttpOnly' is not set to true for this sensitive cookie. |
| test_responseCookie.js:95:5:95:41 | res.coo ... ptions) | Cookie attribute 'HttpOnly' is not set to true for this sensitive cookie. |
| test_responseCookie.js:106:5:106:43 | res.coo ... ptions) | Cookie attribute 'HttpOnly' is not set to true for this sensitive cookie. |
| test_responseCookie.js:117:5:117:40 | res.coo ... ptions) | Cookie attribute 'HttpOnly' is not set to true for this sensitive cookie. |

View File

@@ -1 +0,0 @@
experimental/Security/CWE-1004/CookieWithoutHttpOnly.ql

View File

@@ -1,56 +0,0 @@
const express = require('express')
const app = express()
const session = require('cookie-session')
const expiryDate = new Date(Date.now() + 60 * 60 * 1000)
app.use(session({
name: 'session',
keys: ['key1', 'key2'],
httpOnly: true, // GOOD
}))
app.use(session({
name: 'session',
keys: ['key1', 'key2'],
httpOnly: false // BAD
}))
app.use(session({
name: 'session',
keys: ['key1', 'key2'],
secure: true // GOOD, httpOnly is true by default
}))
var sess = {
name: 'session',
keys: ['key1', 'key2'],
}
sess.httpOnly = false;
app.use(session(sess)) // BAD
var sess2 = {
name: 'session',
keys: ['key1', 'key2'],
httpOnly: true,
}
sess2.httpOnly = false;
app.use(session(sess2)) // BAD
var sess3 = {
name: 'mycookie',
keys: ['key1', 'key2'],
httpOnly: true,
}
sess3.httpOnly = false;
app.use(session(sess3)) // BAD, It is a session cookie, name doesn't matter
var flag = false
var flag2 = flag
app.use(session({
name: 'session',
keys: ['key1', 'key2'],
httpOnly: flag2 // BAD
}))

View File

@@ -1,32 +0,0 @@
const express = require('express')
const app = express()
const session = require('express-session')
app.use(session({
name: 'session',
keys: ['key1', 'key2'],
cookie: { httpOnly: true }, // GOOD
}))
app.use(session({
name: 'session',
keys: ['key1', 'key2'],
cookie: { httpOnly: false } // BAD
}))
app.use(session({
name: 'session',
keys: ['key1', 'key2'],
cookie: { secure: true } // GOOD, httpOnly is true by default
}))
app.use(session({ // GOOD, httpOnly is true by default
name: 'session',
keys: ['key1', 'key2']
}))
app.use(session({
name: 'mycookie',
keys: ['key1', 'key2'],
cookie: { httpOnly: false } // BAD, It is a session cookie, name doesn't matter
}))

View File

@@ -1,91 +0,0 @@
const http = require('http');
function test1() {
const server = http.createServer((req, res) => {
res.setHeader('Content-Type', 'text/html');
// BAD
res.setHeader("Set-Cookie", "auth=ninja");
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('ok');
});
}
function test2() {
const server = http.createServer((req, res) => {
res.setHeader('Content-Type', 'text/html');
// GOOD
res.setHeader("Set-Cookie", "auth=ninja; HttpOnly");
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('ok');
});
}
function test3() {
const server = http.createServer((req, res) => {
res.setHeader('Content-Type', 'text/html');
// BAD
res.setHeader("Set-Cookie", ["auth=ninja", "token=javascript"]);
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('ok');
});
}
function test4() {
const server = http.createServer((req, res) => {
res.setHeader('Content-Type', 'text/html');
// GOOD
res.setHeader("Set-Cookie", ["auth=ninja; HttpOnly"]);
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('ok');
});
}
function test5() {
const server = http.createServer((req, res) => {
res.setHeader('Content-Type', 'text/html');
// GOOD, case insensitive
res.setHeader("Set-Cookie", ["auth=ninja; httponly"]);
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('ok');
});
}
function test6() {
const server = http.createServer((req, res) => {
res.setHeader('Content-Type', 'text/html');
// BAD
res.setHeader("Set-Cookie", ["auth=ninja; httponly", "token=javascript"]);
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('ok');
});
}
function test7() {
const server = http.createServer((req, res) => {
res.setHeader('Content-Type', 'text/html');
// Good, not auth related
res.setHeader("Set-Cookie", ["foo=ninja", "bar=javascript"]);
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('ok');
});
}
function test8() {
const server = http.createServer((req, res) => {
res.setHeader('Content-Type', 'text/html');
let attr = "; httponly"
res.setHeader("Set-Cookie", `session=ninja ${attr}`); // Good, httponly string expression
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('ok');
});
}
function test9() {
const server = http.createServer((req, res) => {
res.setHeader('Content-Type', 'text/html');
let attr = "; secure"
res.setHeader("Set-Cookie", `session=ninja ${attr}`); // Bad, not httponly string expression
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('ok');
});
}

View File

@@ -1,148 +0,0 @@
const express = require('express')
const app = express()
app.get('/a', function (req, res, next) {
res.cookie('session', 'value',
{
maxAge: 9000000000,
httpOnly: true, // GOOD
secure: false
});
res.end('ok')
})
app.get('/a', function (req, res, next) {
res.cookie('session', 'value',
{
maxAge: 9000000000,
httpOnly: false, // BAD
secure: false
});
res.end('ok')
})
app.get('/a', function (req, res, next) {
res.cookie('session', 'value',
{
maxAge: 9000000000
});
res.end('ok') // BAD
})
app.get('/a', function (req, res, next) {
let options = {
maxAge: 9000000000,
httpOnly: true, // GOOD
secure: false
}
res.cookie('session', 'value', options);
res.end('ok')
})
app.get('/a', function (req, res, next) {
let options = {
maxAge: 9000000000,
httpOnly: false, // BAD
secure: false
}
res.cookie('session', 'value', options);
res.end('ok')
})
app.get('/a', function (req, res, next) {
let options = {
maxAge: 9000000000
}
res.cookie('session', 'value', options); // BAD
res.end('ok')
})
app.get('/a', function (req, res, next) {
let options = {
maxAge: 9000000000
}
options.httpOnly = false;
res.cookie('session', 'value', options); // BAD
res.end('ok')
})
app.get('/a', function (req, res, next) {
let options = {
maxAge: 9000000000
}
options.httpOnly = true;
res.cookie('session', 'value', options); // GOOD
res.end('ok')
})
app.get('/a', function (req, res, next) {
let options = {
maxAge: 9000000000,
httpOnly: false,
}
options.httpOnly = false;
res.cookie('session', 'value', options); // BAD
res.end('ok')
})
app.get('/a', function (req, res, next) {
let options = {
maxAge: 9000000000,
httpOnly: false,
}
options.httpOnly = false;
let session = "blabla"
res.cookie(session, 'value', options); // BAD, var name likely auth related
res.end('ok')
})
app.get('/a', function (req, res, next) {
let options = {
maxAge: 9000000000,
httpOnly: false,
}
options.httpOnly = false;
let o = { session: "blabla" }
res.cookie(o.session, 'value', options); // BAD, var name likely auth related
res.end('ok')
})
app.get('/a', function (req, res, next) {
let options = {
maxAge: 9000000000,
httpOnly: false,
}
options.httpOnly = false;
let blabla = "session"
res.cookie(blabla, 'value', options); // BAD, var name likely auth related
res.end('ok')
})
app.get('/a', function (req, res, next) {
let options = {
maxAge: 9000000000,
httpOnly: true,
}
options.httpOnly = true;
res.cookie('session', 'value', options); // GOOD
res.end('ok')
})
app.get('/a', function (req, res, next) {
let options = {
maxAge: 9000000000,
httpOnly: false,
}
options.httpOnly = true;
res.cookie('session', 'value', options); // GOOD
res.end('ok')
})
app.get('/a', function (req, res, next) {
let options = {
maxAge: 9000000000,
httpOnly: false,
}
res.cookie('mycookie', 'value', options); // GOOD, name likely is not auth sensitive
res.end('ok')
})

View File

@@ -0,0 +1,334 @@
const express = require('express')
const app = express()
const session = require('cookie-session')
app.use(session({
name: 'session',
keys: ['key1', 'key2'],
httpOnly: true, // GOOD
}))
app.use(session({
name: 'session',
keys: ['key1', 'key2'],
httpOnly: false // BAD
}))
app.use(session({
name: 'session',
keys: ['key1', 'key2'],
secure: true // GOOD, httpOnly is true by default
}))
var sess = {
name: 'session',
keys: ['key1', 'key2'],
}
sess.httpOnly = false;
app.use(session(sess)) // BAD
var sess2 = {
name: 'session',
keys: ['key1', 'key2'],
httpOnly: true,
}
sess2.httpOnly = false;
app.use(session(sess2)) // BAD
var sess3 = {
name: 'mycookie',
keys: ['key1', 'key2'],
httpOnly: true,
}
sess3.httpOnly = false;
app.use(session(sess3)) // BAD, It is a session cookie, name doesn't matter
var flag = false
var flag2 = flag
app.use(session({
name: 'session',
keys: ['key1', 'key2'],
httpOnly: flag2 // BAD
}))
app.get('/a', function (req, res, next) {
res.cookie('authkey', 'value',
{
maxAge: 9000000000,
httpOnly: true, // GOOD
secure: false
});
res.end('ok')
})
app.get('/a', function (req, res, next) {
res.cookie('authkey', 'value',
{
maxAge: 9000000000,
httpOnly: false, // BAD
secure: false
});
res.end('ok')
})
app.get('/a', function (req, res, next) {
res.cookie('authkey', 'value',
{
maxAge: 9000000000
});
res.end('ok') // BAD
})
app.get('/a', function (req, res, next) {
let options = {
maxAge: 9000000000,
httpOnly: true, // GOOD
secure: false
}
res.cookie('authkey', 'value', options);
res.end('ok')
})
app.get('/a', function (req, res, next) {
let options = {
maxAge: 9000000000,
httpOnly: false, // BAD
secure: false
}
res.cookie('authkey', 'value', options);
res.end('ok')
})
app.get('/a', function (req, res, next) {
let options = {
maxAge: 9000000000
}
res.cookie('authkey', 'value', options); // BAD
res.end('ok')
})
app.get('/a', function (req, res, next) {
let options = {
maxAge: 9000000000
}
options.httpOnly = false;
res.cookie('authkey', 'value', options); // BAD
res.end('ok')
})
app.get('/a', function (req, res, next) {
let options = {
maxAge: 9000000000
}
options.httpOnly = true;
res.cookie('authkey', 'value', options); // GOOD
res.end('ok')
})
app.get('/a', function (req, res, next) {
let options = {
maxAge: 9000000000,
httpOnly: false,
}
options.httpOnly = false;
res.cookie('authkey', 'value', options); // BAD
res.end('ok')
})
app.get('/a', function (req, res, next) {
let options = {
maxAge: 9000000000,
httpOnly: false,
}
options.httpOnly = false;
let authKey = "blabla"
res.cookie(authKey, 'value', options); // BAD, var name likely auth related
res.end('ok')
})
app.get('/a', function (req, res, next) {
let options = {
maxAge: 9000000000,
httpOnly: false,
}
options.httpOnly = false;
let o = { authKey: "blabla" }
res.cookie(o.authKey, 'value', options); // BAD, var name likely auth related
res.end('ok')
})
app.get('/a', function (req, res, next) {
let options = {
maxAge: 9000000000,
httpOnly: false,
}
options.httpOnly = false;
let blabla = "authKey"
res.cookie(blabla, 'value', options); // BAD, var name likely auth related
res.end('ok')
})
app.get('/a', function (req, res, next) {
let options = {
maxAge: 9000000000,
httpOnly: true,
}
options.httpOnly = true;
res.cookie('authkey', 'value', options); // GOOD
res.end('ok')
})
app.get('/a', function (req, res, next) {
let options = {
maxAge: 9000000000,
httpOnly: false,
}
options.httpOnly = true;
res.cookie('authkey', 'value', options); // GOOD
res.end('ok')
})
app.get('/a', function (req, res, next) {
let options = {
maxAge: 9000000000,
httpOnly: false,
}
res.cookie('mycookie', 'value', options); // GOOD, name likely is not auth sensitive
res.end('ok')
})
const http = require('http');
function test1() {
const server = http.createServer((req, res) => {
res.setHeader('Content-Type', 'text/html');
// BAD
res.setHeader("Set-Cookie", "authKey=ninja");
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('ok');
});
}
function test2() {
const server = http.createServer((req, res) => {
res.setHeader('Content-Type', 'text/html');
// GOOD
res.setHeader("Set-Cookie", "auth=ninja; HttpOnly");
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('ok');
});
}
function test3() {
const server = http.createServer((req, res) => {
res.setHeader('Content-Type', 'text/html');
// BAD
res.setHeader("Set-Cookie", ["authKey=ninja", "token=javascript"]);
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('ok');
});
}
function test4() {
const server = http.createServer((req, res) => {
res.setHeader('Content-Type', 'text/html');
// GOOD
res.setHeader("Set-Cookie", ["auth=ninja; HttpOnly"]);
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('ok');
});
}
function test5() {
const server = http.createServer((req, res) => {
res.setHeader('Content-Type', 'text/html');
// GOOD, case insensitive
res.setHeader("Set-Cookie", ["auth=ninja; httponly"]);
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('ok');
});
}
function test6() {
const server = http.createServer((req, res) => {
res.setHeader('Content-Type', 'text/html');
// OK - the sensitive cookie has httpOnly set
res.setHeader("Set-Cookie", ["authKey=ninja; httponly", "token=javascript"]);
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('ok');
});
}
function test7() {
const server = http.createServer((req, res) => {
res.setHeader('Content-Type', 'text/html');
// Good, not auth related
res.setHeader("Set-Cookie", ["foo=ninja", "bar=javascript"]);
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('ok');
});
}
function test8() {
const server = http.createServer((req, res) => {
res.setHeader('Content-Type', 'text/html');
let attr = "; httponly"
res.setHeader("Set-Cookie", `session=ninja ${attr}`); // Good, httponly string expression
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('ok');
});
}
function test9() {
const server = http.createServer((req, res) => {
res.setHeader('Content-Type', 'text/html');
let attr = "; secure"
res.setHeader("Set-Cookie", `authKey=ninja ${attr}`); // Bad, not httponly string expression
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('ok');
});
}
const session = require('express-session')
app.use(session({
name: 'session',
keys: ['key1', 'key2'],
cookie: { httpOnly: true }, // GOOD
}))
app.use(session({
name: 'session',
keys: ['key1', 'key2'],
cookie: { httpOnly: false } // BAD
}))
app.use(session({
name: 'session',
keys: ['key1', 'key2'],
cookie: { secure: true } // GOOD, httpOnly is true by default
}))
app.use(session({ // GOOD, httpOnly is true by default
name: 'session',
keys: ['key1', 'key2']
}))
app.use(session({
name: 'mycookie',
keys: ['key1', 'key2'],
cookie: { httpOnly: false } // BAD, It is a session cookie, name doesn't matter
}))
const http = require('http');
function test10() {
const server = http.createServer((req, res) => {
res.setHeader('Content-Type', 'text/html');
res.setHeader("Set-Cookie", "sessionKey=" + makeSessionKey()); // BAD
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('ok');
});
}

View File

@@ -0,0 +1,16 @@
| tst-cleartextCookie.js:5:5:10:10 | res.coo ... }) | Sensitive cookie sent without enforcing SSL encryption |
| tst-cleartextCookie.js:20:5:20:43 | res.coo ... ptions) | Sensitive cookie sent without enforcing SSL encryption |
| tst-cleartextCookie.js:35:1:35:52 | js_cook ... alse }) | Sensitive cookie sent without enforcing SSL encryption |
| tst-cleartextCookie.js:44:37:44:51 | "authKey=ninja" | Sensitive cookie sent without enforcing SSL encryption |
| tst-cleartextCookie.js:64:13:64:27 | "authKey=ninja" | Sensitive cookie sent without enforcing SSL encryption |
| tst-cleartextCookie.js:97:13:97:25 | "authKey=foo" | Sensitive cookie sent without enforcing SSL encryption |
| tst-cleartextCookie.js:108:9:111:2 | session ... T OK\\n}) | Sensitive cookie sent without enforcing SSL encryption |
| tst-cleartextCookie.js:113:9:116:2 | session ... T OK\\n}) | Sensitive cookie sent without enforcing SSL encryption |
| tst-cleartextCookie.js:118:9:121:2 | session ... T OK\\n}) | Sensitive cookie sent without enforcing SSL encryption |
| tst-cleartextCookie.js:128:9:128:21 | session(sess) | Sensitive cookie sent without enforcing SSL encryption |
| tst-cleartextCookie.js:152:9:160:2 | session ... Date\\n}) | Sensitive cookie sent without enforcing SSL encryption |
| tst-cleartextCookie.js:164:33:164:58 | `authKe ... key()}` | Sensitive cookie sent without enforcing SSL encryption |
| tst-cleartextCookie.js:177:5:177:19 | document.cookie | Sensitive cookie sent without enforcing SSL encryption |
| tst-cleartextCookie.js:181:5:181:41 | cookies ... hkey()) | Sensitive cookie sent without enforcing SSL encryption |
| tst-cleartextCookie.js:186:5:186:46 | cookie. ... hkey()) | Sensitive cookie sent without enforcing SSL encryption |
| tst-cleartextCookie.js:195:33:195:74 | cookie. ... hkey()) | Sensitive cookie sent without enforcing SSL encryption |

View File

@@ -0,0 +1 @@
Security/CWE-614/ClearTextCookie.ql

View File

@@ -1,11 +0,0 @@
| test_cookie-session.js:16:9:24:2 | session ... Date\\n}) | Cookie is added to response without the 'secure' flag being set to true |
| test_express-session.js:5:9:8:2 | session ... T OK\\n}) | Cookie is added to response without the 'secure' flag being set to true |
| test_express-session.js:10:9:13:2 | session ... T OK\\n}) | Cookie is added to response without the 'secure' flag being set to true |
| test_express-session.js:15:9:18:2 | session ... T OK\\n}) | Cookie is added to response without the 'secure' flag being set to true |
| test_express-session.js:25:9:25:21 | session(sess) | Cookie is added to response without the 'secure' flag being set to true |
| test_httpserver.js:7:37:7:48 | "type=ninja" | Cookie is added to response without the 'secure' flag being set to true |
| test_httpserver.js:27:37:27:73 | ["type= ... cript"] | Cookie is added to response without the 'secure' flag being set to true |
| test_httpserver.js:57:37:57:81 | ["type= ... cript"] | Cookie is added to response without the 'secure' flag being set to true |
| test_jscookie.js:2:1:2:48 | js_cook ... alse }) | Cookie is added to response without the 'secure' flag being set to true |
| test_responseCookie.js:5:5:10:10 | res.coo ... }) | Cookie is added to response without the 'secure' flag being set to true |
| test_responseCookie.js:20:5:20:40 | res.coo ... ptions) | Cookie is added to response without the 'secure' flag being set to true |

View File

@@ -1 +0,0 @@
experimental/Security/CWE-614/InsecureCookie.ql

View File

@@ -1,24 +0,0 @@
const express = require('express')
const app = express()
const session = require('cookie-session')
const expiryDate = new Date(Date.now() + 60 * 60 * 1000)
app.use(session({
name: 'session',
keys: ['key1', 'key2'],
secure: true, // OK
httpOnly: true,
domain: 'example.com',
path: 'foo/bar',
expires: expiryDate
}))
app.use(session({
name: 'session',
keys: ['key1', 'key2'],
secure: false, // NOT OK
httpOnly: true,
domain: 'example.com',
path: 'foo/bar',
expires: expiryDate
}))

View File

@@ -1,33 +0,0 @@
const express = require('express')
const app = express()
const session = require('express-session')
app.use(session({
secret: 'secret',
cookie: { secure: false } // NOT OK
}))
app.use(session({
secret: 'secret'
// NOT OK
}))
app.use(session({
secret: 'secret',
cookie: {} // NOT OK
}))
const sess = {
secret: 'secret',
cookie: { secure: false } // NOT OK
}
app.use(session(sess))
app.set('trust proxy', 1)
app.use(session({
secret: 'secret',
cookie: { secure: true } // OK
}))

View File

@@ -1,61 +0,0 @@
const http = require('http');
function test1() {
const server = http.createServer((req, res) => {
res.setHeader('Content-Type', 'text/html');
// BAD
res.setHeader("Set-Cookie", "type=ninja");
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('ok');
});
}
function test2() {
const server = http.createServer((req, res) => {
res.setHeader('Content-Type', 'text/html');
// GOOD
res.setHeader("Set-Cookie", "type=ninja; Secure");
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('ok');
});
}
function test3() {
const server = http.createServer((req, res) => {
res.setHeader('Content-Type', 'text/html');
// BAD
res.setHeader("Set-Cookie", ["type=ninja", "language=javascript"]);
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('ok');
});
}
function test4() {
const server = http.createServer((req, res) => {
res.setHeader('Content-Type', 'text/html');
// GOOD
res.setHeader("Set-Cookie", ["type=ninja; Secure"]);
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('ok');
});
}
function test5() {
const server = http.createServer((req, res) => {
res.setHeader('Content-Type', 'text/html');
// GOOD, case insensitive
res.setHeader("Set-Cookie", ["type=ninja; secure"]);
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('ok');
});
}
function test6() {
const server = http.createServer((req, res) => {
res.setHeader('Content-Type', 'text/html');
// BAD
res.setHeader("Set-Cookie", ["type=ninja; secure", "language=javascript"]);
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('ok');
});
}

View File

@@ -1,3 +0,0 @@
const js_cookie = require('js-cookie')
js_cookie.set('key', 'value', { secure: false }); // NOT OK
js_cookie.set('key', 'value', { secure: true }); // OK

View File

@@ -1,33 +0,0 @@
const express = require('express')
const app = express()
app.get('/a', function (req, res, next) {
res.cookie('name', 'value',
{
maxAge: 9000000000,
httpOnly: true,
secure: false // NOT OK
});
res.end('ok')
})
app.get('/b', function (req, res, next) {
let options = {
maxAge: 9000000000,
httpOnly: true,
secure: false // NOT OK
}
res.cookie('name', 'value', options);
res.end('ok')
})
app.get('/c', function (req, res, next) {
res.cookie('name', 'value',
{
maxAge: 9000000000,
httpOnly: true,
secure: true // OK
});
res.end('ok')
})

View File

@@ -0,0 +1,213 @@
const express = require('express')
const app = express()
app.get('/a', function (req, res, next) {
res.cookie('authkey', 'value',
{
maxAge: 9000000000,
httpOnly: true,
secure: false // NOT OK
});
res.end('ok')
})
app.get('/b', function (req, res, next) {
let options = {
maxAge: 9000000000,
httpOnly: true,
secure: false // NOT OK
}
res.cookie('authKey', 'value', options);
res.end('ok')
})
app.get('/c', function (req, res, next) {
res.cookie('name', 'value',
{
maxAge: 9000000000,
httpOnly: true,
secure: true // OK
});
res.end('ok')
})
const js_cookie = require('js-cookie')
js_cookie.set('authKey', 'value', { secure: false }); // NOT OK
js_cookie.set('authKey', 'value', { secure: true }); // OK
const http = require('http');
function test1() {
const server = http.createServer((req, res) => {
res.setHeader('Content-Type', 'text/html');
// BAD
res.setHeader("Set-Cookie", "authKey=ninja");
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('ok');
});
}
function test2() {
const server = http.createServer((req, res) => {
res.setHeader('Content-Type', 'text/html');
// GOOD
res.setHeader("Set-Cookie", "type=ninja; Secure");
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('ok');
});
}
function test3() {
const server = http.createServer((req, res) => {
res.setHeader('Content-Type', 'text/html');
res.setHeader("Set-Cookie", [
"authKey=ninja", // NOT OK
"language=javascript" // OK
]);
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('ok');
});
}
function test4() {
const server = http.createServer((req, res) => {
res.setHeader('Content-Type', 'text/html');
// GOOD
res.setHeader("Set-Cookie", ["type=ninja; Secure"]);
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('ok');
});
}
function test5() {
const server = http.createServer((req, res) => {
res.setHeader('Content-Type', 'text/html');
// GOOD, case insensitive
res.setHeader("Set-Cookie", ["type=ninja; secure"]);
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('ok');
});
}
function test6() {
const server = http.createServer((req, res) => {
res.setHeader('Content-Type', 'text/html');
res.setHeader("Set-Cookie", [
"type=ninja; secure", // OK
"authKey=foo" // NOT OK
]);
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('ok');
});
}
const express = require('express')
const app = express()
const session = require('express-session')
app.use(session({
secret: 'secret',
cookie: { secure: false } // NOT OK
}))
app.use(session({
secret: 'secret'
// NOT OK
}))
app.use(session({
secret: 'secret',
cookie: {} // NOT OK
}))
const sess = {
secret: 'secret',
cookie: { secure: false } // NOT OK
}
app.use(session(sess))
app.set('trust proxy', 1)
app.use(session({
secret: 'secret',
cookie: { secure: true } // OK
}))
const express = require('express')
const app = express()
const session = require('cookie-session')
const expiryDate = new Date(Date.now() + 60 * 60 * 1000)
app.use(session({
name: 'session',
keys: ['key1', 'key2'],
secure: true, // OK
httpOnly: true,
domain: 'example.com',
path: 'foo/bar',
expires: expiryDate
}))
app.use(session({
name: 'session',
keys: ['key1', 'key2'],
secure: false, // NOT OK
httpOnly: true,
domain: 'example.com',
path: 'foo/bar',
expires: expiryDate
}))
http.createServer((req, res) => {
res.setHeader('Content-Type', 'text/html');
res.setHeader("Set-Cookie", `authKey=${makeAuthkey()}`); // NOT OK
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('ok');
});
http.createServer((req, res) => {
res.setHeader("Set-Cookie", `authKey=${makeAuthkey()}; secure; httpOnly`); // OK
res.writeHead(200, { 'Content-Type': 'text/html' });
res.end('<h2>Hello world</h2>');
});
function clientCookies() {
document.cookie = `authKey=${makeAuthkey()}; secure`; // OK
document.cookie = `authKey=${makeAuthkey()}`; // NOT OK
var cookies = require('browser-cookies');
cookies.set('authKey', makeAuthkey()); // NOT OK
cookies.set('authKey', makeAuthkey(), { secure: true, expires: 7 }); // OK
const cookie = require('cookie');
cookie.serialize('authKey', makeAuthkey()); // NOT OK
cookie.serialize('authKey', makeAuthkey(), { secure: true, expires: 7 }); // OK
}
const cookie = require('cookie');
http.createServer((req, res) => {
res.setHeader('Content-Type', 'text/html');
res.setHeader("Set-Cookie", cookie.serialize("authKey", makeAuthkey(), {secure: true,httpOnly: true})); // OK
res.setHeader("Set-Cookie", cookie.serialize("authKey", makeAuthkey())); // NOT OK
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('ok');
});
(function mightBeSecures() {
const express = require('express')
const app = express()
const session = require('express-session')
app.use(session({
secret: config.sessionSecret,
cookie: {
httpOnly: config.sessionCookie.httpOnly,
secure: config.sessionCookie.secure && config.secure.ssl
},
name: config.sessionKey
}));
})();

View File

@@ -23,6 +23,16 @@ nodes
| tst.js:45:9:45:11 | obj |
| tst.js:48:9:48:11 | obj |
| tst.js:48:9:48:11 | obj |
| tst.js:78:5:78:37 | obj[req ... ', '')] |
| tst.js:78:5:78:37 | obj[req ... ', '')] |
| tst.js:78:9:78:19 | req.query.x |
| tst.js:78:9:78:19 | req.query.x |
| tst.js:78:9:78:36 | req.que ... _', '') |
| tst.js:81:5:81:46 | obj[req ... g, '')] |
| tst.js:81:5:81:46 | obj[req ... g, '')] |
| tst.js:81:9:81:19 | req.query.x |
| tst.js:81:9:81:19 | req.query.x |
| tst.js:81:9:81:45 | req.que ... /g, '') |
edges
| tst.js:5:9:5:38 | taint | tst.js:8:12:8:16 | taint |
| tst.js:5:9:5:38 | taint | tst.js:9:12:9:16 | taint |
@@ -47,6 +57,14 @@ edges
| tst.js:33:23:33:25 | obj | tst.js:45:9:45:11 | obj |
| tst.js:33:23:33:25 | obj | tst.js:48:9:48:11 | obj |
| tst.js:33:23:33:25 | obj | tst.js:48:9:48:11 | obj |
| tst.js:78:9:78:19 | req.query.x | tst.js:78:9:78:36 | req.que ... _', '') |
| tst.js:78:9:78:19 | req.query.x | tst.js:78:9:78:36 | req.que ... _', '') |
| tst.js:78:9:78:36 | req.que ... _', '') | tst.js:78:5:78:37 | obj[req ... ', '')] |
| tst.js:78:9:78:36 | req.que ... _', '') | tst.js:78:5:78:37 | obj[req ... ', '')] |
| tst.js:81:9:81:19 | req.query.x | tst.js:81:9:81:45 | req.que ... /g, '') |
| tst.js:81:9:81:19 | req.query.x | tst.js:81:9:81:45 | req.que ... /g, '') |
| tst.js:81:9:81:45 | req.que ... /g, '') | tst.js:81:5:81:46 | obj[req ... g, '')] |
| tst.js:81:9:81:45 | req.que ... /g, '') | tst.js:81:5:81:46 | obj[req ... g, '')] |
#select
| tst.js:8:5:8:17 | object[taint] | tst.js:5:24:5:37 | req.query.data | tst.js:8:5:8:17 | object[taint] | This assignment may alter Object.prototype if a malicious '__proto__' string is injected from $@. | tst.js:5:24:5:37 | req.query.data | here |
| tst.js:9:5:9:17 | object[taint] | tst.js:5:24:5:37 | req.query.data | tst.js:9:5:9:17 | object[taint] | This assignment may alter Object.prototype if a malicious '__proto__' string is injected from $@. | tst.js:5:24:5:37 | req.query.data | here |
@@ -55,3 +73,5 @@ edges
| tst.js:39:9:39:11 | obj | tst.js:5:24:5:37 | req.query.data | tst.js:39:9:39:11 | obj | This assignment may alter Object.prototype if a malicious '__proto__' string is injected from $@. | tst.js:5:24:5:37 | req.query.data | here |
| tst.js:45:9:45:11 | obj | tst.js:5:24:5:37 | req.query.data | tst.js:45:9:45:11 | obj | This assignment may alter Object.prototype if a malicious '__proto__' string is injected from $@. | tst.js:5:24:5:37 | req.query.data | here |
| tst.js:48:9:48:11 | obj | tst.js:5:24:5:37 | req.query.data | tst.js:48:9:48:11 | obj | This assignment may alter Object.prototype if a malicious '__proto__' string is injected from $@. | tst.js:5:24:5:37 | req.query.data | here |
| tst.js:78:5:78:37 | obj[req ... ', '')] | tst.js:78:9:78:19 | req.query.x | tst.js:78:5:78:37 | obj[req ... ', '')] | This assignment may alter Object.prototype if a malicious '__proto__' string is injected from $@. | tst.js:78:9:78:19 | req.query.x | here |
| tst.js:81:5:81:46 | obj[req ... g, '')] | tst.js:81:9:81:19 | req.query.x | tst.js:81:5:81:46 | obj[req ... g, '')] | This assignment may alter Object.prototype if a malicious '__proto__' string is injected from $@. | tst.js:81:9:81:19 | req.query.x | here |

View File

@@ -71,3 +71,13 @@ class Box {
this.foo = 'bar'; // OK - 'this' won't refer to Object.prototype
}
}
app.get('/foo', (req, res) => {
let obj = {};
obj[req.query.x.replace('_', '-')].x = 'foo'; // OK
obj[req.query.x.replace('_', '')].x = 'foo'; // NOT OK
obj[req.query.x.replace(/_/g, '')].x = 'foo'; // OK
obj[req.query.x.replace(/_/g, '-')].x = 'foo'; // OK
obj[req.query.x.replace(/__proto__/g, '')].x = 'foo'; // NOT OK - "__pr__proto__oto__"
obj[req.query.x.replace('o', '0')].x = 'foo'; // OK
});