@contrast/agent 4.25.4 → 4.25.6-beta.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.
@@ -20,7 +20,7 @@ const tracker = require('../../tracker');
20
20
  const stackFactory = require('../../core/stacktrace').singleton;
21
21
  const { PROXY_TARGET } = require('../../../lib/constants');
22
22
  const TagRange = require('../models/tag-range');
23
- const { toUntrackedString } = require('../utils');
23
+ const distringuish = require('@contrast/distringuish');
24
24
 
25
25
  /**
26
26
  * Holds information about the call context of a function
@@ -126,7 +126,10 @@ function getDisplayRange(arg, orgArg = arg, iteration = 0) {
126
126
  */
127
127
  function valueString(value) {
128
128
  if (_.isString(value)) {
129
- return toUntrackedString(value);
129
+ if (distringuish.isExternal(value.valueOf())) {
130
+ return distringuish.internalize(value.valueOf());
131
+ }
132
+ return value.valueOf();
130
133
  }
131
134
 
132
135
  if (_.isNumber(value)) {
@@ -156,23 +159,7 @@ function create(params) {
156
159
  constructorOpt: params.hooked
157
160
  });
158
161
 
159
- let stack;
160
-
161
- // If this occurs within the constructor it will leak all references within
162
- // the snapshot's closure.
163
- Object.defineProperty(instance, 'stack', {
164
- enumerable: true,
165
- configurable: true,
166
- get() {
167
- if (!stack) {
168
- stack = snapshot();
169
- }
170
- return stack;
171
- },
172
- set(value) {
173
- stack = value;
174
- }
175
- });
162
+ instance.stack = typeof snapshot === 'function' ? snapshot() : snapshot;
176
163
 
177
164
  return instance;
178
165
  }
@@ -37,7 +37,7 @@ const util = module.exports;
37
37
  * @param {*} value
38
38
  * @param {boolean} def set from default or not
39
39
  */
