@contrast/protect 1.8.0 → 1.8.1
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/lib/hardening/handlers.js +4 -2
- package/lib/hardening/install/node-serialize0.js +5 -5
- package/lib/input-analysis/install/http.js +0 -6
- package/lib/input-tracing/handlers/index.js +10 -1
- package/lib/input-tracing/install/child-process.js +5 -5
- package/lib/input-tracing/install/eval.js +5 -5
- package/lib/input-tracing/install/fs.js +5 -5
- package/lib/input-tracing/install/function.js +6 -5
- package/lib/input-tracing/install/http.js +5 -5
- package/lib/input-tracing/install/mongodb.js +30 -25
- package/lib/input-tracing/install/mysql.js +5 -5
- package/lib/input-tracing/install/postgres.js +5 -5
- package/lib/input-tracing/install/sequelize.js +6 -5
- package/lib/input-tracing/install/sqlite3.js +5 -5
- package/lib/input-tracing/install/vm.js +25 -21
- package/lib/make-source-context.js +0 -10
- package/lib/policy.js +13 -8
- package/lib/semantic-analysis/handlers.js +4 -2
- package/lib/semantic-analysis/install/libxmljs.js +5 -5
- package/package.json +4 -4
|
@@ -24,7 +24,8 @@ module.exports = function(core) {
|
|
|
24
24
|
protect: {
|
|
25
25
|
hardening,
|
|
26
26
|
throwSecurityException,
|
|
27
|
-
}
|
|
27
|
+
},
|
|
28
|
+
captureStacktrace,
|
|
28
29
|
} = core;
|
|
29
30
|
|
|
30
31
|
function getResults(sourceContext, ruleId) {
|
|
@@ -38,7 +39,7 @@ module.exports = function(core) {
|
|
|
38
39
|
hardening.handleUntrustedDeserialization = function(sourceContext, sinkContext) {
|
|
39
40
|
const ruleId = 'untrusted-deserialization';
|
|
40
41
|
const mode = sourceContext.policy[ruleId];
|
|
41
|
-
const { name, value } = sinkContext;
|
|
42
|
+
const { name, value, stacktraceData } = sinkContext;
|
|
42
43
|
|
|
43
44
|
if (mode === 'off') return;
|
|
44
45
|
|
|
@@ -48,6 +49,7 @@ module.exports = function(core) {
|
|
|
48
49
|
const blocked = BLOCKING_MODES.includes(mode);
|
|
49
50
|
const results = getResults(sourceContext, ruleId);
|
|
50
51
|
|
|
52
|
+
captureStacktrace(sinkContext, stacktraceData);
|
|
51
53
|
results.push({
|
|
52
54
|
blocked,
|
|
53
55
|
findings: { deserializer: name, command: false },
|
|
@@ -21,7 +21,6 @@ module.exports = function(core) {
|
|
|
21
21
|
const {
|
|
22
22
|
depHooks,
|
|
23
23
|
patcher,
|
|
24
|
-
captureStacktrace,
|
|
25
24
|
protect,
|
|
26
25
|
protect: {
|
|
27
26
|
hardening
|
|
@@ -43,10 +42,11 @@ module.exports = function(core) {
|
|
|
43
42
|
|
|
44
43
|
if (!sourceContext || !value) return;
|
|
45
44
|
|
|
46
|
-
const sinkContext =
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
45
|
+
const sinkContext = {
|
|
46
|
+
name: `${name}.${method}`,
|
|
47
|
+
value,
|
|
48
|
+
stacktraceData: { constructorOpt: hooked, prependFrames: [orig] },
|
|
49
|
+
};
|
|
50
50
|
hardening.handleUntrustedDeserialization(sourceContext, sinkContext);
|
|
51
51
|
},
|
|
52
52
|
});
|
|
@@ -214,12 +214,6 @@ class HttpInstrumentation {
|
|
|
214
214
|
method: reqData.method,
|
|
215
215
|
};
|
|
216
216
|
|
|
217
|
-
// only add queries if it's known that 'qs' or equivalent won't be used.
|
|
218
|
-
/* c8 ignore next 3 */
|
|
219
|
-
if (reqData.standardUrlParsing) {
|
|
220
|
-
connectInputs.queries = reqData.queries;
|
|
221
|
-
}
|
|
222
|
-
|
|
223
217
|
if (inputAnalysis.virtualPatchesEvaluators?.length) {
|
|
224
218
|
store.protect.virtualPatchesEvaluators.push(...inputAnalysis.virtualPatchesEvaluators.map((e) => new Map(e)));
|
|
225
219
|
}
|
|
@@ -24,9 +24,18 @@ const {
|
|
|
24
24
|
} = require('@contrast/common');
|
|
25
25
|
|
|
26
26
|
module.exports = function(core) {
|
|
27
|
-
const {
|
|
27
|
+
const {
|
|
28
|
+
protect: {
|
|
29
|
+
agentLib,
|
|
30
|
+
inputTracing,
|
|
31
|
+
throwSecurityException
|
|
32
|
+
},
|
|
33
|
+
captureStacktrace,
|
|
34
|
+
} = core;
|
|
28
35
|
|
|
29
36
|
function handleFindings(sourceContext, sinkContext, ruleId, result, findings) {
|
|
37
|
+
const { stacktraceData } = sinkContext;
|
|
38
|
+
captureStacktrace(sinkContext, stacktraceData);
|
|
30
39
|
result.details.push({ sinkContext, findings });
|
|
31
40
|
|
|
32
41
|
const mode = sourceContext.policy[ruleId];
|
|
@@ -23,7 +23,6 @@ module.exports = function(core) {
|
|
|
23
23
|
scopes: { instrumentation },
|
|
24
24
|
patcher,
|
|
25
25
|
depHooks,
|
|
26
|
-
captureStacktrace,
|
|
27
26
|
protect,
|
|
28
27
|
protect: { inputTracing }
|
|
29
28
|
} = core;
|
|
@@ -43,10 +42,11 @@ module.exports = function(core) {
|
|
|
43
42
|
|
|
44
43
|
if (!sourceContext || !value || !isString(value)) return;
|
|
45
44
|
|
|
46
|
-
const sinkContext =
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
45
|
+
const sinkContext = {
|
|
46
|
+
name,
|
|
47
|
+
value,
|
|
48
|
+
stacktraceData: { constructorOpt: hooked, prependFrames: [orig] },
|
|
49
|
+
};
|
|
50
50
|
|
|
51
51
|
inputTracing.handleCommandInjection(sourceContext, sinkContext);
|
|
52
52
|
// To evade code duplication we are using these INPUT TRACING instrumentation
|
|
@@ -23,7 +23,6 @@ module.exports = function(core) {
|
|
|
23
23
|
logger,
|
|
24
24
|
scopes: { instrumentation },
|
|
25
25
|
patcher,
|
|
26
|
-
captureStacktrace,
|
|
27
26
|
protect,
|
|
28
27
|
protect: { inputTracing }
|
|
29
28
|
} = core;
|
|
@@ -45,10 +44,11 @@ module.exports = function(core) {
|
|
|
45
44
|
|
|
46
45
|
if (!sourceContext || !value || !isString(value)) return;
|
|
47
46
|
|
|
48
|
-
const sinkContext =
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
47
|
+
const sinkContext = {
|
|
48
|
+
name: 'eval',
|
|
49
|
+
value,
|
|
50
|
+
stacktraceData: { constructorOpt: hooked, prependFrames: [orig] },
|
|
51
|
+
};
|
|
52
52
|
inputTracing.ssjsInjection(sourceContext, sinkContext);
|
|
53
53
|
}
|
|
54
54
|
});
|
|
@@ -64,7 +64,6 @@ module.exports = function(core) {
|
|
|
64
64
|
scopes: { instrumentation },
|
|
65
65
|
patcher,
|
|
66
66
|
depHooks,
|
|
67
|
-
captureStacktrace,
|
|
68
67
|
protect,
|
|
69
68
|
protect: { inputTracing }
|
|
70
69
|
} = core;
|
|
@@ -101,10 +100,11 @@ module.exports = function(core) {
|
|
|
101
100
|
// don't need to necessarily need to lock it here - there are no
|
|
102
101
|
// lower-level calls that we instrument
|
|
103
102
|
for (const value of values) {
|
|
104
|
-
const sinkContext =
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
103
|
+
const sinkContext = {
|
|
104
|
+
name,
|
|
105
|
+
value,
|
|
106
|
+
stacktraceData: { constructorOpt: hooked, prependFrames: [orig] },
|
|
107
|
+
};
|
|
108
108
|
inputTracing.handlePathTraversal(sourceContext, sinkContext);
|
|
109
109
|
core.protect.semanticAnalysis.handlePathTraversalFileSecurityBypass(sourceContext, sinkContext);
|
|
110
110
|
}
|
|
@@ -23,7 +23,6 @@ module.exports = function(core) {
|
|
|
23
23
|
logger,
|
|
24
24
|
scopes: { instrumentation },
|
|
25
25
|
patcher,
|
|
26
|
-
captureStacktrace,
|
|
27
26
|
protect,
|
|
28
27
|
protect: { inputTracing }
|
|
29
28
|
} = core;
|
|
@@ -46,10 +45,12 @@ module.exports = function(core) {
|
|
|
46
45
|
|
|
47
46
|
if (!sourceContext || !fnBody || !isString(fnBody)) return;
|
|
48
47
|
|
|
49
|
-
const sinkContext =
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
48
|
+
const sinkContext = {
|
|
49
|
+
name: 'Function',
|
|
50
|
+
value: fnBody,
|
|
51
|
+
stacktraceData: { constructorOpt: hooked, prependFrames: [orig] },
|
|
52
|
+
};
|
|
53
|
+
console.log({ sinkContext: sinkContext.stacktraceData });
|
|
53
54
|
inputTracing.ssjsInjection(sourceContext, sinkContext);
|
|
54
55
|
}
|
|
55
56
|
})
|
|
@@ -22,7 +22,6 @@ module.exports = function(core) {
|
|
|
22
22
|
scopes: { instrumentation },
|
|
23
23
|
patcher,
|
|
24
24
|
depHooks,
|
|
25
|
-
captureStacktrace,
|
|
26
25
|
protect,
|
|
27
26
|
protect: { inputTracing }
|
|
28
27
|
} = core;
|
|
@@ -44,10 +43,11 @@ module.exports = function(core) {
|
|
|
44
43
|
const value = data.args[0]?.toString();
|
|
45
44
|
if (!value) return;
|
|
46
45
|
|
|
47
|
-
const sinkContext =
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
46
|
+
const sinkContext = {
|
|
47
|
+
name,
|
|
48
|
+
value,
|
|
49
|
+
stacktraceData: { constructorOpt: data.hooked },
|
|
50
|
+
};
|
|
51
51
|
inputTracing.handleReflectedXss(sourceContext, sinkContext);
|
|
52
52
|
}
|
|
53
53
|
});
|
|
@@ -22,7 +22,6 @@ module.exports = function (core) {
|
|
|
22
22
|
const {
|
|
23
23
|
depHooks,
|
|
24
24
|
patcher,
|
|
25
|
-
captureStacktrace,
|
|
26
25
|
protect,
|
|
27
26
|
protect: { inputTracing },
|
|
28
27
|
} = core;
|
|
@@ -67,10 +66,11 @@ module.exports = function (core) {
|
|
|
67
66
|
|
|
68
67
|
if (!sourceContext || !value) return;
|
|
69
68
|
|
|
70
|
-
const sinkContext =
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
69
|
+
const sinkContext = {
|
|
70
|
+
name,
|
|
71
|
+
value,
|
|
72
|
+
stacktraceData: { constructorOpt: hooked, prependFrames: [orig] },
|
|
73
|
+
};
|
|
74
74
|
inputTracing.nosqlInjectionMongo(sourceContext, sinkContext);
|
|
75
75
|
}
|
|
76
76
|
});
|
|
@@ -91,10 +91,11 @@ module.exports = function (core) {
|
|
|
91
91
|
for (const op of ops) {
|
|
92
92
|
const value = op && getOpQueryData(op);
|
|
93
93
|
if (value) {
|
|
94
|
-
const sinkContext =
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
94
|
+
const sinkContext = {
|
|
95
|
+
name,
|
|
96
|
+
value,
|
|
97
|
+
stacktraceData: { constructorOpt: hooked, prependFrames: [orig] },
|
|
98
|
+
};
|
|
98
99
|
inputTracing.nosqlInjectionMongo(sourceContext, sinkContext);
|
|
99
100
|
}
|
|
100
101
|
}
|
|
@@ -132,10 +133,11 @@ module.exports = function (core) {
|
|
|
132
133
|
|
|
133
134
|
if (!sourceContext || !value) return;
|
|
134
135
|
|
|
135
|
-
const sinkContext =
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
136
|
+
const sinkContext = {
|
|
137
|
+
name,
|
|
138
|
+
value,
|
|
139
|
+
stacktraceData: { constructorOpt: hooked, prependFrames: [orig] },
|
|
140
|
+
};
|
|
139
141
|
inputTracing.nosqlInjectionMongo(sourceContext, sinkContext);
|
|
140
142
|
},
|
|
141
143
|
});
|
|
@@ -150,10 +152,11 @@ module.exports = function (core) {
|
|
|
150
152
|
|
|
151
153
|
if (!sourceContext || !value) return;
|
|
152
154
|
|
|
153
|
-
const sinkContext =
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
155
|
+
const sinkContext = {
|
|
156
|
+
name,
|
|
157
|
+
value,
|
|
158
|
+
stacktraceData: { constructorOpt: hooked, prependFrames: [orig] },
|
|
159
|
+
};
|
|
157
160
|
inputTracing.nosqlInjectionMongo(sourceContext, sinkContext);
|
|
158
161
|
}
|
|
159
162
|
});
|
|
@@ -174,10 +177,11 @@ module.exports = function (core) {
|
|
|
174
177
|
|
|
175
178
|
if (!sourceContext || !value) return;
|
|
176
179
|
|
|
177
|
-
const sinkContext =
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
180
|
+
const sinkContext = {
|
|
181
|
+
name,
|
|
182
|
+
value,
|
|
183
|
+
stacktraceData: { constructorOpt: hooked, prependFrames: [orig] },
|
|
184
|
+
};
|
|
181
185
|
|
|
182
186
|
inputTracing.nosqlInjectionMongo(sourceContext, sinkContext);
|
|
183
187
|
}
|
|
@@ -193,10 +197,11 @@ module.exports = function (core) {
|
|
|
193
197
|
|
|
194
198
|
if (!sourceContext || !value) return;
|
|
195
199
|
|
|
196
|
-
const sinkContext =
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
+
const sinkContext = {
|
|
201
|
+
name,
|
|
202
|
+
value,
|
|
203
|
+
stacktraceData: { constructorOpt: hooked, prependFrames: [orig] },
|
|
204
|
+
};
|
|
200
205
|
inputTracing.nosqlInjectionMongo(sourceContext, sinkContext);
|
|
201
206
|
}
|
|
202
207
|
}));
|
|
@@ -22,7 +22,6 @@ module.exports = function(core) {
|
|
|
22
22
|
const {
|
|
23
23
|
depHooks,
|
|
24
24
|
patcher,
|
|
25
|
-
captureStacktrace,
|
|
26
25
|
protect,
|
|
27
26
|
protect: { inputTracing }
|
|
28
27
|
} = core;
|
|
@@ -56,10 +55,11 @@ module.exports = function(core) {
|
|
|
56
55
|
const value = mysqlInstr.getValueFromArgs(args);
|
|
57
56
|
if (!value) return;
|
|
58
57
|
|
|
59
|
-
const sinkContext =
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
58
|
+
const sinkContext = {
|
|
59
|
+
name,
|
|
60
|
+
value,
|
|
61
|
+
stacktraceData: { constructorOpt: hooked, prependFrames: [orig] },
|
|
62
|
+
};
|
|
63
63
|
|
|
64
64
|
inputTracing.handleSqlInjection(sourceContext, sinkContext);
|
|
65
65
|
}
|
|
@@ -22,7 +22,6 @@ module.exports = function(core) {
|
|
|
22
22
|
const {
|
|
23
23
|
depHooks,
|
|
24
24
|
patcher,
|
|
25
|
-
captureStacktrace,
|
|
26
25
|
protect,
|
|
27
26
|
protect: { inputTracing }
|
|
28
27
|
} = core;
|
|
@@ -40,10 +39,11 @@ module.exports = function(core) {
|
|
|
40
39
|
const value = getQueryFromArgs(args);
|
|
41
40
|
if (!value) return;
|
|
42
41
|
|
|
43
|
-
const sinkContext =
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
42
|
+
const sinkContext = {
|
|
43
|
+
name,
|
|
44
|
+
value,
|
|
45
|
+
stacktraceData: { constructorOpt: hooked, prependFrames: [orig] },
|
|
46
|
+
};
|
|
47
47
|
|
|
48
48
|
inputTracing.handleSqlInjection(sourceContext, sinkContext);
|
|
49
49
|
}
|
|
@@ -23,7 +23,6 @@ module.exports = function(core) {
|
|
|
23
23
|
scopes: { instrumentation },
|
|
24
24
|
patcher,
|
|
25
25
|
depHooks,
|
|
26
|
-
captureStacktrace,
|
|
27
26
|
protect,
|
|
28
27
|
protect: { inputTracing }
|
|
29
28
|
} = core;
|
|
@@ -49,10 +48,12 @@ module.exports = function(core) {
|
|
|
49
48
|
const value = getQueryFromArgs(args);
|
|
50
49
|
if (!value) return;
|
|
51
50
|
|
|
52
|
-
const sinkContext =
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
51
|
+
const sinkContext = {
|
|
52
|
+
name,
|
|
53
|
+
value,
|
|
54
|
+
stacktraceData: { constructorOpt: hooked, prependFrames: [orig] },
|
|
55
|
+
};
|
|
56
|
+
|
|
56
57
|
inputTracing.handleSqlInjection(sourceContext, sinkContext);
|
|
57
58
|
}
|
|
58
59
|
});
|
|
@@ -23,7 +23,6 @@ module.exports = function(core) {
|
|
|
23
23
|
scopes: { instrumentation },
|
|
24
24
|
patcher,
|
|
25
25
|
depHooks,
|
|
26
|
-
captureStacktrace,
|
|
27
26
|
protect,
|
|
28
27
|
protect: { inputTracing }
|
|
29
28
|
} = core;
|
|
@@ -44,10 +43,11 @@ module.exports = function(core) {
|
|
|
44
43
|
const value = args[0];
|
|
45
44
|
if (!value || !isString(value)) return;
|
|
46
45
|
|
|
47
|
-
const sinkContext =
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
46
|
+
const sinkContext = {
|
|
47
|
+
name,
|
|
48
|
+
value,
|
|
49
|
+
stacktraceData: { constructorOpt: hooked, prependFrames: [orig] },
|
|
50
|
+
};
|
|
51
51
|
|
|
52
52
|
inputTracing.handleSqlInjection(sourceContext, sinkContext);
|
|
53
53
|
}
|
|
@@ -23,7 +23,6 @@ module.exports = function(core) {
|
|
|
23
23
|
scopes: { instrumentation },
|
|
24
24
|
patcher,
|
|
25
25
|
depHooks,
|
|
26
|
-
captureStacktrace,
|
|
27
26
|
protect,
|
|
28
27
|
protect: { inputTracing }
|
|
29
28
|
} = core;
|
|
@@ -46,10 +45,11 @@ module.exports = function(core) {
|
|
|
46
45
|
const codeString = args[0];
|
|
47
46
|
if (!codeString || !isString(codeString)) return;
|
|
48
47
|
|
|
49
|
-
const sinkContext =
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
48
|
+
const sinkContext = {
|
|
49
|
+
name,
|
|
50
|
+
value: codeString,
|
|
51
|
+
stacktraceData: { constructorOpt: hooked, prependFrames: [orig] },
|
|
52
|
+
};
|
|
53
53
|
inputTracing.ssjsInjection(sourceContext, sinkContext);
|
|
54
54
|
}
|
|
55
55
|
});
|
|
@@ -70,14 +70,16 @@ module.exports = function(core) {
|
|
|
70
70
|
|
|
71
71
|
if ((!codeString || !isString(codeString)) && (!isNonEmptyObject(envObj))) return;
|
|
72
72
|
|
|
73
|
-
const codeStringSinkContext = (codeString && isString(codeString)) ?
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
73
|
+
const codeStringSinkContext = (codeString && isString(codeString)) ? {
|
|
74
|
+
name: 'vm.runInNewContext',
|
|
75
|
+
value: codeString,
|
|
76
|
+
stacktraceData: { constructorOpt: hooked, prependFrames: [orig] }
|
|
77
|
+
} : null;
|
|
78
|
+
const envObjSinkContext = isNonEmptyObject(envObj) ? {
|
|
79
|
+
name: 'vm.runInNewContext',
|
|
80
|
+
value: envObj,
|
|
81
|
+
stacktraceData: { constructorOpt: hooked, prependFrames: [orig] }
|
|
82
|
+
} : null;
|
|
81
83
|
|
|
82
84
|
codeStringSinkContext && inputTracing.ssjsInjection(sourceContext, codeStringSinkContext);
|
|
83
85
|
envObjSinkContext && inputTracing.ssjsInjection(sourceContext, envObjSinkContext);
|
|
@@ -96,10 +98,11 @@ module.exports = function(core) {
|
|
|
96
98
|
const envObj = args[0];
|
|
97
99
|
if (!isNonEmptyObject(envObj)) return;
|
|
98
100
|
|
|
99
|
-
const sinkContext =
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
101
|
+
const sinkContext = {
|
|
102
|
+
name: 'vm.createContext',
|
|
103
|
+
value: envObj,
|
|
104
|
+
stacktraceData: { constructorOpt: hooked, prependFrames: [orig] },
|
|
105
|
+
};
|
|
103
106
|
inputTracing.ssjsInjection(sourceContext, sinkContext);
|
|
104
107
|
}
|
|
105
108
|
});
|
|
@@ -116,10 +119,11 @@ module.exports = function(core) {
|
|
|
116
119
|
const envObj = args[0];
|
|
117
120
|
if (!isNonEmptyObject(envObj)) return;
|
|
118
121
|
|
|
119
|
-
const sinkContext =
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
122
|
+
const sinkContext = {
|
|
123
|
+
name: 'vm.Script.prototype.runInNewContext',
|
|
124
|
+
value: envObj,
|
|
125
|
+
stacktraceData: { constructorOpt: hooked, prependFrames: [orig] },
|
|
126
|
+
};
|
|
123
127
|
inputTracing.ssjsInjection(sourceContext, sinkContext);
|
|
124
128
|
}
|
|
125
129
|
});
|
|
@@ -60,15 +60,6 @@ module.exports = function(core) {
|
|
|
60
60
|
}
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
-
// if it can be determined that qs-type parsing is not being done then set
|
|
64
|
-
// standardUrlParsing to true. if it is true, then the query params and bodies
|
|
65
|
-
// that are form-url-encoded will be parsed by agent-lib and will not need to
|
|
66
|
-
// be parsed separately.
|
|
67
|
-
//
|
|
68
|
-
// the code that scans the dependencies is probably the best place to make the
|
|
69
|
-
// determination.
|
|
70
|
-
const standardUrlParsing = false;
|
|
71
|
-
|
|
72
63
|
// contains request data and information derived from request data. it's
|
|
73
64
|
// possible for any derived information to be derived later, but doing
|
|
74
65
|
// so here is typically better; it makes clear what information is used to
|
|
@@ -81,7 +72,6 @@ module.exports = function(core) {
|
|
|
81
72
|
uriPath,
|
|
82
73
|
queries,
|
|
83
74
|
contentType,
|
|
84
|
-
standardUrlParsing,
|
|
85
75
|
};
|
|
86
76
|
|
|
87
77
|
//
|
package/lib/policy.js
CHANGED
|
@@ -36,14 +36,18 @@ module.exports = function(core) {
|
|
|
36
36
|
protect: { agentLib }
|
|
37
37
|
} = core;
|
|
38
38
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
39
|
+
function initCompiled() {
|
|
40
|
+
return {
|
|
41
|
+
url: [],
|
|
42
|
+
querystring: [],
|
|
43
|
+
header: [],
|
|
44
|
+
body: [],
|
|
45
|
+
cookie: [],
|
|
46
|
+
parameter: [],
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
let compiled = initCompiled();
|
|
47
51
|
|
|
48
52
|
const policy = protect.policy = {
|
|
49
53
|
exclusions: compiled
|
|
@@ -274,6 +278,7 @@ module.exports = function(core) {
|
|
|
274
278
|
].filter((exclusion) => exclusion.modes.includes('defend'));
|
|
275
279
|
|
|
276
280
|
if (!exclusions.length) return;
|
|
281
|
+
compiled = initCompiled();
|
|
277
282
|
|
|
278
283
|
for (const exclusionDtm of exclusions) {
|
|
279
284
|
exclusionDtm.inputType = exclusionDtm.inputType || 'URL';
|
|
@@ -38,12 +38,14 @@ const getRuleResults = function(obj, prop) {
|
|
|
38
38
|
// See files in protect/lib/input-tracing/install/.
|
|
39
39
|
|
|
40
40
|
module.exports = function(core) {
|
|
41
|
-
const { protect: { agentLib, semanticAnalysis, throwSecurityException } } = core;
|
|
41
|
+
const { protect: { agentLib, semanticAnalysis, throwSecurityException }, captureStacktrace } = core;
|
|
42
42
|
|
|
43
43
|
function handleResult(sourceContext, sinkContext, ruleId, mode, finding) {
|
|
44
|
+
const { value, stacktraceData } = sinkContext;
|
|
45
|
+
captureStacktrace(sinkContext, stacktraceData);
|
|
44
46
|
const result = {
|
|
45
47
|
blocked: false,
|
|
46
|
-
findings: { command:
|
|
48
|
+
findings: { command: value },
|
|
47
49
|
sinkContext,
|
|
48
50
|
...finding
|
|
49
51
|
};
|
|
@@ -26,7 +26,6 @@ module.exports = function(core) {
|
|
|
26
26
|
logger,
|
|
27
27
|
protect: { semanticAnalysis },
|
|
28
28
|
protect,
|
|
29
|
-
captureStacktrace
|
|
30
29
|
} = core;
|
|
31
30
|
|
|
32
31
|
function install() {
|
|
@@ -60,10 +59,11 @@ module.exports = function(core) {
|
|
|
60
59
|
// see: https://help.semmle.com/wiki/display/JS/XML+external+entity+expansion
|
|
61
60
|
if (!sourceContext || !value || !isString(value) || !args[1].noent) return;
|
|
62
61
|
|
|
63
|
-
const sinkContext =
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
62
|
+
const sinkContext = {
|
|
63
|
+
name: 'libxmljs.parseXmlString',
|
|
64
|
+
value,
|
|
65
|
+
stacktraceData: { constructorOpt: hooked, prependFrames: [orig] },
|
|
66
|
+
};
|
|
67
67
|
|
|
68
68
|
try {
|
|
69
69
|
semanticAnalysis.handleXXE(sourceContext, sinkContext);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@contrast/protect",
|
|
3
|
-
"version": "1.8.
|
|
3
|
+
"version": "1.8.1",
|
|
4
4
|
"description": "Contrast service providing framework-agnostic Protect support",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE",
|
|
6
6
|
"author": "Contrast Security <nodejs@contrastsecurity.com> (https://www.contrastsecurity.com)",
|
|
@@ -18,9 +18,9 @@
|
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
20
|
"@contrast/agent-lib": "^5.1.0",
|
|
21
|
-
"@contrast/common": "1.1.
|
|
22
|
-
"@contrast/core": "1.7.
|
|
23
|
-
"@contrast/esm-hooks": "1.3.
|
|
21
|
+
"@contrast/common": "1.1.5",
|
|
22
|
+
"@contrast/core": "1.7.1",
|
|
23
|
+
"@contrast/esm-hooks": "1.3.1",
|
|
24
24
|
"@contrast/scopes": "1.2.0",
|
|
25
25
|
"ipaddr.js": "^2.0.1",
|
|
26
26
|
"semver": "^7.3.7"
|