UNPKG

7.54 kBJavaScriptView Raw
1"use strict";
2var __importDefault = (this && this.__importDefault) || function (mod) {
3 return (mod && mod.__esModule) ? mod : { "default": mod };
4};
5var __importStar = (this && this.__importStar) || function (mod) {
6 if (mod && mod.__esModule) return mod;
7 var result = {};
8 if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
9 result["default"] = mod;
10 return result;
11};
12Object.defineProperty(exports, "__esModule", { value: true });
13const find_up_1 = __importDefault(require("find-up"));
14const fp_ts_1 = require("fp-ts");
15const path = __importStar(require("path"));
16const ANONYMIZED_FILE = "<user-file>";
17class Anonymizer {
18 constructor(_configPath) {
19 this._configPath = _configPath;
20 }
21 /**
22 * Given a sentry serialized exception
23 * (https://develop.sentry.dev/sdk/event-payloads/exception/), return an
24 * anonymized version of the event.
25 */
26 anonymize(event) {
27 if (event === null || event === undefined) {
28 return fp_ts_1.either.left("event is null or undefined");
29 }
30 if (typeof event !== "object") {
31 return fp_ts_1.either.left("event is not an object");
32 }
33 const result = {
34 event_id: event.event_id,
35 platform: event.platform,
36 timestamp: event.timestamp,
37 extra: event.extra,
38 };
39 if (event.exception !== undefined && event.exception.values !== undefined) {
40 const anonymizededExceptions = this._anonymizeExceptions(event.exception.values);
41 result.exception = {
42 values: anonymizededExceptions,
43 };
44 }
45 return fp_ts_1.either.right(result);
46 }
47 /**
48 * Return the anonymized filename and a boolean indicating if the content of
49 * the file should be anonymized
50 */
51 anonymizeFilename(filename) {
52 if (filename === this._configPath) {
53 const packageJsonPath = this._getFilePackageJsonPath(filename);
54 if (packageJsonPath === null) {
55 // if we can't find a package.json, we just return the basename
56 return {
57 anonymizedFilename: path.basename(filename),
58 anonymizeContent: true,
59 };
60 }
61 return {
62 anonymizedFilename: path.relative(path.dirname(packageJsonPath), filename),
63 anonymizeContent: true,
64 };
65 }
66 const parts = filename.split(path.sep);
67 const nodeModulesIndex = parts.indexOf("node_modules");
68 if (nodeModulesIndex === -1) {
69 if (filename.startsWith("internal")) {
70 // show internal parts of the stack trace
71 return {
72 anonymizedFilename: filename,
73 anonymizeContent: false,
74 };
75 }
76 // if the file isn't inside node_modules and it's a user file, we hide it completely
77 return {
78 anonymizedFilename: ANONYMIZED_FILE,
79 anonymizeContent: true,
80 };
81 }
82 return {
83 anonymizedFilename: parts.slice(nodeModulesIndex).join(path.sep),
84 anonymizeContent: false,
85 };
86 }
87 anonymizeErrorMessage(errorMessage) {
88 // the \\ before path.sep is necessary for this to work on windows
89 const pathRegex = new RegExp(`\\S+\\${path.sep}\\S+`, "g");
90 // for files that don't have a path separator
91 const fileRegex = new RegExp("\\S+\\.(js|ts)\\S*", "g");
92 // hide hex strings of 20 chars or more
93 const hexRegex = /(0x)?[0-9A-Fa-f]{20,}/g;
94 return errorMessage
95 .replace(pathRegex, ANONYMIZED_FILE)
96 .replace(fileRegex, ANONYMIZED_FILE)
97 .replace(hexRegex, (match) => match.replace(/./g, "x"));
98 }
99 raisedByBuidler(event) {
100 var _a, _b;
101 const exceptions = (_a = event === null || event === void 0 ? void 0 : event.exception) === null || _a === void 0 ? void 0 : _a.values;
102 if (exceptions === undefined) {
103 // if we can't prove that the exception doesn't come from buidler,
104 // we err on the side of reporting the error
105 return true;
106 }
107 const originalException = exceptions[exceptions.length - 1];
108 const frames = (_b = originalException === null || originalException === void 0 ? void 0 : originalException.stacktrace) === null || _b === void 0 ? void 0 : _b.frames;
109 if (frames === undefined) {
110 return true;
111 }
112 for (const frame of frames.slice().reverse()) {
113 if (frame.filename === undefined) {
114 continue;
115 }
116 // we stop after finding either a buidler file or a file from the user's
117 // project
118 if (this._isBuidlerFile(frame.filename)) {
119 return true;
120 }
121 if (frame.filename === ANONYMIZED_FILE) {
122 return false;
123 }
124 if (this._configPath !== undefined &&
125 this._configPath.includes(frame.filename)) {
126 return false;
127 }
128 }
129 // if we didn't find any buidler frame, we don't report the error
130 return false;
131 }
132 _getFilePackageJsonPath(filename) {
133 return find_up_1.default.sync("package.json", {
134 cwd: path.dirname(filename),
135 });
136 }
137 _isBuidlerFile(filename) {
138 const nomiclabsPath = path.join("node_modules", "@nomiclabs");
139 const truffleContractPath = path.join(nomiclabsPath, "truffle-contract");
140 const isBuidlerFile = filename.startsWith(nomiclabsPath) &&
141 !filename.startsWith(truffleContractPath);
142 return isBuidlerFile;
143 }
144 _anonymizeExceptions(exceptions) {
145 return exceptions.map((exception) => this._anonymizeException(exception));
146 }
147 _anonymizeException(value) {
148 const result = {
149 type: value.type,
150 };
151 if (value.value !== undefined) {
152 result.value = this.anonymizeErrorMessage(value.value);
153 }
154 if (value.stacktrace !== undefined) {
155 result.stacktrace = this._anonymizeStacktrace(value.stacktrace);
156 }
157 return result;
158 }
159 _anonymizeStacktrace(stacktrace) {
160 if (stacktrace.frames !== undefined) {
161 const anonymizededFrames = this._anonymizeFrames(stacktrace.frames);
162 return {
163 frames: anonymizededFrames,
164 };
165 }
166 return {};
167 }
168 _anonymizeFrames(frames) {
169 return frames.map((frame) => this._anonymizeFrame(frame));
170 }
171 _anonymizeFrame(frame) {
172 const result = {
173 lineno: frame.lineno,
174 colno: frame.colno,
175 function: frame.function,
176 };
177 let anonymizeContent = true;
178 if (frame.filename !== undefined) {
179 const anonymizationResult = this.anonymizeFilename(frame.filename);
180 result.filename = anonymizationResult.anonymizedFilename;
181 anonymizeContent = anonymizationResult.anonymizeContent;
182 }
183 if (!anonymizeContent) {
184 result.context_line = frame.context_line;
185 result.pre_context = frame.pre_context;
186 result.post_context = frame.post_context;
187 result.vars = frame.vars;
188 }
189 return result;
190 }
191}
192exports.Anonymizer = Anonymizer;
193//# sourceMappingURL=anonymizer.js.map
\No newline at end of file