@workleap/logrocket 4.0.5 → 4.0.6
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/CHANGELOG.md +6 -0
- package/dist/js/createRequestSanitizer.js +5 -3
- package/dist/js/createRequestSanitizer.js.map +1 -1
- package/dist/js/createResponseSanitizer.js +5 -0
- package/dist/js/createResponseSanitizer.js.map +1 -1
- package/dist/js/sanitizeHeaders.d.ts +3 -0
- package/dist/js/sanitizeHeaders.js +32 -0
- package/dist/js/sanitizeHeaders.js.map +1 -0
- package/package.json +2 -3
- package/src/js/createRequestSanitizer.ts +2 -3
- package/src/js/createResponseSanitizer.ts +3 -0
- package/src/js/sanitizeHeaders.ts +26 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# @workleap/logrocket
|
|
2
2
|
|
|
3
|
+
## 4.0.6
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#275](https://github.com/workleap/wl-telemetry/pull/275) [`0128608`](https://github.com/workleap/wl-telemetry/commit/012860830e4e4a17dc6960c9e3d310e7aac98b8e) Thanks [@patricklafrance](https://github.com/patricklafrance)! - Redact the credential headers of the network requests and responses recorded in LogRocket session replays, regardless of the casing of the header name. A header is now redacted when its name contains `auth`, `cookie`, `token`, `session`, `secret`, `key`, `csrf`, `xsrf` or `x-honeycomb-team`. Previously, only a request header named exactly `Authorization` was redacted.
|
|
8
|
+
|
|
3
9
|
## 4.0.5
|
|
4
10
|
|
|
5
11
|
### Patch Changes
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
import { sanitizeHeaders } from "./sanitizeHeaders.js";
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
1
5
|
function createRequestSanitizer(fuzzyRequestSanitizer) {
|
|
2
6
|
return (req)=>{
|
|
3
|
-
|
|
4
|
-
req.headers["Authorization"] = "**redacted**";
|
|
5
|
-
}
|
|
7
|
+
req.headers = sanitizeHeaders(req.headers);
|
|
6
8
|
if (req.body) {
|
|
7
9
|
// Do not return the request body, which could contain sensitive information.
|
|
8
10
|
req.body = "**redacted**";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"js/createRequestSanitizer.js","sources":["../../src/js/createRequestSanitizer.ts"],"sourcesContent":["import type { LogRocketRequest } from \"./logRocketTypes.ts\";\n\n// oxlint-disable-next-line typescript/no-explicit-any\nexport type RequestSanitizerFunction = (req: LogRocketRequest) => any;\n\nexport function createRequestSanitizer(fuzzyRequestSanitizer: RequestSanitizerFunction) {\n return (req: LogRocketRequest) => {\n
|
|
1
|
+
{"version":3,"file":"js/createRequestSanitizer.js","sources":["../../src/js/createRequestSanitizer.ts"],"sourcesContent":["import type { LogRocketRequest } from \"./logRocketTypes.ts\";\nimport { sanitizeHeaders } from \"./sanitizeHeaders.ts\";\n\n// oxlint-disable-next-line typescript/no-explicit-any\nexport type RequestSanitizerFunction = (req: LogRocketRequest) => any;\n\nexport function createRequestSanitizer(fuzzyRequestSanitizer: RequestSanitizerFunction) {\n return (req: LogRocketRequest) => {\n req.headers = sanitizeHeaders(req.headers);\n\n if (req.body) {\n // Do not return the request body, which could contain sensitive information.\n req.body = \"**redacted**\";\n }\n\n return fuzzyRequestSanitizer(req);\n };\n}\n"],"names":["sanitizeHeaders","createRequestSanitizer","fuzzyRequestSanitizer","req"],"mappings":";;;AACuD;AAKhD,SAASC,uBAAuBC,qBAA+C;IAClF,OAAO,CAACC;QACJA,IAAI,OAAO,GAAGH,eAAeA,CAACG,IAAI,OAAO;QAEzC,IAAIA,IAAI,IAAI,EAAE;YACV,6EAA6E;YAC7EA,IAAI,IAAI,GAAG;QACf;QAEA,OAAOD,sBAAsBC;IACjC;AACJ"}
|
|
@@ -1,5 +1,10 @@
|
|
|
1
|
+
import { sanitizeHeaders } from "./sanitizeHeaders.js";
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
1
5
|
function createResponseSanitizer(fuzzyResponseSanitizer) {
|
|
2
6
|
return (res)=>{
|
|
7
|
+
res.headers = sanitizeHeaders(res.headers);
|
|
3
8
|
if (res.body) {
|
|
4
9
|
// Do not return the response body, which could contain sensitive information.
|
|
5
10
|
res.body = "**redacted**";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"js/createResponseSanitizer.js","sources":["../../src/js/createResponseSanitizer.ts"],"sourcesContent":["import type { LogRocketResponse } from \"./logRocketTypes.ts\";\n\n// oxlint-disable-next-line typescript/no-explicit-any\nexport type ResponseSanitizerFunction = (res: LogRocketResponse) => any;\n\nexport function createResponseSanitizer(fuzzyResponseSanitizer: ResponseSanitizerFunction) {\n return (res: LogRocketResponse) => {\n if (res.body) {\n // Do not return the response body, which could contain sensitive information.\n res.body = \"**redacted**\";\n }\n\n return fuzzyResponseSanitizer(res);\n };\n}\n"],"names":["createResponseSanitizer","fuzzyResponseSanitizer","res"],"mappings":"
|
|
1
|
+
{"version":3,"file":"js/createResponseSanitizer.js","sources":["../../src/js/createResponseSanitizer.ts"],"sourcesContent":["import type { LogRocketResponse } from \"./logRocketTypes.ts\";\nimport { sanitizeHeaders } from \"./sanitizeHeaders.ts\";\n\n// oxlint-disable-next-line typescript/no-explicit-any\nexport type ResponseSanitizerFunction = (res: LogRocketResponse) => any;\n\nexport function createResponseSanitizer(fuzzyResponseSanitizer: ResponseSanitizerFunction) {\n return (res: LogRocketResponse) => {\n res.headers = sanitizeHeaders(res.headers);\n\n if (res.body) {\n // Do not return the response body, which could contain sensitive information.\n res.body = \"**redacted**\";\n }\n\n return fuzzyResponseSanitizer(res);\n };\n}\n"],"names":["sanitizeHeaders","createResponseSanitizer","fuzzyResponseSanitizer","res"],"mappings":";;;AACuD;AAKhD,SAASC,wBAAwBC,sBAAiD;IACrF,OAAO,CAACC;QACJA,IAAI,OAAO,GAAGH,eAAeA,CAACG,IAAI,OAAO;QAEzC,IAAIA,IAAI,IAAI,EAAE;YACV,8EAA8E;YAC9EA,IAAI,IAAI,GAAG;QACf;QAEA,OAAOD,uBAAuBC;IAClC;AACJ"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
// A header is redacted when its lowercased name contains one of the following values.
|
|
2
|
+
const PrivateHeaderNames = [
|
|
3
|
+
"auth",
|
|
4
|
+
"cookie",
|
|
5
|
+
"token",
|
|
6
|
+
"session",
|
|
7
|
+
"secret",
|
|
8
|
+
"key",
|
|
9
|
+
"csrf",
|
|
10
|
+
"xsrf",
|
|
11
|
+
"x-honeycomb-team"
|
|
12
|
+
];
|
|
13
|
+
// When the headers of a fetch request are provided as an array of tuples, LogRocket indexes the headers by their position
|
|
14
|
+
// and the header name ends up in the value, e.g. { "0": "Authorization,Bearer 123" }.
|
|
15
|
+
const IndexedHeaderNameRegEx = /^\d+$/;
|
|
16
|
+
function isPrivateHeader(name) {
|
|
17
|
+
const lowercasedName = name.toLowerCase();
|
|
18
|
+
return IndexedHeaderNameRegEx.test(name) || PrivateHeaderNames.some((x)=>lowercasedName.includes(x));
|
|
19
|
+
}
|
|
20
|
+
function sanitizeHeaders(headers) {
|
|
21
|
+
const sanitizedHeaders = {};
|
|
22
|
+
if (headers !== null && typeof headers === "object") {
|
|
23
|
+
for (const [name, value] of Object.entries(headers)){
|
|
24
|
+
sanitizedHeaders[name] = isPrivateHeader(name) ? "**redacted**" : value;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return sanitizedHeaders;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export { sanitizeHeaders };
|
|
31
|
+
|
|
32
|
+
//# sourceMappingURL=sanitizeHeaders.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"js/sanitizeHeaders.js","sources":["../../src/js/sanitizeHeaders.ts"],"sourcesContent":["import type { LogRocketRequest } from \"./logRocketTypes.ts\";\n\n// A header is redacted when its lowercased name contains one of the following values.\nconst PrivateHeaderNames = [\"auth\", \"cookie\", \"token\", \"session\", \"secret\", \"key\", \"csrf\", \"xsrf\", \"x-honeycomb-team\"];\n\n// When the headers of a fetch request are provided as an array of tuples, LogRocket indexes the headers by their position\n// and the header name ends up in the value, e.g. { \"0\": \"Authorization,Bearer 123\" }.\nconst IndexedHeaderNameRegEx = /^\\d+$/;\n\nfunction isPrivateHeader(name: string) {\n const lowercasedName = name.toLowerCase();\n\n return IndexedHeaderNameRegEx.test(name) || PrivateHeaderNames.some(x => lowercasedName.includes(x));\n}\n\nexport function sanitizeHeaders(headers: unknown) {\n const sanitizedHeaders: LogRocketRequest[\"headers\"] = {};\n\n if (headers !== null && typeof headers === \"object\") {\n for (const [name, value] of Object.entries(headers)) {\n sanitizedHeaders[name] = isPrivateHeader(name) ? \"**redacted**\" : value;\n }\n }\n\n return sanitizedHeaders;\n}\n"],"names":["PrivateHeaderNames","IndexedHeaderNameRegEx","isPrivateHeader","name","lowercasedName","x","sanitizeHeaders","headers","sanitizedHeaders","value","Object"],"mappings":"AAEA,sFAAsF;AACtF,MAAMA,qBAAqB;IAAC;IAAQ;IAAU;IAAS;IAAW;IAAU;IAAO;IAAQ;IAAQ;CAAmB;AAEtH,0HAA0H;AAC1H,sFAAsF;AACtF,MAAMC,yBAAyB;AAE/B,SAASC,gBAAgBC,IAAY;IACjC,MAAMC,iBAAiBD,KAAK,WAAW;IAEvC,OAAOF,uBAAuB,IAAI,CAACE,SAASH,mBAAmB,IAAI,CAACK,CAAAA,IAAKD,eAAe,QAAQ,CAACC;AACrG;AAEO,SAASC,gBAAgBC,OAAgB;IAC5C,MAAMC,mBAAgD,CAAC;IAEvD,IAAID,YAAY,QAAQ,OAAOA,YAAY,UAAU;QACjD,KAAK,MAAM,CAACJ,MAAMM,MAAM,IAAIC,OAAO,OAAO,CAACH,SAAU;YACjDC,gBAAgB,CAACL,KAAK,GAAGD,gBAAgBC,QAAQ,iBAAiBM;QACtE;IACJ;IAEA,OAAOD;AACX"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@workleap/logrocket",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.6",
|
|
4
4
|
"description": "A package containing utilities for LogRocket.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Workleap",
|
|
@@ -30,8 +30,7 @@
|
|
|
30
30
|
},
|
|
31
31
|
"publishConfig": {
|
|
32
32
|
"access": "public",
|
|
33
|
-
"provenance": true
|
|
34
|
-
"registry": "https://registry.npmjs.org/"
|
|
33
|
+
"provenance": true
|
|
35
34
|
},
|
|
36
35
|
"dependencies": {
|
|
37
36
|
"@workleap-telemetry/core": "^2.0.7",
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import type { LogRocketRequest } from "./logRocketTypes.ts";
|
|
2
|
+
import { sanitizeHeaders } from "./sanitizeHeaders.ts";
|
|
2
3
|
|
|
3
4
|
// oxlint-disable-next-line typescript/no-explicit-any
|
|
4
5
|
export type RequestSanitizerFunction = (req: LogRocketRequest) => any;
|
|
5
6
|
|
|
6
7
|
export function createRequestSanitizer(fuzzyRequestSanitizer: RequestSanitizerFunction) {
|
|
7
8
|
return (req: LogRocketRequest) => {
|
|
8
|
-
|
|
9
|
-
req.headers["Authorization"] = "**redacted**";
|
|
10
|
-
}
|
|
9
|
+
req.headers = sanitizeHeaders(req.headers);
|
|
11
10
|
|
|
12
11
|
if (req.body) {
|
|
13
12
|
// Do not return the request body, which could contain sensitive information.
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import type { LogRocketResponse } from "./logRocketTypes.ts";
|
|
2
|
+
import { sanitizeHeaders } from "./sanitizeHeaders.ts";
|
|
2
3
|
|
|
3
4
|
// oxlint-disable-next-line typescript/no-explicit-any
|
|
4
5
|
export type ResponseSanitizerFunction = (res: LogRocketResponse) => any;
|
|
5
6
|
|
|
6
7
|
export function createResponseSanitizer(fuzzyResponseSanitizer: ResponseSanitizerFunction) {
|
|
7
8
|
return (res: LogRocketResponse) => {
|
|
9
|
+
res.headers = sanitizeHeaders(res.headers);
|
|
10
|
+
|
|
8
11
|
if (res.body) {
|
|
9
12
|
// Do not return the response body, which could contain sensitive information.
|
|
10
13
|
res.body = "**redacted**";
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { LogRocketRequest } from "./logRocketTypes.ts";
|
|
2
|
+
|
|
3
|
+
// A header is redacted when its lowercased name contains one of the following values.
|
|
4
|
+
const PrivateHeaderNames = ["auth", "cookie", "token", "session", "secret", "key", "csrf", "xsrf", "x-honeycomb-team"];
|
|
5
|
+
|
|
6
|
+
// When the headers of a fetch request are provided as an array of tuples, LogRocket indexes the headers by their position
|
|
7
|
+
// and the header name ends up in the value, e.g. { "0": "Authorization,Bearer 123" }.
|
|
8
|
+
const IndexedHeaderNameRegEx = /^\d+$/;
|
|
9
|
+
|
|
10
|
+
function isPrivateHeader(name: string) {
|
|
11
|
+
const lowercasedName = name.toLowerCase();
|
|
12
|
+
|
|
13
|
+
return IndexedHeaderNameRegEx.test(name) || PrivateHeaderNames.some(x => lowercasedName.includes(x));
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function sanitizeHeaders(headers: unknown) {
|
|
17
|
+
const sanitizedHeaders: LogRocketRequest["headers"] = {};
|
|
18
|
+
|
|
19
|
+
if (headers !== null && typeof headers === "object") {
|
|
20
|
+
for (const [name, value] of Object.entries(headers)) {
|
|
21
|
+
sanitizedHeaders[name] = isPrivateHeader(name) ? "**redacted**" : value;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return sanitizedHeaders;
|
|
26
|
+
}
|