fix(logging): write log fields without throwing and without credentials

formatLogLine wrote the fields of a log call with JSON.stringify. A
circular reference threw, so Strapi's error middleware lost the error
it was logging: the axios error of a failed PayPal token request holds
its request object, which refers to itself. An Error was written as {},
and the config.headers of an axios error carried "Authorization: Basic"
with the base64 of the PayPal client id and secret into the line.

The fields are now copied before they are written:
- a field named like a credential (authorization, cookie, password,
  secret, token, api key) is written as "[redacted]", at any depth;
- an Error is written as { name, message }, with the first line of the
  message as describeError has it, and its stack only with the stack
  option;
- an object that contains itself is written once, the reference to it
  as "[Circular]";
- an instance of a class is written as its toJSON(), or as its class
  name without one: a request object keeps its headers in _header;
- a bigint is written as its digits, an unreadable field as
  "[unreadable]".

The three todo tests of the formatter pass and are regular tests now.

Refs libretech/mp#71
Refs libretech/mp#67
This commit is contained in:
libretech committed 2026-10-09 01:41:34 +02:00
1 parent 66e5800418
commit ab071cd222
3 files changed
+203 -42

No files matched your search

+1 -1
View File
@@ -50,7 +50,7 @@ test("describes a thrown value that is not an error by its type alone", () => {
});
test("the log line of the description holds no credentials", () => {
// Compare log-format.test.ts: the line of the error object itself holds them, a known defect of the formatter.
// The formatter now also keeps them out of the line of the error object itself, see log-format.test.ts.
const line = formatLogLine({
timestamp: TIMESTAMP,
level: "error",