@appland/scanner 1.46.3 → 1.47.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.
- package/built/rules/deserializationOfUntrustedData.js +12 -80
- package/built/rules/deserializationOfUntrustedData.js.map +1 -1
- package/built/rules/execOfUntrustedCommand.js +97 -0
- package/built/rules/execOfUntrustedCommand.js.map +1 -0
- package/built/rules/lib/parseRuleDescription.js +4 -3
- package/built/rules/lib/parseRuleDescription.js.map +1 -1
- package/built/rules/lib/precedingEvents.js +80 -0
- package/built/rules/lib/precedingEvents.js.map +1 -0
- package/built/rules/lib/sanitizesData.js +10 -0
- package/built/rules/lib/sanitizesData.js.map +1 -0
- package/built/rules/missingAuthentication.js +3 -3
- package/built/rules/missingAuthentication.js.map +1 -1
- package/built/sampleConfig/default.yml +2 -1
- package/doc/labels/{public.md → access.public.md} +1 -1
- package/doc/labels/deserialize.safe.md +2 -0
- package/doc/labels/deserialize.sanitize.md +22 -0
- package/doc/labels/deserialize.unsafe.md +2 -0
- package/doc/labels/system.exec.md +7 -0
- package/doc/labels/system.exec.safe.md +7 -0
- package/doc/labels/system.exec.sanitize.md +22 -0
- package/doc/rules/deserializationOfUntrustedData.md +1 -1
- package/doc/rules/execOfUntrustedCommand.md +16 -0
- package/doc/rules/missingAuthentication.md +1 -1
- package/package.json +1 -1
- package/doc/labels/sanitize.md +0 -29
|
@@ -1,31 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
3
|
-
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
4
|
-
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
5
|
-
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
6
|
-
function step(op) {
|
|
7
|
-
if (f) throw new TypeError("Generator is already executing.");
|
|
8
|
-
while (_) try {
|
|
9
|
-
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
10
|
-
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
11
|
-
switch (op[0]) {
|
|
12
|
-
case 0: case 1: t = op; break;
|
|
13
|
-
case 4: _.label++; return { value: op[1], done: false };
|
|
14
|
-
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
15
|
-
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
16
|
-
default:
|
|
17
|
-
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
18
|
-
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
19
|
-
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
20
|
-
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
21
|
-
if (t[2]) _.ops.pop();
|
|
22
|
-
_.trys.pop(); continue;
|
|
23
|
-
}
|
|
24
|
-
op = body.call(thisArg, _);
|
|
25
|
-
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
26
|
-
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
27
|
-
}
|
|
28
|
-
};
|
|
29
2
|
var __values = (this && this.__values) || function(o) {
|
|
30
3
|
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
|
|
31
4
|
if (m) return m.call(o);
|
|
@@ -44,75 +17,34 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
44
17
|
var models_1 = require("@appland/models");
|
|
45
18
|
var url_1 = require("url");
|
|
46
19
|
var parseRuleDescription_1 = __importDefault(require("./lib/parseRuleDescription"));
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
!!event.returnValue &&
|
|
50
|
-
!!event.returnValue.object_id &&
|
|
51
|
-
event.returnValue.object_id === objectId);
|
|
52
|
-
}
|
|
53
|
-
function precedingEvents(rootEvent, target) {
|
|
54
|
-
var _a, _b, event, e_1_1;
|
|
55
|
-
var e_1, _c;
|
|
56
|
-
return __generator(this, function (_d) {
|
|
57
|
-
switch (_d.label) {
|
|
58
|
-
case 0:
|
|
59
|
-
_d.trys.push([0, 5, 6, 7]);
|
|
60
|
-
_a = __values(new models_1.EventNavigator(rootEvent).descendants()), _b = _a.next();
|
|
61
|
-
_d.label = 1;
|
|
62
|
-
case 1:
|
|
63
|
-
if (!!_b.done) return [3 /*break*/, 4];
|
|
64
|
-
event = _b.value;
|
|
65
|
-
if (event.event === target) {
|
|
66
|
-
return [3 /*break*/, 4];
|
|
67
|
-
}
|
|
68
|
-
return [4 /*yield*/, event];
|
|
69
|
-
case 2:
|
|
70
|
-
_d.sent();
|
|
71
|
-
_d.label = 3;
|
|
72
|
-
case 3:
|
|
73
|
-
_b = _a.next();
|
|
74
|
-
return [3 /*break*/, 1];
|
|
75
|
-
case 4: return [3 /*break*/, 7];
|
|
76
|
-
case 5:
|
|
77
|
-
e_1_1 = _d.sent();
|
|
78
|
-
e_1 = { error: e_1_1 };
|
|
79
|
-
return [3 /*break*/, 7];
|
|
80
|
-
case 6:
|
|
81
|
-
try {
|
|
82
|
-
if (_b && !_b.done && (_c = _a.return)) _c.call(_a);
|
|
83
|
-
}
|
|
84
|
-
finally { if (e_1) throw e_1.error; }
|
|
85
|
-
return [7 /*endfinally*/];
|
|
86
|
-
case 7: return [2 /*return*/];
|
|
87
|
-
}
|
|
88
|
-
});
|
|
89
|
-
}
|
|
20
|
+
var precedingEvents_1 = __importDefault(require("./lib/precedingEvents"));
|
|
21
|
+
var sanitizesData_1 = __importDefault(require("./lib/sanitizesData"));
|
|
90
22
|
function allArgumentsSanitized(rootEvent, event) {
|
|
91
23
|
return (event.parameters || [])
|
|
92
24
|
.filter(function (parameter) { return parameter.object_id; })
|
|
93
25
|
.every(function (parameter) {
|
|
94
|
-
var
|
|
26
|
+
var e_1, _a;
|
|
95
27
|
try {
|
|
96
|
-
for (var _b = __values(
|
|
28
|
+
for (var _b = __values((0, precedingEvents_1.default)(rootEvent, event)), _c = _b.next(); !_c.done; _c = _b.next()) {
|
|
97
29
|
var candidate = _c.value;
|
|
98
|
-
if (
|
|
30
|
+
if ((0, sanitizesData_1.default)(candidate.event, parameter.object_id, DeserializeSanitize)) {
|
|
99
31
|
return true;
|
|
100
32
|
}
|
|
101
33
|
}
|
|
102
34
|
}
|
|
103
|
-
catch (
|
|
35
|
+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
104
36
|
finally {
|
|
105
37
|
try {
|
|
106
38
|
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
|
|
107
39
|
}
|
|
108
|
-
finally { if (
|
|
40
|
+
finally { if (e_1) throw e_1.error; }
|
|
109
41
|
}
|
|
110
42
|
return false;
|
|
111
43
|
});
|
|
112
44
|
}
|
|
113
45
|
function build() {
|
|
114
46
|
function matcher(rootEvent) {
|
|
115
|
-
var
|
|
47
|
+
var e_2, _a;
|
|
116
48
|
try {
|
|
117
49
|
for (var _b = __values(new models_1.EventNavigator(rootEvent).descendants()), _c = _b.next(); !_c.done; _c = _b.next()) {
|
|
118
50
|
var event = _c.value;
|
|
@@ -134,12 +66,12 @@ function build() {
|
|
|
134
66
|
}
|
|
135
67
|
}
|
|
136
68
|
}
|
|
137
|
-
catch (
|
|
69
|
+
catch (e_2_1) { e_2 = { error: e_2_1 }; }
|
|
138
70
|
finally {
|
|
139
71
|
try {
|
|
140
72
|
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
|
|
141
73
|
}
|
|
142
|
-
finally { if (
|
|
74
|
+
finally { if (e_2) throw e_2.error; }
|
|
143
75
|
}
|
|
144
76
|
}
|
|
145
77
|
return {
|
|
@@ -148,11 +80,11 @@ function build() {
|
|
|
148
80
|
}
|
|
149
81
|
var DeserializeUnsafe = 'deserialize.unsafe';
|
|
150
82
|
var DeserializeSafe = 'deserialize.safe';
|
|
151
|
-
var
|
|
83
|
+
var DeserializeSanitize = 'deserialize.sanitize';
|
|
152
84
|
exports.default = {
|
|
153
85
|
id: 'deserialization-of-untrusted-data',
|
|
154
86
|
title: 'Deserialization of untrusted data',
|
|
155
|
-
labels: [DeserializeUnsafe, DeserializeSafe,
|
|
87
|
+
labels: [DeserializeUnsafe, DeserializeSafe, DeserializeSanitize],
|
|
156
88
|
impactDomain: 'Security',
|
|
157
89
|
enumerateScope: false,
|
|
158
90
|
// scope: //*[@command]
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deserializationOfUntrustedData.js","sourceRoot":"","sources":["../../src/rules/deserializationOfUntrustedData.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"deserializationOfUntrustedData.js","sourceRoot":"","sources":["../../src/rules/deserializationOfUntrustedData.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,0CAAwD;AAExD,2BAA0B;AAC1B,oFAA8D;AAC9D,0EAAoD;AACpD,sEAAgD;AAEhD,SAAS,qBAAqB,CAAC,SAAgB,EAAE,KAAY;IAC3D,OAAO,CAAC,KAAK,CAAC,UAAU,IAAI,EAAE,CAAC;SAC5B,MAAM,CAAC,UAAC,SAAS,IAAK,OAAA,SAAS,CAAC,SAAS,EAAnB,CAAmB,CAAC;SAC1C,KAAK,CAAC,UAAC,SAAS;;;YACf,KAAwB,IAAA,KAAA,SAAA,IAAA,yBAAe,EAAC,SAAS,EAAE,KAAK,CAAC,CAAA,gBAAA,4BAAE;gBAAtD,IAAM,SAAS,WAAA;gBAClB,IAAI,IAAA,uBAAa,EAAC,SAAS,CAAC,KAAK,EAAE,SAAS,CAAC,SAAU,EAAE,mBAAmB,CAAC,EAAE;oBAC7E,OAAO,IAAI,CAAC;iBACb;aACF;;;;;;;;;QACD,OAAO,KAAK,CAAC;IACf,CAAC,CAAC,CAAC;AACP,CAAC;AAED,SAAS,KAAK;IACZ,SAAS,OAAO,CAAC,SAAgB;;;YAC/B,KAAoB,IAAA,KAAA,SAAA,IAAI,uBAAc,CAAC,SAAS,CAAC,CAAC,WAAW,EAAE,CAAA,gBAAA,4BAAE;gBAA5D,IAAM,KAAK,WAAA;gBACd,mIAAmI;gBACnI,IACE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,iBAAiB,CAAC;oBACzC,CAAC,KAAK,CAAC,KAAK,CAAC,SAAS,EAAE,CAAC,IAAI,CAAC,UAAC,QAAQ,IAAK,OAAA,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,eAAe,CAAC,EAApC,CAAoC,CAAC,EACjF;oBACA,IAAI,qBAAqB,CAAC,SAAS,EAAE,KAAK,CAAC,KAAK,CAAC,EAAE;wBACjD,OAAO;qBACR;yBAAM;wBACL,OAAO;4BACL;gCACE,KAAK,EAAE,OAAO;gCACd,KAAK,EAAE,KAAK,CAAC,KAAK;gCAClB,OAAO,EAAK,KAAK,CAAC,KAAK,iCAA8B;6BACtD;yBACF,CAAC;qBACH;iBACF;aACF;;;;;;;;;IACH,CAAC;IAED,OAAO;QACL,OAAO,SAAA;KACR,CAAC;AACJ,CAAC;AAED,IAAM,iBAAiB,GAAG,oBAAoB,CAAC;AAC/C,IAAM,eAAe,GAAG,kBAAkB,CAAC;AAC3C,IAAM,mBAAmB,GAAG,sBAAsB,CAAC;AAEnD,kBAAe;IACb,EAAE,EAAE,mCAAmC;IACvC,KAAK,EAAE,mCAAmC;IAC1C,MAAM,EAAE,CAAC,iBAAiB,EAAE,eAAe,EAAE,mBAAmB,CAAC;IACjE,YAAY,EAAE,UAAU;IACxB,cAAc,EAAE,KAAK;IACrB,uBAAuB;IACvB,UAAU,EAAE;QACV,SAAS,EAAE,IAAI,SAAG,CAAC,iDAAiD,CAAC;QACrE,eAAe,EAAE,IAAI,SAAG,CAAC,0DAA0D,CAAC;KACrF;IACD,WAAW,EAAE,IAAA,8BAAoB,EAAC,gCAAgC,CAAC;IACnE,GAAG,EAAE,0FAA0F;IAC/F,KAAK,OAAA;CACE,CAAC"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __values = (this && this.__values) || function(o) {
|
|
3
|
+
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
|
|
4
|
+
if (m) return m.call(o);
|
|
5
|
+
if (o && typeof o.length === "number") return {
|
|
6
|
+
next: function () {
|
|
7
|
+
if (o && i >= o.length) o = void 0;
|
|
8
|
+
return { value: o && o[i++], done: !o };
|
|
9
|
+
}
|
|
10
|
+
};
|
|
11
|
+
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
|
|
12
|
+
};
|
|
13
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
14
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
var models_1 = require("@appland/models");
|
|
18
|
+
var url_1 = require("url");
|
|
19
|
+
var parseRuleDescription_1 = __importDefault(require("./lib/parseRuleDescription"));
|
|
20
|
+
var precedingEvents_1 = __importDefault(require("./lib/precedingEvents"));
|
|
21
|
+
var sanitizesData_1 = __importDefault(require("./lib/sanitizesData"));
|
|
22
|
+
function allArgumentsSanitized(rootEvent, event) {
|
|
23
|
+
return (event.parameters || [])
|
|
24
|
+
.filter(function (parameter) { return parameter.object_id; })
|
|
25
|
+
.every(function (parameter) {
|
|
26
|
+
var e_1, _a;
|
|
27
|
+
try {
|
|
28
|
+
for (var _b = __values((0, precedingEvents_1.default)(rootEvent, event)), _c = _b.next(); !_c.done; _c = _b.next()) {
|
|
29
|
+
var candidate = _c.value;
|
|
30
|
+
if ((0, sanitizesData_1.default)(candidate.event, parameter.object_id, ExecSanitize)) {
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
36
|
+
finally {
|
|
37
|
+
try {
|
|
38
|
+
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
|
|
39
|
+
}
|
|
40
|
+
finally { if (e_1) throw e_1.error; }
|
|
41
|
+
}
|
|
42
|
+
return false;
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
function build() {
|
|
46
|
+
function matcher(rootEvent) {
|
|
47
|
+
var e_2, _a;
|
|
48
|
+
try {
|
|
49
|
+
for (var _b = __values(new models_1.EventNavigator(rootEvent).descendants()), _c = _b.next(); !_c.done; _c = _b.next()) {
|
|
50
|
+
var event = _c.value;
|
|
51
|
+
if (event.event.labels.has(Exec) &&
|
|
52
|
+
!event.event.ancestors().find(function (ancestor) { return ancestor.labels.has(ExecSafe); })) {
|
|
53
|
+
if (allArgumentsSanitized(rootEvent, event.event)) {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
return [
|
|
58
|
+
{
|
|
59
|
+
level: 'error',
|
|
60
|
+
event: event.event,
|
|
61
|
+
message: event.event + " executes an untrusted command string",
|
|
62
|
+
},
|
|
63
|
+
];
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
catch (e_2_1) { e_2 = { error: e_2_1 }; }
|
|
69
|
+
finally {
|
|
70
|
+
try {
|
|
71
|
+
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
|
|
72
|
+
}
|
|
73
|
+
finally { if (e_2) throw e_2.error; }
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return {
|
|
77
|
+
matcher: matcher,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
var Exec = 'system.exec';
|
|
81
|
+
var ExecSafe = 'system.exec.safe';
|
|
82
|
+
var ExecSanitize = 'system.exec.sanitize';
|
|
83
|
+
exports.default = {
|
|
84
|
+
id: 'exec-of-untrusted-command',
|
|
85
|
+
title: 'Execution of untrusted system command',
|
|
86
|
+
labels: [Exec, ExecSafe, ExecSanitize],
|
|
87
|
+
impactDomain: 'Security',
|
|
88
|
+
enumerateScope: false,
|
|
89
|
+
// scope: //*[@command]
|
|
90
|
+
references: {
|
|
91
|
+
'CWE-78': new url_1.URL('https://cwe.mitre.org/data/definitions/78.html'),
|
|
92
|
+
},
|
|
93
|
+
description: (0, parseRuleDescription_1.default)('execOfUntrustedCommand'),
|
|
94
|
+
url: 'https://appland.com/docs/analysis/rules-reference.html#exec-of-untrusted-command',
|
|
95
|
+
build: build,
|
|
96
|
+
};
|
|
97
|
+
//# sourceMappingURL=execOfUntrustedCommand.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"execOfUntrustedCommand.js","sourceRoot":"","sources":["../../src/rules/execOfUntrustedCommand.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,0CAAwD;AACxD,2BAA0B;AAE1B,oFAA8D;AAC9D,0EAAoD;AACpD,sEAAgD;AAEhD,SAAS,qBAAqB,CAAC,SAAgB,EAAE,KAAY;IAC3D,OAAO,CAAC,KAAK,CAAC,UAAU,IAAI,EAAE,CAAC;SAC5B,MAAM,CAAC,UAAC,SAAS,IAAK,OAAA,SAAS,CAAC,SAAS,EAAnB,CAAmB,CAAC;SAC1C,KAAK,CAAC,UAAC,SAAS;;;YACf,KAAwB,IAAA,KAAA,SAAA,IAAA,yBAAe,EAAC,SAAS,EAAE,KAAK,CAAC,CAAA,gBAAA,4BAAE;gBAAtD,IAAM,SAAS,WAAA;gBAClB,IAAI,IAAA,uBAAa,EAAC,SAAS,CAAC,KAAK,EAAE,SAAS,CAAC,SAAU,EAAE,YAAY,CAAC,EAAE;oBACtE,OAAO,IAAI,CAAC;iBACb;aACF;;;;;;;;;QACD,OAAO,KAAK,CAAC;IACf,CAAC,CAAC,CAAC;AACP,CAAC;AAED,SAAS,KAAK;IACZ,SAAS,OAAO,CAAC,SAAgB;;;YAC/B,KAAoB,IAAA,KAAA,SAAA,IAAI,uBAAc,CAAC,SAAS,CAAC,CAAC,WAAW,EAAE,CAAA,gBAAA,4BAAE;gBAA5D,IAAM,KAAK,WAAA;gBACd,IACE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC;oBAC5B,CAAC,KAAK,CAAC,KAAK,CAAC,SAAS,EAAE,CAAC,IAAI,CAAC,UAAC,QAAQ,IAAK,OAAA,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,EAA7B,CAA6B,CAAC,EAC1E;oBACA,IAAI,qBAAqB,CAAC,SAAS,EAAE,KAAK,CAAC,KAAK,CAAC,EAAE;wBACjD,OAAO;qBACR;yBAAM;wBACL,OAAO;4BACL;gCACE,KAAK,EAAE,OAAO;gCACd,KAAK,EAAE,KAAK,CAAC,KAAK;gCAClB,OAAO,EAAK,KAAK,CAAC,KAAK,0CAAuC;6BAC/D;yBACF,CAAC;qBACH;iBACF;aACF;;;;;;;;;IACH,CAAC;IAED,OAAO;QACL,OAAO,SAAA;KACR,CAAC;AACJ,CAAC;AAED,IAAM,IAAI,GAAG,aAAa,CAAC;AAC3B,IAAM,QAAQ,GAAG,kBAAkB,CAAC;AACpC,IAAM,YAAY,GAAG,sBAAsB,CAAC;AAE5C,kBAAe;IACb,EAAE,EAAE,2BAA2B;IAC/B,KAAK,EAAE,uCAAuC;IAC9C,MAAM,EAAE,CAAC,IAAI,EAAE,QAAQ,EAAE,YAAY,CAAC;IACtC,YAAY,EAAE,UAAU;IACxB,cAAc,EAAE,KAAK;IACrB,uBAAuB;IACvB,UAAU,EAAE;QACV,QAAQ,EAAE,IAAI,SAAG,CAAC,gDAAgD,CAAC;KACpE;IACD,WAAW,EAAE,IAAA,8BAAoB,EAAC,wBAAwB,CAAC;IAC3D,GAAG,EAAE,kFAAkF;IACvF,KAAK,OAAA;CACE,CAAC"}
|
|
@@ -4,13 +4,14 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
var fs_1 = __importDefault(require("fs"));
|
|
7
|
-
var errors_1 = require("../../errors");
|
|
8
7
|
var path_1 = require("path");
|
|
9
8
|
function parseRuleDescription(id) {
|
|
10
9
|
var content = fs_1.default.readFileSync((0, path_1.join)(__dirname, "../../../doc/rules/" + id + ".md"), 'utf-8');
|
|
11
|
-
var propertiesContent = content.match(/---\n((?:.*\n)+)---\n((?:.*\n)+?)
|
|
10
|
+
var propertiesContent = content.match(/---\n((?:.*\n)+)---\n((?:.*\n)+?)##?#?/);
|
|
12
11
|
if (!propertiesContent) {
|
|
13
|
-
|
|
12
|
+
// This is probably a new doc that doesn't have front matter yet.
|
|
13
|
+
// It's all description.
|
|
14
|
+
return content;
|
|
14
15
|
}
|
|
15
16
|
return propertiesContent[2].replace(/\n/g, ' ').trim();
|
|
16
17
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parseRuleDescription.js","sourceRoot":"","sources":["../../../src/rules/lib/parseRuleDescription.ts"],"names":[],"mappings":";;;;;AAAA,0CAAoB;AACpB,
|
|
1
|
+
{"version":3,"file":"parseRuleDescription.js","sourceRoot":"","sources":["../../../src/rules/lib/parseRuleDescription.ts"],"names":[],"mappings":";;;;;AAAA,0CAAoB;AACpB,6BAA4B;AAE5B,SAAwB,oBAAoB,CAAC,EAAU;IACrD,IAAM,OAAO,GAAG,YAAE,CAAC,YAAY,CAAC,IAAA,WAAI,EAAC,SAAS,EAAE,wBAAsB,EAAE,QAAK,CAAC,EAAE,OAAO,CAAC,CAAC;IACzF,IAAM,iBAAiB,GAAG,OAAO,CAAC,KAAK,CAAC,wCAAwC,CAAC,CAAC;IAElF,IAAI,CAAC,iBAAiB,EAAE;QACtB,iEAAiE;QACjE,wBAAwB;QACxB,OAAO,OAAO,CAAC;KAChB;IAED,OAAO,iBAAiB,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;AACzD,CAAC;AAXD,uCAWC"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
3
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
4
|
+
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
5
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
6
|
+
function step(op) {
|
|
7
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
8
|
+
while (_) try {
|
|
9
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
10
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
11
|
+
switch (op[0]) {
|
|
12
|
+
case 0: case 1: t = op; break;
|
|
13
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
14
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
15
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
16
|
+
default:
|
|
17
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
18
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
19
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
20
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
21
|
+
if (t[2]) _.ops.pop();
|
|
22
|
+
_.trys.pop(); continue;
|
|
23
|
+
}
|
|
24
|
+
op = body.call(thisArg, _);
|
|
25
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
26
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
var __values = (this && this.__values) || function(o) {
|
|
30
|
+
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
|
|
31
|
+
if (m) return m.call(o);
|
|
32
|
+
if (o && typeof o.length === "number") return {
|
|
33
|
+
next: function () {
|
|
34
|
+
if (o && i >= o.length) o = void 0;
|
|
35
|
+
return { value: o && o[i++], done: !o };
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
|
|
39
|
+
};
|
|
40
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
41
|
+
var models_1 = require("@appland/models");
|
|
42
|
+
function precedingEvents(rootEvent, target) {
|
|
43
|
+
var _a, _b, event, e_1_1;
|
|
44
|
+
var e_1, _c;
|
|
45
|
+
return __generator(this, function (_d) {
|
|
46
|
+
switch (_d.label) {
|
|
47
|
+
case 0:
|
|
48
|
+
_d.trys.push([0, 5, 6, 7]);
|
|
49
|
+
_a = __values(new models_1.EventNavigator(rootEvent).descendants()), _b = _a.next();
|
|
50
|
+
_d.label = 1;
|
|
51
|
+
case 1:
|
|
52
|
+
if (!!_b.done) return [3 /*break*/, 4];
|
|
53
|
+
event = _b.value;
|
|
54
|
+
if (event.event === target) {
|
|
55
|
+
return [3 /*break*/, 4];
|
|
56
|
+
}
|
|
57
|
+
return [4 /*yield*/, event];
|
|
58
|
+
case 2:
|
|
59
|
+
_d.sent();
|
|
60
|
+
_d.label = 3;
|
|
61
|
+
case 3:
|
|
62
|
+
_b = _a.next();
|
|
63
|
+
return [3 /*break*/, 1];
|
|
64
|
+
case 4: return [3 /*break*/, 7];
|
|
65
|
+
case 5:
|
|
66
|
+
e_1_1 = _d.sent();
|
|
67
|
+
e_1 = { error: e_1_1 };
|
|
68
|
+
return [3 /*break*/, 7];
|
|
69
|
+
case 6:
|
|
70
|
+
try {
|
|
71
|
+
if (_b && !_b.done && (_c = _a.return)) _c.call(_a);
|
|
72
|
+
}
|
|
73
|
+
finally { if (e_1) throw e_1.error; }
|
|
74
|
+
return [7 /*endfinally*/];
|
|
75
|
+
case 7: return [2 /*return*/];
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
exports.default = precedingEvents;
|
|
80
|
+
//# sourceMappingURL=precedingEvents.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"precedingEvents.js","sourceRoot":"","sources":["../../../src/rules/lib/precedingEvents.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,0CAAwD;AAExD,SAAyB,eAAe,CACtC,SAAgB,EAChB,MAAa;;;;;;;gBAEO,KAAA,SAAA,IAAI,uBAAc,CAAC,SAAS,CAAC,CAAC,WAAW,EAAE,CAAA;;;;gBAApD,KAAK;gBACd,IAAI,KAAK,CAAC,KAAK,KAAK,MAAM,EAAE;oBAC1B,wBAAM;iBACP;gBACD,qBAAM,KAAK,EAAA;;gBAAX,SAAW,CAAC;;;;;;;;;;;;;;;;;;;CAEf;AAVD,kCAUC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
function sanitizesData(event, objectId, label) {
|
|
4
|
+
return (event.labels.has(label) &&
|
|
5
|
+
!!event.returnValue &&
|
|
6
|
+
!!event.returnValue.object_id &&
|
|
7
|
+
event.returnValue.object_id === objectId);
|
|
8
|
+
}
|
|
9
|
+
exports.default = sanitizesData;
|
|
10
|
+
//# sourceMappingURL=sanitizesData.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sanitizesData.js","sourceRoot":"","sources":["../../../src/rules/lib/sanitizesData.ts"],"names":[],"mappings":";;AAEA,SAAwB,aAAa,CAAC,KAAY,EAAE,QAAgB,EAAE,KAAa;IACjF,OAAO,CACL,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC;QACvB,CAAC,CAAC,KAAK,CAAC,WAAW;QACnB,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC,SAAS;QAC7B,KAAK,CAAC,WAAW,CAAC,SAAS,KAAK,QAAQ,CACzC,CAAC;AACJ,CAAC;AAPD,gCAOC"}
|
|
@@ -10,7 +10,7 @@ var matchPattern_1 = require("./lib/matchPattern");
|
|
|
10
10
|
var url_1 = require("url");
|
|
11
11
|
var parseRuleDescription_1 = __importDefault(require("./lib/parseRuleDescription"));
|
|
12
12
|
function isPublic(event) {
|
|
13
|
-
return event.labels.has(
|
|
13
|
+
return event.labels.has(AccessPublic);
|
|
14
14
|
}
|
|
15
15
|
var authenticatedBy = function (iterator) {
|
|
16
16
|
var i = iterator.next();
|
|
@@ -56,13 +56,13 @@ function build(options) {
|
|
|
56
56
|
matcher: matcher,
|
|
57
57
|
};
|
|
58
58
|
}
|
|
59
|
-
var
|
|
59
|
+
var AccessPublic = 'access.public';
|
|
60
60
|
var SecurityAuthentication = 'security.authentication';
|
|
61
61
|
exports.default = {
|
|
62
62
|
id: 'missing-authentication',
|
|
63
63
|
title: 'Unauthenticated HTTP server request',
|
|
64
64
|
scope: 'http_server_request',
|
|
65
|
-
labels: [
|
|
65
|
+
labels: [AccessPublic, SecurityAuthentication],
|
|
66
66
|
impactDomain: 'Security',
|
|
67
67
|
enumerateScope: false,
|
|
68
68
|
references: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"missingAuthentication.js","sourceRoot":"","sources":["../../src/rules/missingAuthentication.ts"],"names":[],"mappings":";;;;;AAAA,0CAAwD;AACxD,oDAA2D;AAG3D,mCAAoD;AAEpD,mDAAkD;AAClD,2BAA0B;AAC1B,oFAA8D;AAE9D,SAAS,QAAQ,CAAC,KAAY;IAC5B,OAAO,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,
|
|
1
|
+
{"version":3,"file":"missingAuthentication.js","sourceRoot":"","sources":["../../src/rules/missingAuthentication.ts"],"names":[],"mappings":";;;;;AAAA,0CAAwD;AACxD,oDAA2D;AAG3D,mCAAoD;AAEpD,mDAAkD;AAClD,2BAA0B;AAC1B,oFAA8D;AAE9D,SAAS,QAAQ,CAAC,KAAY;IAC5B,OAAO,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;AACxC,CAAC;AAED,IAAM,eAAe,GAAG,UAAC,QAAkC;IACzD,IAAI,CAAC,GAAmC,QAAQ,CAAC,IAAI,EAAE,CAAC;IACxD,OAAO,CAAC,CAAC,CAAC,IAAI,EAAE;QACd,IAAI,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,IAAA,6BAAsB,EAAC,CAAC,CAAC,KAAK,CAAC,KAAK,EAAE,sBAAsB,CAAC,EAAE;YAC5F,OAAO,IAAI,CAAC;SACb;QACD,CAAC,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC;KACrB;IAED,OAAO,KAAK,CAAC;AACf,CAAC,CAAC;AAEF;IAAA;QACS,wBAAmB,GAAyB,EAAE,CAAC;QAC/C,wBAAmB,GAAyB,EAAE,CAAC;IACxD,CAAC;IAAD,cAAC;AAAD,CAAC,AAHD,IAGC;AAED,SAAS,KAAK,CAAC,OAAgC;IAAhC,wBAAA,EAAA,cAAuB,OAAO,EAAE;IAC7C,IAAM,mBAAmB,GAAG,IAAA,2BAAY,EAAC,OAAO,CAAC,mBAAmB,CAAC,CAAC;IACtE,IAAM,mBAAmB,GAAG,IAAA,2BAAY,EAAC,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAEtE,SAAS,eAAe,CAAC,WAAmB;QAC1C,SAAS,IAAI,CAAC,MAAoB;YAChC,OAAO,MAAM,CAAC,WAAW,CAAC,CAAC;QAC7B,CAAC;QAED,OAAO,CACL,CAAC,mBAAmB,CAAC,MAAM,KAAK,CAAC,IAAI,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACpE,CAAC,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC,CAChC,CAAC;IACJ,CAAC;IAED,SAAS,OAAO,CAAC,KAAY;QAC3B,OAAO,CAAC,eAAe,CAAC,IAAI,uBAAc,CAAC,KAAK,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;IACnE,CAAC;IAED,SAAS,KAAK,CAAC,CAAQ;QACrB,OAAO,CACL,CAAC,CAAC,KAAK,KAAK,SAAS;YACrB,CAAC,CAAC,kBAAkB,KAAK,SAAS;YAClC,CAAC,CAAC,kBAAkB,CAAC,MAAM,GAAG,GAAG;YACjC,CAAC,CAAC,IAAA,+BAAkB,EAAC,CAAC,CAAC;YACvB,CAAC,CAAC,IAAA,+BAAkB,EAAC,CAAC,CAAE,CAAC,WAAW;YACpC,eAAe,CAAC,IAAA,+BAAkB,EAAC,CAAC,CAAE,CAAC,WAAW,CAAC,CACpD,CAAC;IACJ,CAAC;IACD,OAAO;QACL,KAAK,OAAA;QACL,OAAO,SAAA;KACR,CAAC;AACJ,CAAC;AACD,IAAM,YAAY,GAAG,eAAe,CAAC;AACrC,IAAM,sBAAsB,GAAG,yBAAyB,CAAC;AAEzD,kBAAe;IACb,EAAE,EAAE,wBAAwB;IAC5B,KAAK,EAAE,qCAAqC;IAC5C,KAAK,EAAE,qBAAqB;IAC5B,MAAM,EAAE,CAAC,YAAY,EAAE,sBAAsB,CAAC;IAC9C,YAAY,EAAE,UAAU;IACxB,cAAc,EAAE,KAAK;IACrB,UAAU,EAAE;QACV,SAAS,EAAE,IAAI,SAAG,CAAC,iDAAiD,CAAC;KACtE;IACD,WAAW,EAAE,IAAA,8BAAoB,EAAC,uBAAuB,CAAC;IAC1D,GAAG,EAAE,+EAA+E;IACpF,OAAO,SAAA;IACP,KAAK,OAAA;CACE,CAAC"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
checks:
|
|
2
2
|
- rule: authzBeforeAuthn
|
|
3
3
|
- rule: circularDependency
|
|
4
|
-
|
|
4
|
+
- rule: deserializationOfUntrustedData
|
|
5
|
+
- rule: execOfUntrustedCommand
|
|
5
6
|
- rule: http500
|
|
6
7
|
# - rule: illegalPackageDependency
|
|
7
8
|
# - rule: incompatibleHttpClientRequest
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: deserialize.sanitize
|
|
3
|
+
rules:
|
|
4
|
+
- deserialization-of-untrusted-data
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
Ensures that data is safe and trusted for deserialization, transforming it if necessary, and
|
|
8
|
+
returning `falsey` or raising an exception if it's impossible to make the data safe.
|
|
9
|
+
|
|
10
|
+
A function with this label can be used to convert untrusted data such as direct user input or HTTP
|
|
11
|
+
request parameters into trusted data.
|
|
12
|
+
|
|
13
|
+
Note that this is not the same as ensuring that a parameter satisfies business logic constraints -
|
|
14
|
+
such as presence or max length. It's a security check that ensures the data cannot cause harm on
|
|
15
|
+
deserialization.
|
|
16
|
+
|
|
17
|
+
To be considered successful, a `deserialize.sanitize` function must return a `truthy` value.
|
|
18
|
+
|
|
19
|
+
## Examples
|
|
20
|
+
|
|
21
|
+
- Running user-provided YAML through a "safe loader" which discards unsafe syntax such as object
|
|
22
|
+
class names.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: system.exec.sanitize
|
|
3
|
+
rules:
|
|
4
|
+
- exec-of-untrusted-command
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
Ensures that data is safe and trusted for use as a system command, transforming it if necessary, and
|
|
8
|
+
returning `falsey` or raising an exception if it's impossible to make the data safe.
|
|
9
|
+
|
|
10
|
+
A function with this label can be used to convert untrusted data such as direct user input or HTTP
|
|
11
|
+
request parameters into trusted data.
|
|
12
|
+
|
|
13
|
+
Note that this is not the same as ensuring that a parameter satisfies business logic constraints -
|
|
14
|
+
such as presence or max length. It's a security check that ensures the data cannot cause harm when
|
|
15
|
+
used as a system command.
|
|
16
|
+
|
|
17
|
+
To be considered successful, a `system.exec.sanitize` function must return a `truthy` value.
|
|
18
|
+
|
|
19
|
+
## Examples
|
|
20
|
+
|
|
21
|
+
- Ensuring that a user-provided file path is a subdirectory of a known allowed directory.
|
|
22
|
+
- Ensuring that a system command string does not have any potential injection or side-effects.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
---
|
|
2
|
+
rule: exec-of-untrusted-command
|
|
3
|
+
name: Exec of untrusted command
|
|
4
|
+
title: Execution of untrusted system command
|
|
5
|
+
references:
|
|
6
|
+
CWE-78: https://cwe.mitre.org/data/definitions/78.html
|
|
7
|
+
impactDomain: Security
|
|
8
|
+
labels:
|
|
9
|
+
- system.exec
|
|
10
|
+
- system.exec.safe
|
|
11
|
+
- system.exec.sanitize
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
Find occurrances of system command execution in which the command string is not guaranteed to be
|
|
15
|
+
safe.
|
|
16
|
+
|
package/package.json
CHANGED
package/doc/labels/sanitize.md
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: sanitize
|
|
3
|
-
rules:
|
|
4
|
-
- deserialization-of-untrusted-data
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
Ensures that data is safe and trusted, transforming it if necessary, and returning `falsey` or
|
|
8
|
-
raising an exception if it's impossible to make the data safe.
|
|
9
|
-
|
|
10
|
-
A function with this label can be used to convert untrusted data such as direct user input or HTTP
|
|
11
|
-
request parameters into trusted data.
|
|
12
|
-
|
|
13
|
-
Note that this is not the same as ensuring that a parameter satisfies business logic constraints -
|
|
14
|
-
such as presence or max length. It's a security check that ensures the data cannot cause downstream
|
|
15
|
-
harm.
|
|
16
|
-
|
|
17
|
-
To be considered successful, a `sanitize` function must return a `truthy` value.
|
|
18
|
-
|
|
19
|
-
## Examples
|
|
20
|
-
|
|
21
|
-
- Sanitizing HTML by removing all potentially harmful elements, such as script tags.
|
|
22
|
-
- Ensuring that SQL queries are properly escaped.
|
|
23
|
-
- Running user-provided YAML through a "safe loader" which discards unsafe syntax such as object
|
|
24
|
-
class names.
|
|
25
|
-
- Ensuring that a user-provided file path is a subdirectory of a known allowed directory.
|
|
26
|
-
- Ensuring that a system command string does not have any potential injection or side-effects.
|
|
27
|
-
- Ruby -
|
|
28
|
-
[sanitize_filename](https://github.com/technoweenie/attachment_fu/blob/fa08cb03914b02b66853b4615cd3eca768291ca7/lib/technoweenie/attachment_fu.rb#L410)
|
|
29
|
-
in `attachment_fu`.
|