Skip to content

Commit

Permalink
Merge pull request #247 from pulsar-edit/additional-safety-filters
Browse files Browse the repository at this point in the history
Ensure sensitive details are never logged via CallStack
  • Loading branch information
confused-Techie authored Mar 27, 2024
2 parents 8c6d2a8 + 8186d21 commit ccb9989
Show file tree
Hide file tree
Showing 2 changed files with 134 additions and 11 deletions.
63 changes: 52 additions & 11 deletions src/models/callStack.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,23 +20,64 @@ module.exports = class CallStack {

// Attempts to remove any sensitive data that may be found within
sanitize(content) {
if (typeof content !== "object") {
return content;
}

const badKeys = [
"token",
"password",
"pass",
"auth",
"secret",
"passphrase",
"card"
];
const githubTokenReg = /(?:gho_|ghp_|github_pat_|ghu_|ghs_|ghr_)/;
const hideString = "*****";
let outContent = {};
let type = typeof content;

for (const key in content) {
switch (key) {
case "token":
outContent[key] = "*****";
break;
default:
outContent[key] = content[key];
break;
// Since JavaScript `typeof` will assign an array as "object" as well as null
// we will extend this typeof check to add those as different types, to ease
// the complexity of the below switch statement
if (type === "object") {
if (Array.isArray(content)) {
type = "array";
} else if (content === null) {
type = "null";
}
}

switch(type) {
case "object":
for (const key in content) {
// Match different possible keys that represent sensitive data
if (badKeys.includes(key)) {
outContent[key] = hideString;
} else {
outContent[key] = this.sanitize(content[key]);
}
}
break;
case "string":
// Match different strings of sensitive data

// https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/about-authentication-to-github#githubs-token-formats
if (githubTokenReg.test(content)) {
outContent = hideString;
} else { // More strings to test can be added here
// String seems safe
outContent = content;
}
break;
case "array":
outContent = [];
for (let i = 0; i < content.length; i++) {
outContent.push(this.sanitize(content[i]));
}
break;
default:
outContent = content;
}

return outContent;
}
};
82 changes: 82 additions & 0 deletions tests/unit/models/callStack.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
const callStack = require("../../../src/models/callStack.js");
const hideValue = "*****";

describe("Sanitizes content as expected", () => {
test("Leaves safe data unmodified", () => {
const cs = new callStack();

const before = {
value: "Safe data"
};

const after = cs.sanitize(before);

expect(after).toEqual(before);
});

test("Removes value of a key starting with 'token'", () => {
const cs = new callStack();

const before = {
token: "super_secret"
};

const after = cs.sanitize(before);

expect(after).toEqual({ token: hideValue });
});

test("Removes value of an unsafe string", () => {
const cs = new callStack();

const before = "gho_value";

const after = cs.sanitize(before);

expect(after).toEqual(hideValue);
});

test("Removes deeply nested unsafe string", () => {
const cs = new callStack();

const before = { value: { value: { value: { value: "github_pat_value" }}}};

const after = cs.sanitize(before);

expect(after).toEqual({ value: { value: { value: { value: hideValue }}}});
});

test("Removes unsafe value from array", () => {
const cs = new callStack();

const before = [{}, {}, { token: "super_secret" }];
const after = cs.sanitize(before);

expect(after).toEqual([{}, {}, { token: hideValue }]);
});

test("Doesn't break on 'null'", () => {
const cs = new callStack();

const before = null;
const after = cs.sanitize(before);

expect(after).toEqual(null);
});

test("Removes all known github token formats", () => {
const cs = new callStack();

const before = [
{ v1: "ghp_personal_access_token_classic" },
{ v2: "github_pat_fine_grained_personal_access_token" },
{ v3: "gho_oauth_access_token" },
{ v4: "ghu_user_access_token_for_github_app" },
{ v5: "ghs_installation_access_token" },
{ v6: "ghr_refresh_token_for_github_app" }
];
const after = cs.sanitize(before);

expect(after).toEqual([{v1: hideValue}, {v2: hideValue}, {v3: hideValue}, {v4: hideValue}, {v5: hideValue}, {v6: hideValue}]);
});
});

0 comments on commit ccb9989

Please sign in to comment.