[Logger] Strip ANSI escape codes from the message (#164337)

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Alejandro Fernández Haro 2023-08-25 11:53:57 +02:00 committed by GitHub
parent 4297b8708e
commit 4b88b10b0f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 77 additions and 4 deletions

View file

@ -806,6 +806,7 @@
"JSONStream": "1.3.5",
"adm-zip": "^0.5.9",
"ajv": "^8.12.0",
"ansi-regex": "^5.0.1",
"antlr4ts": "^0.5.0-alpha.3",
"archiver": "^5.3.1",
"async": "^3.2.3",

View file

@ -0,0 +1,48 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import { LogLevel, LogRecord } from '@kbn/logging';
import { MessageConversion } from './message';
const baseRecord: LogRecord = {
pid: 1,
timestamp: new Date(),
level: LogLevel.Info,
context: '',
message: '',
};
describe('MessageConversion', () => {
test('it should keep break lines', () => {
expect(
MessageConversion.convert({ ...baseRecord, message: 'Hi!\nHow are you?' }, false)
).toEqual('Hi!\nHow are you?');
});
test('it should remove ANSI chars lines from the message', () => {
expect(
MessageConversion.convert(
{ ...baseRecord, message: 'Blinking...\u001b[5;7;6mThis is Fine\u001b[27m' },
false
)
).toEqual('Blinking...This is Fine');
});
test('it should remove any unicode injection from the message', () => {
expect(
MessageConversion.convert(
{
...baseRecord,
message:
'\u001b[31mESC-INJECTION-LFUNICODE:\u001b[32mSUCCESSFUL\u001b[0m\u0007\n\nInjecting 10.000 lols 😂\u001b[10000;b\u0007',
},
false
)
).toEqual('ESC-INJECTION-LFUNICODE:SUCCESSFUL\n\nInjecting 10.000 lols 😂');
});
});

View file

@ -6,13 +6,20 @@
* Side Public License, v 1.
*/
import ansiRegex from 'ansi-regex';
import { LogRecord } from '@kbn/logging';
import { Conversion } from './types';
// Defining it globally because it's more performant than creating for each log entry
// We can reuse the same global RegExp here because `.replace()` automatically resets the `.lastIndex` of the RegExp.
const ANSI_ESCAPE_CODES_REGEXP = ansiRegex();
export const MessageConversion: Conversion = {
pattern: /%message/g,
convert(record: LogRecord) {
// Error stack is much more useful than just the message.
return (record.error && record.error.stack) || record.message;
const str = record.error?.stack || record.message;
// We need to validate it's a string because, despite types, there are use case where it's not a string :/
return typeof str === 'string' ? str.replace(ANSI_ESCAPE_CODES_REGEXP, '') : str;
},
};

View file

@ -139,6 +139,24 @@
"enabled": true,
"prCreation": "immediate"
},
{
"groupName": "ansi-regex",
"matchPackageNames": [
"ansi-regex"
],
"reviewers": [
"team:kibana-core"
],
"matchBaseBranches": [
"main"
],
"labels": [
"release_note:skip",
"Team:Core",
"backport:skip"
],
"enabled": true
},
{
"groupName": "babel",
"matchPackageNames": [
@ -592,4 +610,4 @@
"enabled": true
}
]
}
}

View file

@ -6,8 +6,7 @@
*/
import stripAnsi from 'strip-ansi';
// eslint-disable-next-line import/no-extraneous-dependencies
import ansiRegex from 'ansi-regex'; // its a dependency of `strip-ansi` so it should be fine
import ansiRegex from 'ansi-regex';
import { blue } from 'chalk';
import { DataFormatter } from './data_formatter';
import { SCREEN_ROW_MAX_WIDTH } from './constants';