mirror of
https://github.com/appium/appium.git
synced 2026-10-17 04:41:24 +08:00
fix(logger): mask secure values surrounded by non-word characters (#22553)
`\b` only asserts a boundary next to a word character, so text rules like `P@ssw0rd!` never matched anything. Now it is only added to the sides where the value itself begins or ends with a word character.
This commit is contained in:
@@ -34,7 +34,7 @@ export class SecureValuesPreprocessor {
|
||||
if (rule.length === 0) {
|
||||
throw new Error(`${JSON.stringify(rule)} -> The value must not be empty`);
|
||||
}
|
||||
pattern = `\\b${escapeRegExp(rule)}\\b`;
|
||||
pattern = toExactMatchPattern(rule);
|
||||
} else if (isPlainObject(rule)) {
|
||||
if (isLogFilterRegex(rule)) {
|
||||
if (typeof rule.pattern !== 'string' || rule.pattern.length === 0) {
|
||||
@@ -45,7 +45,7 @@ export class SecureValuesPreprocessor {
|
||||
if (typeof rule.text !== 'string' || rule.text.length === 0) {
|
||||
throw new Error(`${JSON.stringify(rule)} -> The value of 'text' must be a valid non-empty string`);
|
||||
}
|
||||
pattern = `\\b${escapeRegExp(rule.text)}\\b`;
|
||||
pattern = toExactMatchPattern(rule.text);
|
||||
}
|
||||
if (!pattern) {
|
||||
throw new Error(`${JSON.stringify(rule)} -> Must either have a field named 'pattern' or 'text'`);
|
||||
@@ -136,3 +136,20 @@ export class SecureValuesPreprocessor {
|
||||
function isLogFilterRegex(value: object): value is LogFilterRegex {
|
||||
return 'pattern' in value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms the given text to a pattern, which does not match if the
|
||||
* text is only a part of a longer word.
|
||||
*
|
||||
* `\b` only asserts a boundary next to a word character, so it is only added
|
||||
* to the sides where the text itself begins or ends with one. Otherwise values
|
||||
* like `P@ssw0rd!` would never match anything.
|
||||
*
|
||||
* @param {string} text The text to match
|
||||
* @returns {string} The resulting regular expression source
|
||||
*/
|
||||
function toExactMatchPattern(text: string): string {
|
||||
const prefix = /^\w/.test(text) ? '\\b' : '';
|
||||
const suffix = /\w$/.test(text) ? '\\b' : '';
|
||||
return `${prefix}${escapeRegExp(text)}${suffix}`;
|
||||
}
|
||||
|
||||
@@ -59,6 +59,28 @@ describe('Log Internals', function () {
|
||||
expect(preprocessor.preprocess(':yolo" yo Yolo yyolo')).to.eql(`:${replacer}" yo ${replacer} yyolo`);
|
||||
});
|
||||
|
||||
it('should preprocess values starting or ending with non-word characters', async function () {
|
||||
const issues = await preprocessor.loadRules(['P@ssw0rd!', '+15550100', '#hunter2']);
|
||||
expect(issues.length).to.eql(0);
|
||||
const replacer = preprocessor.rules[0].replacer;
|
||||
expect(preprocessor.preprocess('P@ssw0rd! call +15550100 tag #hunter2')).to.eql(
|
||||
`${replacer} call ${replacer} tag ${replacer}`,
|
||||
);
|
||||
});
|
||||
|
||||
it(`should preprocess a value with non-word characters given as 'text'`, async function () {
|
||||
const issues = await preprocessor.loadRules([{text: '$ecret'}]);
|
||||
expect(issues.length).to.eql(0);
|
||||
const replacer = preprocessor.rules[0].replacer;
|
||||
expect(preprocessor.preprocess('the token is $ecret')).to.eql(`the token is ${replacer}`);
|
||||
});
|
||||
|
||||
it('should not preprocess a value which is a part of a longer word', async function () {
|
||||
const issues = await preprocessor.loadRules(['yolo']);
|
||||
expect(issues.length).to.eql(0);
|
||||
expect(preprocessor.preprocess('yolos yyolo')).to.eql('yolos yyolo');
|
||||
});
|
||||
|
||||
it('should leave the string unchanged if all rules have issues', async function () {
|
||||
const replacer2 = '***';
|
||||
const issues = await preprocessor.loadRules([null, {flags: 'i'}, {pattern: '^:(', replacer: replacer2}] as any);
|
||||
|
||||
Reference in New Issue
Block a user