40
- function set(conf, name, value, def) {
40
+ function set(conf, name, value, def, origin) {
41
41
  // use _.set so we can nest properties for names like 'application.vulnerability.tags'
42
42
  // and ensure 'var t = config.application.vulnerability.tags' is not going
43
43
  // to throw anything like 'can't read property tagRanges of undefined'
@@ -47,6 +47,7 @@ function set(conf, name, value, def) {
47
47
  if (!name.startsWith('api.')) {
48
48
  conf._flat[name] = value;
49
49
  }
50
+ conf._sources[name] = origin;
50
51
  }
51
52
 
52
53
  class ConfigurationError extends Error {
@@ -59,6 +60,7 @@ class Config {
59
60
  constructor() {
60
61
  this._default = {};
61
62
  this._flat = {};
63
+ this._sources = {};
62
64
 
63
65
  // all properties on node.agent should always exist, so that
64
66
  // no code needs to check whether they exist or not. this rule
@@ -87,6 +89,10 @@ class Config {
87
89
  return this._default[name];
88
90
  }
89
91
 
92
+ getOrigin(name) {
93
+ return this._sources[name];
94
+ }
95
+
90
96
  query(name) {
91
97
  const isDefault = this.isDefault(name);
92
98
  const value = this.get(name);
@@ -188,9 +194,8 @@ function readConfig(cliOptions, logger) {
188
194
  let fileContents;
189
195
 
190
196
  if (configPath) {
191
- cliOptions.configFile = path.resolve(configPath);
192
197
  try {
193
- fileContents = fs.readFileSync(cliOptions.configFile, 'utf-8');
198
+ fileContents = fs.readFileSync(path.resolve(configPath), 'utf-8');
194
199
  } catch (e) {
195
200
  logger.error(`Unable to read config file. ${e.message}`);
196
201
  }
@@ -211,7 +216,7 @@ function readConfig(cliOptions, logger) {
211
216
  }
212
217
  }
213
218
 
214
- return config;
219
+ return { config, configPath };
215
220
  }
216
221
 
217
222
  /**
@@ -221,10 +226,9 @@ function readConfig(cliOptions, logger) {
221
226
  * @param {Object} cliOptions
222
227
  * @return {Object} "un-flattened" file options
223
228
  */
224
- function getFileOptions(cliOptions, logger) {
225
- const config = readConfig(cliOptions, logger);
226
- return _.reduce(
227
- config,
229
+ util.getFileOptions = function(cliOptions, logger) {
230
+ const { config, configPath } = readConfig(cliOptions, logger);
231
+ return _.reduce({ ...config, configPath },
228
232
  (memo, value, key) => {
229
233
  // Merge if necessary,
230
234
  if (memo[key]) {
@@ -233,12 +237,11 @@ function getFileOptions(cliOptions, logger) {
233
237
  // but otherwise set the config path.
234
238
  _.set(memo, key, value);
235
239
  }
236
-
237
240
  return memo;
238
241
  },
239
242
  {}
240
243
  );
241
- }
244
+ };
242
245
 
243
246
  /**
244
247
  * only set autoEnv if it's a common config option
@@ -256,8 +259,9 @@ function getAutoEnv(name) {
256
259
  * @return {Config} merged options
257
260
  */
258
261
  function mergeCliOptions(cliOptions, logger) {
259
- const fileOptions = getFileOptions(cliOptions, logger);
262
+ const fileOptions = util.getFileOptions(cliOptions, logger);
260
263
 
264
+ // eslint-disable-next-line complexity
261
265
  return configOptions.reduce((options, option) => {
262
266
  const {
263
267
  default: optDefault,
@@ -273,12 +277,26 @@ function mergeCliOptions(cliOptions, logger) {
273
277
  const fileFlag = _.get(fileOptions, name);
274
278
 
275
279
  // For some values, we want to know if we assigned by falling back to default
276
- let isFromDefault;
277
-
278
280
  // cli > env > file > default
281
+ let isFromDefault, origin;
282
+
283
+ if (cliFlag != null) {
284
+ origin = 'CLI';
285
+ } else if (env != null || autoEnv != null) {
286
+ origin = 'ENV';
287
+ } else if (fileFlag != null) {
288
+ origin = 'YAML';
289
+ }
290
+
279
291
  let value = [cliFlag, env, autoEnv, fileFlag]
280
- .map((v) => fn(v, logger))
281
- .find((flag) => flag !== undefined);
292
+ .map((v) => fn(v, logger)).find((flag) => flag !== undefined);
293
+
294
+ // This is kind of a special case. We never set a default value for it so
295
+ // if we want to see it in the config, it needs to be set explicitly
296
+ if (name == 'configFile' && value == null) {
297
+ value = fileOptions.configPath;
298
+ origin = 'DEFAULT';
299
+ }
282
300
 
283
301
  // if it's an enum, find it in the enum or set the value to default
284
302
  // ineffective if optDefault wasn't in the enum;
@@ -288,6 +306,7 @@ function mergeCliOptions(cliOptions, logger) {
288
306
  if (optEnum && optEnum.indexOf(value) === -1) {
289
307
  value = fn(optDefault, logger);
290
308
  isFromDefault = true;
309
+ origin = 'DEFAULT';
291
310
  }
292
311
 
293
312
  // set default last and separately, so that we can mark that the option was
@@ -297,12 +316,12 @@ function mergeCliOptions(cliOptions, logger) {
297
316
  logger.error("Missing required option '%s'", name);
298
317
  return options;
299
318
  }
300
-
301
319
  value = fn(optDefault, logger);
302
320
  isFromDefault = true;
321
+ origin = 'DEFAULT';
303
322
  }
323
+ set(options, name, value, isFromDefault, origin);
304
324
 
305
- set(options, name, value, isFromDefault);
306
325
  return options;
307
326
  }, new Config());
308
327
  }
package/lib/tracker.js CHANGED
@@ -132,6 +132,14 @@ class Tracker {
132
132
  */
133
133
  untrack(str) {
134
134
  if (typeof str === 'string') {
135
+ const props = distringuish.getProperties(str);
136
+ if (props) {
137
+ Object.assign(props, {
138
+ event: null,
139
+ tagRanges: [],
140
+ tracked: false,
141
+ });
142
+ }
135
143
  return distringuish.internalize(str);
136
144
  }
137
145
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contrast/agent",
3
- "version": "4.25.4",
3
+ "version": "4.25.6-beta.0",
4
4
  "description": "Node.js security instrumentation by Contrast Security",
5
5
  "keywords": [
6
6
  "security",
@@ -77,7 +77,7 @@
77
77
  "@babel/traverse": "^7.12.1",
78
78
  "@babel/types": "^7.12.1",
79
79
  "@contrast/agent-lib": "^4.3.0",
80
- "@contrast/distringuish": "^4.0.0",
80
+ "@contrast/distringuish": "^4.2.1",
81
81
  "@contrast/flat": "^4.1.1",
82
82
  "@contrast/fn-inspect": "^3.1.0",
83
83
  "@contrast/protobuf-api": "^3.2.5",