@contrast/protect 1.2.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/lib/cli-rewriter.js +15 -0
  2. package/lib/error-handlers/constants.js +15 -0
  3. package/lib/error-handlers/index.js +17 -0
  4. package/lib/error-handlers/install/express4.js +90 -0
  5. package/lib/error-handlers/install/fastify3.js +15 -0
  6. package/lib/error-handlers/install/koa2.js +15 -0
  7. package/lib/esm-loader.mjs +15 -0
  8. package/lib/index.d.ts +145 -19
  9. package/lib/index.js +15 -0
  10. package/lib/input-analysis/constants.js +20 -0
  11. package/lib/input-analysis/handlers.js +33 -10
  12. package/lib/input-analysis/index.js +36 -3
  13. package/lib/input-analysis/install/body-parser1.js +130 -0
  14. package/lib/input-analysis/install/cookie-parser1.js +82 -0
  15. package/lib/input-analysis/install/express4.js +108 -0
  16. package/lib/input-analysis/install/fastify3.js +47 -19
  17. package/lib/input-analysis/install/formidable1.js +73 -0
  18. package/lib/input-analysis/install/http.js +18 -1
  19. package/lib/input-analysis/install/koa-body5.js +68 -0
  20. package/lib/input-analysis/install/koa-bodyparser4.js +68 -0
  21. package/lib/input-analysis/install/koa2.js +26 -25
  22. package/lib/input-analysis/install/multer1.js +89 -0
  23. package/lib/input-analysis/install/qs6.js +61 -0
  24. package/lib/input-analysis/install/universal-cookie4.js +56 -0
  25. package/lib/input-tracing/constants.js +15 -0
  26. package/lib/input-tracing/handlers/index.js +154 -59
  27. package/lib/input-tracing/index.js +17 -0
  28. package/lib/input-tracing/install/child-process.js +16 -1
  29. package/lib/input-tracing/install/fs.js +17 -2
  30. package/lib/input-tracing/install/mongodb.js +233 -0
  31. package/lib/input-tracing/install/mysql.js +18 -2
  32. package/lib/input-tracing/install/postgres.js +15 -0
  33. package/lib/input-tracing/install/sequelize.js +15 -0
  34. package/lib/input-tracing/install/sqlite3.js +15 -0
  35. package/lib/make-response-blocker.js +15 -0
  36. package/lib/make-source-context.js +18 -0
  37. package/lib/security-exception.js +15 -0
  38. package/lib/throw-security-exception.js +17 -6
  39. package/lib/utils.js +14 -18
  40. package/package.json +7 -7
  41. package/lib/input-analysis/install/co-body.js +0 -51
  42. package/lib/input-analysis/install/cookie-parser.js +0 -48
  43. package/lib/input-analysis/install/formidable.js +0 -53
  44. package/lib/input-analysis/install/multer.js +0 -52
  45. package/lib/input-analysis/install/qs.js +0 -40
  46. package/lib/input-analysis/install/universal-cookie.js +0 -34
  47. package/lib/input-tracing/handlers/nosql-injection-mongo.js +0 -48
