@contrast/agentify 1.3.1 → 1.4.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/contrast-methods.js +77 -24
- package/lib/function-hooks.js +1 -1
- package/lib/index.js +25 -14
- package/lib/rewrite-hooks.js +6 -1
- package/package.json +2 -2
package/lib/contrast-methods.js
CHANGED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
|
|
16
16
|
'use strict';
|
|
17
17
|
|
|
18
|
-
module.exports = function(core) {
|
|
18
|
+
module.exports = function (core) {
|
|
19
19
|
const { logger, patcher } = core;
|
|
20
20
|
|
|
21
21
|
const getOrig = (v) => patcher.unwrap(v);
|
|
@@ -28,70 +28,123 @@ module.exports = function(core) {
|
|
|
28
28
|
* 2) patch those functions on `contrastMethods.api` in order to add instrumentation
|
|
29
29
|
*/
|
|
30
30
|
const contrastMethods = {
|
|
31
|
-
// TODO: Assess will require add'l methods
|
|
32
|
-
// TODO: ESM will require add'l methods
|
|
33
31
|
api: {
|
|
34
32
|
eval(v) {
|
|
35
33
|
return v;
|
|
36
34
|
},
|
|
37
|
-
|
|
35
|
+
|
|
36
|
+
// Binary Operators
|
|
37
|
+
add(left, right) {
|
|
38
38
|
const ret = getOrig(left) + getOrig(right);
|
|
39
39
|
return ret;
|
|
40
40
|
},
|
|
41
|
-
|
|
41
|
+
eqEq(left, right) {
|
|
42
42
|
left = getOrig(left);
|
|
43
43
|
right = getOrig(right);
|
|
44
44
|
|
|
45
45
|
return left == right;
|
|
46
46
|
},
|
|
47
|
-
|
|
47
|
+
eqEqEq(left, right) {
|
|
48
48
|
left = getOrig(left);
|
|
49
49
|
right = getOrig(right);
|
|
50
50
|
|
|
51
|
-
return left
|
|
51
|
+
return left === right;
|
|
52
52
|
},
|
|
53
|
-
|
|
53
|
+
notEqEq(left, right) {
|
|
54
54
|
left = getOrig(left);
|
|
55
55
|
right = getOrig(right);
|
|
56
56
|
|
|
57
|
-
return left
|
|
57
|
+
return left !== right;
|
|
58
58
|
},
|
|
59
|
-
|
|
59
|
+
notEq(left, right) {
|
|
60
60
|
left = getOrig(left);
|
|
61
61
|
right = getOrig(right);
|
|
62
62
|
|
|
63
63
|
return left != right;
|
|
64
64
|
},
|
|
65
|
+
|
|
66
|
+
// Computed Properties
|
|
67
|
+
// Used to force a copy of handle:
|
|
68
|
+
// https://stackoverflow.com/a/31733628
|
|
69
|
+
// This is a workaround for CONTRAST-30333, in which something we
|
|
70
|
+
// suspect is a v8 bug means that handle will otherwise be clobbered
|
|
71
|
+
// and if it was externalized, we will lose the data associated with it
|
|
65
72
|
forceCopy(handle) {
|
|
66
|
-
// Used to force a copy of handle:
|
|
67
|
-
// https://stackoverflow.com/a/31733628
|
|
68
|
-
// This is a workaround for CONTRAST-30333, in which something we
|
|
69
|
-
// suspect is a v8 bug means that handle will otherwise be clobbered
|
|
70
|
-
// and if it was externalized, we will lose the data associated with it
|
|
71
73
|
if (typeof handle === 'string') {
|
|
72
74
|
handle = toUntrackedString(handle);
|
|
73
75
|
}
|
|
74
76
|
return handle;
|
|
75
77
|
},
|
|
76
|
-
|
|
78
|
+
|
|
79
|
+
// Switch Case
|
|
80
|
+
cast(val) {
|
|
77
81
|
return getOrig(val);
|
|
78
82
|
},
|
|
79
|
-
|
|
80
|
-
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Tagged Templates
|
|
86
|
+
* The first argument received by the tag function is an array of strings.
|
|
87
|
+
* For any template literal, its length is equal to the number of
|
|
88
|
+
* substitutions (occurrences of ${...}) plus one, and is therefore always
|
|
89
|
+
* non-empty.
|
|
90
|
+
* see: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals#tagged_templates
|
|
91
|
+
* @param {string[]} strings length n+1
|
|
92
|
+
* @param {string[]} args length n
|
|
93
|
+
* @returns {string}
|
|
94
|
+
*/
|
|
95
|
+
tag(strings, ...args) {
|
|
96
|
+
const [first, ...rest] = strings;
|
|
97
|
+
|
|
98
|
+
return rest.reduce(
|
|
99
|
+
(result, str, i) => result.concat(args[i], str),
|
|
100
|
+
first,
|
|
101
|
+
);
|
|
102
|
+
},
|
|
103
|
+
|
|
104
|
+
// Import Statements
|
|
105
|
+
importDefault(...args) {
|
|
106
|
+
// noop
|
|
81
107
|
},
|
|
82
108
|
|
|
109
|
+
importStarAs(...args) {
|
|
110
|
+
// noop
|
|
111
|
+
},
|
|
112
|
+
|
|
113
|
+
importNamed(...args) {
|
|
114
|
+
// noop
|
|
115
|
+
},
|
|
116
|
+
|
|
117
|
+
// Injections
|
|
83
118
|
Function: core.patcher.patch(global.Function, {
|
|
84
119
|
name: 'global.Function',
|
|
85
|
-
patchType: 'rewrite-injection'
|
|
120
|
+
patchType: 'rewrite-injection',
|
|
121
|
+
}),
|
|
122
|
+
JSON: core.patcher.patch(global.JSON, {
|
|
123
|
+
name: 'global.JSON',
|
|
124
|
+
patchType: 'rewrite-injection',
|
|
125
|
+
}),
|
|
126
|
+
Number: core.patcher.patch(global.Number, {
|
|
127
|
+
name: 'global.Number',
|
|
128
|
+
patchType: 'rewrite-injection',
|
|
129
|
+
}),
|
|
130
|
+
Object: core.patcher.patch(global.Object, {
|
|
131
|
+
name: 'global.Object',
|
|
132
|
+
patchType: 'rewrite-injection',
|
|
133
|
+
}),
|
|
134
|
+
String: core.patcher.patch(global.String, {
|
|
135
|
+
name: 'global.String',
|
|
136
|
+
patchType: 'rewrite-injection',
|
|
86
137
|
}),
|
|
87
138
|
},
|
|
139
|
+
|
|
88
140
|
installed: false,
|
|
141
|
+
|
|
89
142
|
getGlobal() {
|
|
90
143
|
return global;
|
|
91
|
-
}
|
|
144
|
+
},
|
|
92
145
|
};
|
|
93
146
|
|
|
94
|
-
contrastMethods.install = function() {
|
|
147
|
+
contrastMethods.install = function () {
|
|
95
148
|
if (contrastMethods.installed) {
|
|
96
149
|
return;
|
|
97
150
|
}
|
|
@@ -102,15 +155,15 @@ module.exports = function(core) {
|
|
|
102
155
|
Object.defineProperty(global, 'ContrastMethods', {
|
|
103
156
|
enumerable: true,
|
|
104
157
|
configurable: false,
|
|
105
|
-
value: contrastMethods.api
|
|
158
|
+
value: contrastMethods.api,
|
|
106
159
|
});
|
|
107
160
|
contrastMethods.installed = true;
|
|
108
161
|
} catch (err) {
|
|
109
162
|
// We should never expect this since the installation process is well
|
|
110
163
|
// controlled, but still we should have the defensive code.
|
|
111
|
-
logger.error({ err }, 'Unable to
|
|
164
|
+
logger.error({ err }, 'Unable to inject global.ContrastMethods');
|
|
112
165
|
}
|
|
113
166
|
};
|
|
114
167
|
|
|
115
|
-
return core.contrastMethods = contrastMethods;
|
|
168
|
+
return (core.contrastMethods = contrastMethods);
|
|
116
169
|
};
|
package/lib/function-hooks.js
CHANGED
|
@@ -81,7 +81,7 @@ module.exports = function (deps) {
|
|
|
81
81
|
unwritten = rewriter.unwrite(unwritten);
|
|
82
82
|
unwritten = unwritten.replace(METHOD_CONTEXT, '');
|
|
83
83
|
unwritten = unwritten.replace(FUNCTION_CONTEXT, '');
|
|
84
|
-
unwritten = unwritten.replace(
|
|
84
|
+
unwritten = unwritten.replace(/;\s*$/, ''); // removes trailing semicolon/whitespace
|
|
85
85
|
return unwritten;
|
|
86
86
|
} catch (err) {
|
|
87
87
|
logger.warn({ err, code }, 'Failed to unwrite function code');
|
package/lib/index.js
CHANGED
|
@@ -31,7 +31,8 @@ const defaultOpts = {
|
|
|
31
31
|
'assess',
|
|
32
32
|
'protect',
|
|
33
33
|
'depHooks',
|
|
34
|
-
'
|
|
34
|
+
'routeCoverage',
|
|
35
|
+
'libraryAnalysis',
|
|
35
36
|
'rewriteHooks',
|
|
36
37
|
'functionHooks'
|
|
37
38
|
]
|
|
@@ -106,7 +107,7 @@ class Agent {
|
|
|
106
107
|
await self.handleInstallFailure(err);
|
|
107
108
|
}
|
|
108
109
|
|
|
109
|
-
self.
|
|
110
|
+
self.logDiagnosticFiles();
|
|
110
111
|
return self.runMain.apply(this, args);
|
|
111
112
|
};
|
|
112
113
|
}
|
|
@@ -135,29 +136,39 @@ class Agent {
|
|
|
135
136
|
}
|
|
136
137
|
}
|
|
137
138
|
|
|
138
|
-
|
|
139
|
-
const { config, getEffectiveConfig } = this.core;
|
|
139
|
+
logDiagnosticFiles() {
|
|
140
|
+
const { agentName, agentVersion, config, getEffectiveConfig, getSystemInfo } = this.core;
|
|
140
141
|
|
|
141
|
-
if (config.
|
|
142
|
-
const
|
|
142
|
+
if (config.agent.diagnostics.enable !== false) {
|
|
143
|
+
const effectiveConfig = JSON.stringify(getEffectiveConfig(), null, 2).concat('\n\n');
|
|
143
144
|
|
|
144
|
-
|
|
145
|
-
|
|
145
|
+
let systemInfo = getSystemInfo();
|
|
146
|
+
systemInfo.Contrast.Agent = {
|
|
147
|
+
Name: agentName,
|
|
148
|
+
Version: agentVersion,
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
systemInfo = JSON.stringify(systemInfo, null, 2).concat('\n\n');
|
|
152
|
+
if (!config.agent.diagnostics.quiet) {
|
|
153
|
+
fs.writeFileSync(1, effectiveConfig, 'utf8');
|
|
154
|
+
fs.writeFileSync(1, systemInfo, 'utf8');
|
|
146
155
|
}
|
|
147
156
|
|
|
148
|
-
let outputDir = config.
|
|
157
|
+
let outputDir = config.agent.diagnostics.report_path;
|
|
149
158
|
if (!outputDir && config.agent.logger.path) {
|
|
150
|
-
outputDir = path.join(config.agent.logger.path, '
|
|
159
|
+
outputDir = path.join(config.agent.logger.path, '..');
|
|
151
160
|
}
|
|
152
161
|
|
|
153
162
|
try {
|
|
154
|
-
fs.writeFileSync(outputDir,
|
|
163
|
+
fs.writeFileSync(path.join(outputDir, 'contrast_effective_config.json'), effectiveConfig, 'utf-8');
|
|
164
|
+
fs.writeFileSync(path.join(outputDir, 'contrast_system_info.json'), systemInfo, 'utf-8');
|
|
155
165
|
} catch (err) {
|
|
156
|
-
outputDir = path.join(process.cwd()
|
|
166
|
+
outputDir = path.join(process.cwd());
|
|
157
167
|
try {
|
|
158
|
-
fs.writeFileSync(outputDir,
|
|
168
|
+
fs.writeFileSync(path.join(outputDir, 'contrast_effective_config.json'), effectiveConfig, 'utf-8');
|
|
169
|
+
fs.writeFileSync(path.join(outputDir, 'contrast_system_info.json'), systemInfo, 'utf-8');
|
|
159
170
|
} catch (err) {
|
|
160
|
-
fs.writeFileSync(1, `Couldn't create
|
|
171
|
+
fs.writeFileSync(1, `Couldn't create the diagnostic files: ${err}`, 'utf-8');
|
|
161
172
|
}
|
|
162
173
|
}
|
|
163
174
|
}
|
package/lib/rewrite-hooks.js
CHANGED
|
@@ -27,7 +27,12 @@ module.exports = function(deps) {
|
|
|
27
27
|
|
|
28
28
|
Module.prototype._compile = function(content, filename) {
|
|
29
29
|
let compiled;
|
|
30
|
-
const { code } = deps.rewriter.rewrite(content, {
|
|
30
|
+
const { code } = deps.rewriter.rewrite(content, {
|
|
31
|
+
filename,
|
|
32
|
+
isModule: false,
|
|
33
|
+
inject: true,
|
|
34
|
+
wrap: true,
|
|
35
|
+
});
|
|
31
36
|
|
|
32
37
|
try {
|
|
33
38
|
compiled = origCompile.call(this, code, filename);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@contrast/agentify",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.1",
|
|
4
4
|
"description": "Configures Contrast agent services and instrumentation within an application",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE",
|
|
6
6
|
"author": "Contrast Security <nodejs@contrastsecurity.com> (https://www.contrastsecurity.com)",
|
|
@@ -16,4 +16,4 @@
|
|
|
16
16
|
"scripts": {
|
|
17
17
|
"test": "../scripts/test.sh"
|
|
18
18
|
}
|
|
19
|
-
}
|
|
19
|
+
}
|