@appland/scanner 1.70.2 → 1.70.4
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.
- package/CHANGELOG.md +15 -0
- package/built/algorithms/hash/hashV1.js +42 -2
- package/built/cli/scan/watchScan.js +1 -1
- package/built/configuration/schema/options.json +8 -2
- package/built/rules/jwtAlgorithmNone.js +13 -1
- package/built/rules/jwtUnverifiedSignature.js +6 -0
- package/built/rules/too-many-joins/options.js +1 -1
- package/doc/labels/jwt.decode.md +7 -0
- package/doc/labels/jwt.encode.md +7 -0
- package/doc/labels/jwt.signature.verify.md +7 -0
- package/doc/rules/jwt-algorithm-none.md +6 -0
- package/doc/rules/jwt-unverified-signature.md +7 -0
- package/package.json +3 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,18 @@
|
|
|
1
|
+
# [@appland/scanner-v1.70.4](https://github.com/getappmap/appmap-js/compare/@appland/scanner-v1.70.3...@appland/scanner-v1.70.4) (2022-09-27)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* Add excludeTables option for too-many-joins ([ad8b97d](https://github.com/getappmap/appmap-js/commit/ad8b97d4ca47ea7a6a0c9fc31560a42351ba0b94))
|
|
7
|
+
* Add missing JWT algorithm docs ([328f0a7](https://github.com/getappmap/appmap-js/commit/328f0a7e14e419a843c8deb4efd7b2cc56ddad8b))
|
|
8
|
+
|
|
9
|
+
# [@appland/scanner-v1.70.3](https://github.com/applandinc/appmap-js/compare/@appland/scanner-v1.70.2...@appland/scanner-v1.70.3) (2022-09-21)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
### Bug Fixes
|
|
13
|
+
|
|
14
|
+
* Scan existing files in scan --watch ([3a3138d](https://github.com/applandinc/appmap-js/commit/3a3138d2018e0ff96eed68e1125eb99fc2cb98f1)), closes [#727](https://github.com/applandinc/appmap-js/issues/727)
|
|
15
|
+
|
|
1
16
|
# [@appland/scanner-v1.70.2](https://github.com/applandinc/appmap-js/compare/@appland/scanner-v1.70.1...@appland/scanner-v1.70.2) (2022-09-19)
|
|
2
17
|
|
|
3
18
|
|
|
@@ -1,10 +1,50 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const models_1 = require("@appland/models");
|
|
7
|
+
const sha256_1 = __importDefault(require("crypto-js/sha256"));
|
|
8
|
+
const assert_1 = __importDefault(require("assert"));
|
|
3
9
|
const crypto_1 = require("crypto");
|
|
10
|
+
// BEGIN COMMENT
|
|
11
|
+
// Moved here from packages/models, in order to retain backwards compatibility with Hash v1
|
|
12
|
+
// as the Event algoritms hash and identityHash are updated.
|
|
13
|
+
function qualifiedMethodId(event) {
|
|
14
|
+
const { definedClass, isStatic, methodId } = event;
|
|
15
|
+
(0, assert_1.default)(definedClass, 'Event.definedClass');
|
|
16
|
+
return `${definedClass}${isStatic ? '.' : '#'}${methodId}`;
|
|
17
|
+
}
|
|
18
|
+
// Returns a string suitable for durable identification of a call event
|
|
19
|
+
// that's independent of parameters and return values.
|
|
20
|
+
// For SQL queries, it's a JSON of abstract query AST.
|
|
21
|
+
// For HTTP queries, it's the method plus normalized path info.
|
|
22
|
+
// For function calls it's the qualified function id.
|
|
23
|
+
// TODO: This can be removed/deprecated when the current hash algorithm is removed.
|
|
24
|
+
function callEventToString(event) {
|
|
25
|
+
const { sqlQuery, route } = event;
|
|
26
|
+
if (sqlQuery)
|
|
27
|
+
return (0, models_1.abstractSqlAstJSON)(sqlQuery, event.sql.database_type);
|
|
28
|
+
if (route)
|
|
29
|
+
return route;
|
|
30
|
+
return qualifiedMethodId(event);
|
|
31
|
+
}
|
|
32
|
+
// Returns a short string (hash) suitable for durable identification
|
|
33
|
+
// of a call event that's independent of parameters and return values.
|
|
34
|
+
// For SQL queries, it considers the abstract query (ignoring differences in literal values).
|
|
35
|
+
// For HTTP queries, it considers the method plus normalized path info.
|
|
36
|
+
// For function calls it's the qualified function id.
|
|
37
|
+
// Non-call events will throw an error.
|
|
38
|
+
function hashEvent(event) {
|
|
39
|
+
if (event.event !== 'call')
|
|
40
|
+
throw new Error('tried to hash a non-call event');
|
|
41
|
+
return (0, sha256_1.default)(callEventToString(event)).toString();
|
|
42
|
+
}
|
|
43
|
+
// END COMMENT
|
|
4
44
|
class HashV1 {
|
|
5
45
|
constructor(ruleId, findingEvent, relatedEvents) {
|
|
6
46
|
this.hash = (0, crypto_1.createHash)('sha256');
|
|
7
|
-
this.hash.update(findingEvent
|
|
47
|
+
this.hash.update(hashEvent(findingEvent));
|
|
8
48
|
this.hash.update(ruleId);
|
|
9
49
|
// Admittedly odd, this implementation matches the original hash algorithm.
|
|
10
50
|
const uniqueEvents = new Set();
|
|
@@ -18,7 +58,7 @@ class HashV1 {
|
|
|
18
58
|
});
|
|
19
59
|
// This part where the hashes go into a Set, and there is some kind of ordering as a side-
|
|
20
60
|
// effect, is particularly weird.
|
|
21
|
-
new Set(hashEvents.map((e) => e
|
|
61
|
+
new Set(hashEvents.map((e) => hashEvent(e))).forEach((eventHash) => {
|
|
22
62
|
this.hash.update(eventHash);
|
|
23
63
|
});
|
|
24
64
|
}
|
|
@@ -61,7 +61,7 @@ class Watcher {
|
|
|
61
61
|
// Chokidar struggles with relative paths. Make sure the watch pattern is absolute.
|
|
62
62
|
const watchPattern = path_1.default.resolve(this.options.appmapDir, '**', 'mtime');
|
|
63
63
|
this.appmapWatcher = chokidar.watch(watchPattern, {
|
|
64
|
-
ignoreInitial:
|
|
64
|
+
ignoreInitial: false,
|
|
65
65
|
});
|
|
66
66
|
this.appmapWatcher
|
|
67
67
|
.on('add', (filePath) => this.scan(filePath))
|
|
@@ -173,12 +173,18 @@
|
|
|
173
173
|
},
|
|
174
174
|
"TooManyJoins.Options": {
|
|
175
175
|
"type": "object",
|
|
176
|
-
"additionalProperties": false,
|
|
177
176
|
"properties": {
|
|
178
177
|
"warningLimit": {
|
|
179
178
|
"type": "number"
|
|
179
|
+
},
|
|
180
|
+
"excludeTables": {
|
|
181
|
+
"type": "array",
|
|
182
|
+
"items": {
|
|
183
|
+
"$ref": "https://appland.com/schemas/scanner/match-pattern-config.json"
|
|
184
|
+
}
|
|
180
185
|
}
|
|
181
|
-
}
|
|
186
|
+
},
|
|
187
|
+
"additionalProperties": false
|
|
182
188
|
},
|
|
183
189
|
"TooManyUpdates.Options": {
|
|
184
190
|
"type": "object",
|
|
@@ -3,7 +3,13 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.Labels = void 0;
|
|
6
7
|
const parseRuleDescription_1 = __importDefault(require("./lib/parseRuleDescription"));
|
|
8
|
+
const url_1 = require("url");
|
|
9
|
+
var Labels;
|
|
10
|
+
(function (Labels) {
|
|
11
|
+
Labels["JwtEncode"] = "jwt.encode";
|
|
12
|
+
})(Labels = exports.Labels || (exports.Labels = {}));
|
|
7
13
|
function getHeader(jwt) {
|
|
8
14
|
try {
|
|
9
15
|
const [header] = jwt.split('.');
|
|
@@ -28,7 +34,7 @@ class JwtAlgoritmNoneLogic {
|
|
|
28
34
|
return matches;
|
|
29
35
|
}
|
|
30
36
|
where(event) {
|
|
31
|
-
return event.labels.has(
|
|
37
|
+
return event.labels.has(Labels.JwtEncode);
|
|
32
38
|
}
|
|
33
39
|
}
|
|
34
40
|
class JwtAlgoritmNone {
|
|
@@ -39,6 +45,12 @@ class JwtAlgoritmNone {
|
|
|
39
45
|
this.enumerateScope = true;
|
|
40
46
|
this.description = (0, parseRuleDescription_1.default)('jwtAlgorithmNone');
|
|
41
47
|
this.url = 'https://appland.com/docs/analysis/rules-reference.html#jwt-algorithm-none';
|
|
48
|
+
this.labels = [Labels.JwtEncode];
|
|
49
|
+
this.references = {
|
|
50
|
+
'CWE-345': new url_1.URL('https://cwe.mitre.org/data/definitions/345.html'),
|
|
51
|
+
'A02:2021': new url_1.URL('https://owasp.org/Top10/A02_2021-Cryptographic_Failures'),
|
|
52
|
+
'RFC 7519': new url_1.URL('https://www.rfc-editor.org/rfc/rfc7519'),
|
|
53
|
+
};
|
|
42
54
|
}
|
|
43
55
|
build() {
|
|
44
56
|
return new JwtAlgoritmNoneLogic();
|
|
@@ -76,6 +76,12 @@ class JwtUnverifiedSignature {
|
|
|
76
76
|
this.enumerateScope = true;
|
|
77
77
|
this.description = (0, parseRuleDescription_1.default)('jwtUnverifiedSignature');
|
|
78
78
|
this.url = 'https://appland.com/docs/analysis/rules-reference.html#jwt-unverified-signature';
|
|
79
|
+
this.labels = [Labels.JwtDecode, Labels.SignatureVerify];
|
|
80
|
+
this.references = {
|
|
81
|
+
'CWE-345': new URL('https://cwe.mitre.org/data/definitions/345.html'),
|
|
82
|
+
'A02:2021': new URL('https://owasp.org/Top10/A02_2021-Cryptographic_Failures'),
|
|
83
|
+
'RFC 7519': new URL('https://www.rfc-editor.org/rfc/rfc7519'),
|
|
84
|
+
};
|
|
79
85
|
}
|
|
80
86
|
build() {
|
|
81
87
|
return new JwtUnverifiedSignatureLogic();
|
|
@@ -2,7 +2,13 @@
|
|
|
2
2
|
rule: jwt-algorithm-none
|
|
3
3
|
name: Jwt algorithm none
|
|
4
4
|
title: JWT 'none' algorithm
|
|
5
|
+
references:
|
|
6
|
+
CWE-345: https://cwe.mitre.org/data/definitions/345.html
|
|
7
|
+
A02:2021: https://owasp.org/Top10/A02_2021-Cryptographic_Failures
|
|
8
|
+
RFC 7519: https://www.rfc-editor.org/rfc/rfc7519
|
|
5
9
|
impactDomain: Security
|
|
10
|
+
labels:
|
|
11
|
+
- jwt.encode
|
|
6
12
|
---
|
|
7
13
|
|
|
8
14
|
Finds usage of unsecured JWTs which use the `none` algorithm. When declaring this algorithm, there
|
|
@@ -2,7 +2,14 @@
|
|
|
2
2
|
rule: jwt-unverified-signature
|
|
3
3
|
name: Jwt unverified signature
|
|
4
4
|
title: Unverified signature
|
|
5
|
+
references:
|
|
6
|
+
CWE-345: https://cwe.mitre.org/data/definitions/345.html
|
|
7
|
+
A02:2021: https://owasp.org/Top10/A02_2021-Cryptographic_Failures
|
|
8
|
+
RFC 7519: https://www.rfc-editor.org/rfc/rfc7519
|
|
5
9
|
impactDomain: Security
|
|
10
|
+
labels:
|
|
11
|
+
- jwt.decode
|
|
12
|
+
- jwt.signature.verify
|
|
6
13
|
---
|
|
7
14
|
|
|
8
15
|
Finds cases where a JWT is decoded but the signature is never verified. Without proper signature
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@appland/scanner",
|
|
3
|
-
"version": "1.70.
|
|
3
|
+
"version": "1.70.4",
|
|
4
4
|
"description": "",
|
|
5
5
|
"bin": "built/cli.js",
|
|
6
6
|
"files": [
|
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
"@semantic-release/changelog": "^6.0.1",
|
|
27
27
|
"@semantic-release/git": "^10.0.1",
|
|
28
28
|
"@types/async": "^3.2.12",
|
|
29
|
+
"@types/crypto-js": "^4.1.1",
|
|
29
30
|
"@types/fs-extra": "^9.0.13",
|
|
30
31
|
"@types/glob": "^7.2.0",
|
|
31
32
|
"@types/jest": "^27.4.1",
|
|
@@ -69,6 +70,7 @@
|
|
|
69
70
|
"chokidar": "applandinc/chokidar#fix/new-file-new-directory-race-on-linux",
|
|
70
71
|
"cli-progress": "^3.11.0",
|
|
71
72
|
"conf": "^10.0.2",
|
|
73
|
+
"crypto-js": "^4.0.0",
|
|
72
74
|
"form-data": "^4.0.0",
|
|
73
75
|
"glob": "7.2.3",
|
|
74
76
|
"inquirer": "^8.1.2",
|