@@ -1,53 +0,0 @@
1
- 'use strict';
2
-
3
- module.exports = (core) => {
4
- const {
5
- depHooks,
6
- patcher,
7
- logger,
8
- scopes: { sources },
9
- protect: { inputAnalysis },
10
- } = core;
11
-
12
- return {
13
- // Patch `formidable`
14
- install() {
15
- depHooks.resolve({ name: 'formidable' }, (formidable) => {
16
- formidable.IncomingForm.prototype.parse = patcher.patch(formidable.IncomingForm.prototype.parse, {
17
- name: 'Formidable.IncomingForm.prototype.parse',
18
- patchType: 'framework-patch',
19
- pre(data) {
20
- const origCb = data.args[1];
21
-
22
- function hookedCb(...cbArgs) {
23
- const sourceContext = sources.getStore()?.protect;
24
- const [, fields, files] = cbArgs;
25
-
26
- if (!sourceContext) {
27
- logger.debug('source context not available in `formidable` hook');
28
- } else {
29
- if (fields) {
30
- sourceContext.parsedBody = fields;
31
- inputAnalysis.handleParsedBody(sourceContext, fields);
32
- }
33
- if (files) {
34
- logger.debug('Check for vulnerable filename upload nyi');
35
- // CHECK FILENAME - NYI
36
- }
37
- }
38
-
39
- if (origCb && typeof origCb === 'function') {
40
- // Should we explicitly run in the current source context?
41
- origCb.apply(this, cbArgs);
42
- }
43
- }
44
-
45
- data.args[1] = hookedCb;
46
- }
47
- });
48
-
49
- return formidable;
50
- });
51
- }
52
- };
53
- };
@@ -1,52 +0,0 @@
1
- 'use strict';
2
-
3
- module.exports = (core) => {
4
- const {
5
- depHooks,
6
- patcher,
7
- logger,
8
- scopes: { sources },
9
- protect: { inputAnalysis },
10
- } = core;
11
-
12
- return {
13
- // Patch `multer`
14
- install() {
15
- depHooks.resolve({ name: 'multer', file: 'lib/make-middleware.js' }, (multerMakeMiddleware) => patcher.patch(multerMakeMiddleware, {
16
- name: 'multer.make-middleware',
17
- patchType: 'framework-patch',
18
- post(data) {
19
- data.result = patcher.patch(data.result, {
20
- name: 'multerMiddleware',
21
- patchType: 'framework-patch',
22
- pre(data) {
23
- const [req, , origNext] = data.args;
24
-
25
- async function contrastNext() {
26
-
27
- const sourceContext = sources.getStore()?.protect;
28
-
29
- if (!sourceContext) {
30
- logger.debug('source context not available in `multer` hook');
31
- } else {
32
- if (req.body) {
33
- sourceContext.parsedBody = req.body;
34
- inputAnalysis.handleParsedBody(sourceContext, req.body);
35
- }
36
- if (req.file || req.files) {
37
- logger.debug('Check for vulnerable filename upload nyi');
38
- // CHECK FILENAME - NYI
39
- }
40
- }
41
-
42
- await origNext();
43
- }
44
-
45
- data.args[2] = contrastNext;
46
- }
47
- });
48
- }
49
- }));
50
- }
51
- };
52
- };
@@ -1,40 +0,0 @@
1
- 'use strict';
2
-
3
- module.exports = (core) => {
4
- const {
5
- depHooks,
6
- patcher,
7
- logger,
8
- scopes: { sources },
9
- protect: { inputAnalysis },
10
- } = core;
11
-
12
- return {
13
- // Patch `qs`
14
- install() {
15
- depHooks.resolve({ name: 'qs' },
16
- (qs) => patcher.patch(qs, 'parse', {
17
- name: 'qs',
18
- patchType: 'framework-patch',
19
- post({ args, result }) {
20
- if (result && Object.keys(result).length) {
21
- const sourceContext = sources.getStore()?.protect;
22
-
23
- if (!sourceContext) {
24
- logger.debug('source context not available in `qs` hook');
25
-
26
- // We need to run analysis for the `qs` result only when it's used as a query parser.
27
- // `qs` is used also for parsing bodies, but these cases we handle individually with
28
- // the respective library that's using it (e.g. `formidable`, `co-body`) because in
29
- // some cases its use is optional and we cannot rely on it.
30
- } else if (sourceContext.reqData?.queries === args[0]) {
31
- sourceContext.parsedQuery = result;
32
- inputAnalysis.handleQueryParams(sourceContext, result);
33
- }
34
- }
35
- }
36
- })
37
- );
38
- }
39
- };
40
- };
@@ -1,34 +0,0 @@
1
- 'use strict';
2
-
3
- module.exports = (core) => {
4
- const {
5
- depHooks,
6
- patcher,
7
- logger,
8
- scopes: { sources },
9
- protect: { inputAnalysis },
10
- } = core;
11
-
12
- return {
13
- // Patch `universal-cookie` package
14
- install() {
15
- depHooks.resolve({ name: 'universal-cookie', file: 'cjs/utils.js' }, (uCookieUtils) => patcher.patch(uCookieUtils, 'parseCookies', {
16
- name: 'universal-cookie.utils',
17
- patchType: 'framework-patch',
18
- post({ result }) {
19
- if (result && Object.keys(result).length) {
20
- const sourceContext = sources.getStore()?.protect;
21
-
22
- if (!sourceContext) {
23
- logger.debug('source context not available in `universal-cookie` hook');
24
- } else {
25
- sourceContext.parsedCookies = result;
26
- inputAnalysis.handleCookies(sourceContext, result);
27
- }
28
- }
29
- }
30
- })
31
- );
32
- }
33
- };
34
- };
@@ -1,48 +0,0 @@
1
- 'use strict';
2
-
3
- /* c8 ignore start */
4
- // this is just the general structure of how to handle mongo sinks
5
- const util = require('util');
6
-
7
- const { simpleTraverse } = require('../../utils');
8
-
9
- function mongoSink(results, sinkContext) {
10
- if (typeof sinkContext.value === 'object') {
11
- return handleObjectValue(results, sinkContext.value);
12
- } else if (typeof sinkContext.value === 'string') {
13
- return handleStringValue(results, sinkContext.value);
14
- }
15
-
16
- return null;
17
- }
18
-
19
- function handleObjectValue(results, object) {
20
- for (const result of results) {
21
- simpleTraverse(object, function(path, type, value) {
22
- if (type !== 'Key') {
23
- return;
24
- }
25
- // the result value is the key that was found
26
- if (result.value === value) {
27
- // does the object at this path equal the user input?
28
- let obj = object;
29
- for (const p of path) {
30
- obj = obj[p];
31
- }
32
- obj = obj[value];
33
- // does the found object in the query equal the saved object?
34
- if (util.isDeepStrictEqual(obj, object)) {
35
- //
36
- }
37
- }
38
- });
39
- }
40
- }
41
-
42
- function handleStringValue(results, string) {
43
- // nyi
44
- }
45
-
46
- module.exports = mongoSink;
47
-
48
- /* c8 ignore stop */