Update dependency @larvit/log to v2.5.0 #238

Merged
renovate-bot merged 1 commits from renovate/larvit-log-2.x into main 2026-11-11 05:35:26 +01:00
Collaborator

This PR contains the following updates:

Package Change Age Confidence
@larvit/log 2.4.0 → 2.5.0 age confidence

Release Notes

larvit/log (@​larvit/log)

v2.5.0

Compare Source

Rotate the credentials that several Security entries name: earlier versions exported them. One
exposure stays open: keep credentials out of a url you base64-encode into a request path.
Fewer ways for a credential to reach a span: a url nested in the request path, a header Elastic
APM's rule names, a query key Datadog's rule names, userinfo in more spellings, and the url in a
span's status message all record REDACTED. A batch survives a failed send, a full queue and a
throwing storage, and no longer holds the process open. The text format writes the time to the
millisecond, and resolveFormatter is new. README → Audience now promises only that a credential
records REDACTED in the shapes README → Credentials in a captured value lists.

Security
  • Keep credentials out of a url you base64-encode into a request path: url.full exports it as
    written.
    An image proxy such as imgproxy takes its source url this way. log.fetch still
    exports any credential in that url, on every such call, as it has since v2.3.0. Send such a
    request with the global fetch, which records no span, or keep the credential out of the url.
    Search url.full in spans from any version for aHR0c, which finds such a url where the encoded
    text starts with http, and rotate any credential a hit holds.
  • url.full records REDACTED for a url nested in the request path, raw or percent-encoded.
    Since v2.3.0, log.fetch("https://proxy.test/fetch/https://user:pass@cb.test/x") — the shape a
    fetch-through, CORS or image proxy takes — exported the password in url.full with no capture
    option involved, and a signed url percent-encoded into the path exported its signature. Now the
    path records REDACTED from the first segment starting with a scheme and opening a url that holds a
    credential, at any depth of percent-encoding: https://proxy.test/fetch/REDACTED. It also records
    REDACTED from the first segment holding a query key that names a credential, wherever the
    nested url sits: /fetch/s3.test/k%3Fsig%3D… records /fetch/s3.test/REDACTED, and
    /a/x=https:%2F%2Fcb.test%2Fx%3Fpassword%3D… records /a/REDACTED; so does a matrix
    parameter such as /m/img;sig=…/x.png, which records /m/REDACTED. A path showing userinfo
    after //, \\, /\ or \/, raw or percent-encoded, such as /users//bob@x.test, records
    /REDACTED whole, and so does one percent-encoded more than eight times. A dashboard grouping on
    url.full sees such a path change, and some paths holding no credential too: a nested url's
    ?key= lookup cuts the path, and so does a ninth nested url. Rotate what such a path carried in
    spans an earlier version exported, as v2.4.0 says.
  • An invalid otlpAdditionalHeaders name is reported by its position, never by the name. Since
    v2.4.0, a whole header line pasted as a name, such as { "Authorization: Bearer …": "" }, wrote
    the token in the queue's OTLP export headers invalid, batch dropped report, to stderr or your
    report. Now a name that isn't a valid header name reports as
    otlpAdditionalHeaders carries an invalid header name at position 1 (counting from 1). Search those reports for
    carries an invalid and rotate any credential the name shows.
  • A captured header records REDACTED by Elastic APM's default sanitize_field_names rule.
    Since v2.3.0 only authorization, cookie, proxy-authorization and set-cookie did, so a
    listed x-api-key, x-auth-token or x-amz-security-token exported its value. Now a name that,
    in any casing, is passwd, password, pwd or secret, ends in key, or holds auth, card,
    credit, principal, session or token records REDACTED too, so a dashboard grouping on
    such a header sees it change, a non-secret www-authenticate or x-idempotency-key included.
    Check captureRequestHeaders and captureResponseHeaders for such a name, and rotate what it
    carried.
  • log.fetch redacts the url it fetched in its span's status message as url.full's query is
    with captureQuery on, whatever captureQuery says.
    Since v2.4.0,
    log.fetch("https://u:p@h.test/x?access_token=…") on Node or in a browser exported the token in
    the rejection the runtime quotes the url into; only the userinfo was redacted. Now the url in it
    records https://REDACTED@h.test/x?access_token=REDACTED. An end({ error }) message that is a
    url is redacted the same way, so a ?key= lookup or a ?token= cursor in one records REDACTED
    and a dashboard grouping on status messages sees it change. Search status messages with the regex
    (?i)([?&#;]|%(25)*(3f|26|23|3b))[-_]*([^&=%\s]*(auth|authentication|authorization|consumer[-_]?id|credential|key|key[-_]?id|pass|pass[-_]?phrase|p(ass)?w(or)?d[12]?|secret|sig|sign|signature|signed|token)|code|googleaccessid|id[-_]?token[-_]?hint)[-_]*(=|%(25)*3d)
    for a match followed by anything but REDACTED, and rotate what it finds.
  • Userinfo is redacted in \\ and mixed-slash spellings among other text, in a slashless url, and
    percent-encoded.
    Since v2.3.0, a captured location of https:\\u:pw@h or http:u:pw@h
    exported pw. So did https:\\u:pw@h or https:/\u:pw@h among other text in a header value, a
    kept query value such as ?next=https://my+user:pw@cb.test/x, and a url percent-encoded twice or
    more into a header value or three times or more into a query value. Since v2.4.0, either spelling
    among other text in a status message did too. Search captured header values, status messages and
    url.full with (?i)(https?:|([\\/]|%(25)*(2F|5C)){2})\S*(@|%(25)*40) and rotate any password a
    match holds; a match reading REDACTED before its @ holds none.
  • A query key that names a credential has its value redacted in a header value, a kept query key
    or value or a status message, where the rules for a parsed url left it.
    Since v2.3.0,
    location: /cb?token=…, a link: </next?access_token=…> header and a kept query value holding a
    scheme-less or protocol-relative url, such as ?src=%2F%2Fcdn.test%2Fk%3Fsig%3D…, exported the
    credential, and so did a key opening a fragment, such as an OAuth implicit-flow redirect's
    location: https://app.test/cb#access_token=…; since v2.4.0, so did an end({ error }) message
    such as node-fetch's request to …?token=… failed. Now a header value or query value holding such
    a key after a ?, &, # or ; records REDACTED whole, and a query key records it with its value. A status message records
    REDACTED in place of the value, which ends at &, # or a plain space:
    request to https://h/x?token=REDACTED failed. Text percent-encoded is read decoded up to eight
    times, and a status message holding a key only decoded, or encoded deeper, records REDACTED
    whole. A dashboard grouping on such a header, message or url.full sees it change, a ?key=
    lookup included. Search captured header values, status messages and url.full with the regex in
    the status-message entry above for a match followed by anything but REDACTED, and rotate what it
    finds.
  • captureQuery redacts a url a query key or value holds once decoded, at every level. Its
    userinfo records REDACTED in place of the whole key or value, and a matched key's value
    REDACTED in place: since v2.3.0, ?next=https%3A%2F%2Ft.test%2Fx%3Ftoken%3D… with
    captureQuery on exported the token in url.full, and now records
    next=https%3A%2F%2Ft.test%2Fx%3Ftoken%3DREDACTED. A url in a key is read with its value too, as
    a proxy taking ?<url> reads it, and where that finds a credential both record REDACTED:
    ?https://t.test/x?token=… and ?https://a@b=pw@evil.test, whose userinfo runs across the =.
    ?//u:pw&w@evil.test, whose userinfo runs across the &, records
    REDACTED=REDACTED&REDACTED=REDACTED; README → Credentials in a captured value says which pairs
    such userinfo takes.
    Search url.full with
    (?i)%(25)*(3f|26|23|3b)[-_]*([^&=%]*(auth|authentication|authorization|consumer[-_]?id|credential|key|key[-_]?id|pass|pass[-_]?phrase|p(ass)?w(or)?d[12]?|secret|sig|sign|signature|signed|token)|code|googleaccessid|id[-_]?token[-_]?hint)[-_]*(=|%(25)*3d),
    and with (?i)(^|[?&])[^&=]*%(25)*2F%(25)*2F\S*%(25)*40 for a match followed by anything
    but REDACTED, and rotate what it finds; a presigned SigV4 url only while unexpired, as v2.4.0
    says.
  • captureQuery redacts userinfo holding a +, %2F, %3F or %23 in a kept query. Since v2.3.0,
    ?//u:pw+x@host, ?//u:p&a%2Fb&w@host and ?next=//my+user:pw@cb.test/x, with captureQuery
    on, exported the password in url.full: the query was read form-decoded only, where those turn
    into a space and delimiters that end userinfo. It is now read as typed too, and userinfo either
    reading finds records REDACTED. Text holding a url and later an @, with only + or %20
    between, records REDACTED too, as in ?text=Visit+https://app.test+or+mail+help@app.test, so a
    dashboard grouping on such a url.full sees it change. Search url.full with
    (?i)(//|%(25)*2F%(25)*2F)\S*(@|%(25)*40) and rotate any password a match holds.
  • captureQuery redacts the value of a query key that names a credential, by the key terms of
    Datadog's default rule.
    A key's value records REDACTED when the key, in any casing and with
    - and _ ignored, ends in a term such as token, key, secret, password or auth, or is
    code, googleaccessid or idtokenhint; README → Credentials in a captured value lists them.
    Since v2.3.0, log.fetch("https://api.test/me?access_token=…") with captureQuery on exported
    the token in url.full; search url.full with
    (?i)[?&][-_]*([^&=]*(auth|authentication|authorization|consumer[-_]?id|credential|key|key[-_]?id|pass|pass[-_]?phrase|p(ass)?w(or)?d[12]?|secret|sig|sign|signature|signed|token)|code|googleaccessid|id[-_]?token[-_]?hint)[-_]*=
    for a match followed by anything but REDACTED, and rotate what it finds. Search a spelling with
    a - or _ inside a term, such as pass_word, for itself. A value that is no secret, such as a
    key lookup, a token pagination cursor or an oauth flag, records REDACTED too, so a
    dashboard grouping on such a url.full sees it change.
  • A child or clone sending to another origin than its source's no longer inherits
    otlpAdditionalHeaders.
    Since v1.4.0 for a child and v2.2.0 for a clone,
    new Log({ parentLog, otlpHttpBaseURI: other }) sent the parent's headers, a bearer token
    included, to other; rotate any token that may have reached such a host. Set the headers on the
    child where that host should get them.
  • A Queue's storage no longer reaches a stringified log.conf or queue.conf. storage is
    non-enumerable on queue.conf, so a localStorage given as one stays out of JSON.stringify and
    of a spread; the v2.4.0 entry says what to rotate. A Queue built from { ...queue.conf } has no
    storage; pass storage to it by name.
  • A credential header sent over plain http: to a host other than localhost, 127.0.0.0/8 or
    ::1 writes one @larvit/log: warning naming the host and the header, unless the Queue sets
    the new acceptPlainHttpCredentials: true.
    A credential header is any whose name log.fetch
    redacts, such as Authorization or api-key, set by user:pass@ in otlpHttpBaseURI or in
    otlpAdditionalHeaders at any time. Each line is written once per host, header and credential
    source: to each report function, or at warn to each stderr for a queue a Log built. The
    request still goes. Rotate a credential that has crossed a network you do not trust. On one you
    do, a Log using otlpHttpBaseURI moves its otlp* options to
    otlpQueue: new Queue({ acceptPlainHttpCredentials: true, otlpHttpBaseURI }), whose report lines
    then go to that queue's report, console.error unless you pass one.
  • Userinfo holding any whitespace character but a space is redacted in text that isn't a whole
    url.
    A url parser drops a tab, newline or carriage return, so https://admin:hun<TAB>ter2@db.test/x
    has the password hunter2, and keeps any other whitespace character percent-encoded, so
    https://admin:hun<NBSP>ter2@db.test/x has the password hun%C2%A0ter2. Since v2.3.0 a captured
    header value that isn't a whole url, and since v2.4.0 a status message from end({ error }) or a
    failed log.fetch, exported such userinfo unchanged; so did url.full with captureQuery, when a
    tab sat in a query key and the @ was percent-encoded, or another such character sat in a query
    key or value. Now no whitespace character but a space ends userinfo after //, \\, /\ or
    \/: a status message records REDACTED in place of the userinfo, as in
    retry https://REDACTED@db.test/x, and a header value records REDACTED whole. Text with no
    credential in it is redacted too when such a character sits between its // and an @: //note,
    a line break and @mention. Search captured header values, status messages and url.full with
    (?i)(https?:|([\\/]|%(25)*(2F|5C)){2})[^ ]*(@|%(25)*40) and rotate any password a match holds; a
    match reading REDACTED before its @ holds none.
Everything else
  • The text format writes the time to the millisecond, as 2022-09-24T23:40:39.123Z [inf] ….
    It cut the time to whole seconds, so entries written within one second lost their order in a
    backend reading stdout. A parser of the text line sees it change; parse format: "json"
    instead, as README → Audience says.
  • README → Audience promises that a credential records REDACTED in each shape README →
    Credentials in a captured value lists.
    A minor may add a shape. A value holding no credential
    may record REDACTED, as one percent-encoded more than eight times or holding a ninth nested url
    does. A minor may change such a redaction and those limits, so the value may show again. A
    credential in any other shape exports as written, text you log and a url you base64-encode into a
    request path included.
  • README → Runtimes says a React Native app installs a URL polyfill. React Native's own URL
    and URLSearchParams throw "not implemented" from members that new Log({ otlpHttpBaseURI }),
    new Queue and log.fetch read, so those calls throw in an app with no polyfill. Nothing in the
    package changed; install one such as react-native-url-polyfill before the app's code uses it.
  • log.fetch(url, request) sends a Request passed as init with its own method, body, signal and
    other settings.
    Before, only its headers were kept, so log.fetch(url, new Request(url, { method: "POST", body })) sent a GET with no body, though the span named a POST. Now the request is the one
    fetch(url, request) sends, plus traceparent.
  • A batch whose retry was reported survives the maxItems trim. Before, a failed batch went
    back in front of the queue and the trim dropped it first, so an offline app at maxItems reported
    "OTLP export failed, will retry" for items the retry then found gone. Now the trim drops the
    oldest items behind that batch, also while entries are logged during the retry wait, and the
    batch is retried whole.
  • A batch being sent stays in storage until its send settles. Before, an entry logged during
    the send saved the queue without the batch, so a process that died then lost it.
  • A storage whose getItem throws keeps what it holds. Before, one failed read at startup
    deleted the stored queue, and the first save overwrote it. Now the queue reports "OTLP queue
    storage unreadable, stored queue kept and not written to", leaves the stored queue as it is, and
    writes nothing to it until the next start; new entries and spans are still sent from memory.
    Content that reads but isn't a list of payloads is still discarded.
  • log.enabled(level) never writes, so a library author's check emits no line. Before, an
    unknown logLevel made enabled() write the warning, and which caller warned depended on call
    order. Now only the level methods warn, once per stderr sink as before, and enabled() still
    treats an unknown logLevel as info.
  • A pending batch no longer holds a Node, Bun or Deno process open, so await end() before exit.
    A script that awaits neither end() nor flush() now exits without exporting what it queued.
    Before, a queued entry or span kept the process alive for up to batchDelayMs, and so did an
    entry logged while a successful export was in flight, after await log.flush() had returned.
  • Spans and log records export under the instrumentation scope @larvit/log, at this package's
    version.
    A span's scope was its span name, and records had none, so a query or dashboard
    grouping on the scope name sees it change; group on the span name instead.
  • user:pass@ in otlpHttpBaseURI beside an Authorization in otlpAdditionalHeaders writes
    one @larvit/log: line per report function, or per stderr for a queue a Log built, and
    throws from 3.0.0.
    The otlpAdditionalHeaders Authorization is still sent and the userinfo is
    not, as in v2.4.0. Keep one of the two.
  • resolveFormatter(conf) hands back the EntryFormatter a conf writes with. Read
    resolveFormatter(log.conf) where you read log.conf.entryFormatter, which 3.0.0 removes.
  • A 401 or 403 from the collector reports OTLP export unauthorized, batch dropped. It read
    OTLP export rejected, batch dropped, so an alert matching that text sees it change.
  • An invalid name in captureRequestHeaders or captureResponseHeaders is skipped, with one
    warn line per stderr.
    It rejected every traced call, or turned a response the runtime
    delivered into a rejection.
  • Chrome 80–84 and Firefox 74–78 parse the module again, and README → Runtimes states the browser
    floor: Chrome 80, Firefox 74 or Safari 14.
    v2.4.0 added ??=, which raised the floor to
    Chrome 85 and Firefox 79, so a bundler leaving node_modules untranspiled gave those browsers a
    SyntaxError. The build now targets ES2020, so it lowers newer syntax and rejects newer
    built-ins.

Configuration

📅 Schedule: (UTC)

  • Branch creation
    • At any time (no schedule defined)
  • Automerge
    • At any time (no schedule defined)

🚦 Automerge: Enabled.

♻ Rebasing: Whenever PR is behind base branch, or you tick the rebase/retry checkbox.

🔕 Ignore: Close this PR and you won't be reminded about this update again.


  • If you want to rebase/retry this PR, check this box

This PR has been generated by Mend Renovate CLI.

This PR contains the following updates: | Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) | |---|---|---|---| | [@larvit/log](https://github.com/larvit/log) | [`2.4.0` → `2.5.0`](https://renovatebot.com/diffs/npm/@larvit%2flog/2.4.0/2.5.0) | ![age](https://developer.mend.io/api/mc/badges/age/npm/@larvit%2flog/2.5.0?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@larvit%2flog/2.4.0/2.5.0?slim=true) | --- ### Release Notes <details> <summary>larvit/log (@&#8203;larvit/log)</summary> ### [`v2.5.0`](https://github.com/larvit/log/blob/HEAD/CHANGELOG.md#v250) [Compare Source](https://github.com/larvit/log/compare/v2.4.0...v2.5.0) Rotate the credentials that several Security entries name: earlier versions exported them. One exposure stays open: keep credentials out of a url you base64-encode into a request path. Fewer ways for a credential to reach a span: a url nested in the request path, a header Elastic APM's rule names, a query key Datadog's rule names, userinfo in more spellings, and the url in a span's status message all record `REDACTED`. A batch survives a failed send, a full queue and a throwing `storage`, and no longer holds the process open. The text format writes the time to the millisecond, and `resolveFormatter` is new. README → Audience now promises only that a credential records `REDACTED` in the shapes README → Credentials in a captured value lists. ##### Security - **Keep credentials out of a url you base64-encode into a request path: `url.full` exports it as written.** An image proxy such as imgproxy takes its source url this way. `log.fetch` still exports any credential in that url, on every such call, as it has since v2.3.0. Send such a request with the global `fetch`, which records no span, or keep the credential out of the url. Search `url.full` in spans from any version for `aHR0c`, which finds such a url where the encoded text starts with `http`, and rotate any credential a hit holds. - **`url.full` records `REDACTED` for a url nested in the request path, raw or percent-encoded.** Since v2.3.0, `log.fetch("https://proxy.test/fetch/https://user:pass@cb.test/x")` — the shape a fetch-through, CORS or image proxy takes — exported the password in `url.full` with no capture option involved, and a signed url percent-encoded into the path exported its signature. Now the path records `REDACTED` from the first segment starting with a scheme and opening a url that holds a credential, at any depth of percent-encoding: `https://proxy.test/fetch/REDACTED`. It also records `REDACTED` from the first segment holding a query key that names a credential, wherever the nested url sits: `/fetch/s3.test/k%3Fsig%3D…` records `/fetch/s3.test/REDACTED`, and `/a/x=https:%2F%2Fcb.test%2Fx%3Fpassword%3D…` records `/a/REDACTED`; so does a matrix parameter such as `/m/img;sig=…/x.png`, which records `/m/REDACTED`. A path showing userinfo after `//`, `\\`, `/\` or `\/`, raw or percent-encoded, such as `/users//bob@x.test`, records `/REDACTED` whole, and so does one percent-encoded more than eight times. A dashboard grouping on `url.full` sees such a path change, and some paths holding no credential too: a nested url's `?key=` lookup cuts the path, and so does a ninth nested url. Rotate what such a path carried in spans an earlier version exported, as v2.4.0 says. - **An invalid `otlpAdditionalHeaders` name is reported by its position, never by the name.** Since v2.4.0, a whole header line pasted as a name, such as `{ "Authorization: Bearer …": "" }`, wrote the token in the queue's `OTLP export headers invalid, batch dropped` report, to `stderr` or your `report`. Now a name that isn't a valid header name reports as `otlpAdditionalHeaders carries an invalid header name at position 1 (counting from 1)`. Search those reports for `carries an invalid` and rotate any credential the name shows. - **A captured header records `REDACTED` by Elastic APM's default `sanitize_field_names` rule.** Since v2.3.0 only `authorization`, `cookie`, `proxy-authorization` and `set-cookie` did, so a listed `x-api-key`, `x-auth-token` or `x-amz-security-token` exported its value. Now a name that, in any casing, is `passwd`, `password`, `pwd` or `secret`, ends in `key`, or holds `auth`, `card`, `credit`, `principal`, `session` or `token` records `REDACTED` too, so a dashboard grouping on such a header sees it change, a non-secret `www-authenticate` or `x-idempotency-key` included. Check `captureRequestHeaders` and `captureResponseHeaders` for such a name, and rotate what it carried. - **`log.fetch` redacts the url it fetched in its span's status message as `url.full`'s query is with `captureQuery` on, whatever `captureQuery` says.** Since v2.4.0, `log.fetch("https://u:p@h.test/x?access_token=…")` on Node or in a browser exported the token in the rejection the runtime quotes the url into; only the userinfo was redacted. Now the url in it records `https://REDACTED@h.test/x?access_token=REDACTED`. An `end({ error })` message that is a url is redacted the same way, so a `?key=` lookup or a `?token=` cursor in one records `REDACTED` and a dashboard grouping on status messages sees it change. Search status messages with the regex `(?i)([?&#;]|%(25)*(3f|26|23|3b))[-_]*([^&=%\s]*(auth|authentication|authorization|consumer[-_]?id|credential|key|key[-_]?id|pass|pass[-_]?phrase|p(ass)?w(or)?d[12]?|secret|sig|sign|signature|signed|token)|code|googleaccessid|id[-_]?token[-_]?hint)[-_]*(=|%(25)*3d)` for a match followed by anything but `REDACTED`, and rotate what it finds. - **Userinfo is redacted in `\\` and mixed-slash spellings among other text, in a slashless url, and percent-encoded.** Since v2.3.0, a captured `location` of `https:\\u:pw@h` or `http:u:pw@h` exported `pw`. So did `https:\\u:pw@h` or `https:/\u:pw@h` among other text in a header value, a kept query value such as `?next=https://my+user:pw@cb.test/x`, and a url percent-encoded twice or more into a header value or three times or more into a query value. Since v2.4.0, either spelling among other text in a status message did too. Search captured header values, status messages and `url.full` with `(?i)(https?:|([\\/]|%(25)*(2F|5C)){2})\S*(@|%(25)*40)` and rotate any password a match holds; a match reading `REDACTED` before its `@` holds none. - **A query key that names a credential has its value redacted in a header value, a kept query key or value or a status message, where the rules for a parsed url left it.** Since v2.3.0, `location: /cb?token=…`, a `link: </next?access_token=…>` header and a kept query value holding a scheme-less or protocol-relative url, such as `?src=%2F%2Fcdn.test%2Fk%3Fsig%3D…`, exported the credential, and so did a key opening a fragment, such as an OAuth implicit-flow redirect's `location: https://app.test/cb#access_token=…`; since v2.4.0, so did an `end({ error })` message such as node-fetch's `request to …?token=… failed`. Now a header value or query value holding such a key after a `?`, `&`, `#` or `;` records `REDACTED` whole, and a query key records it with its value. A status message records `REDACTED` in place of the value, which ends at `&`, `#` or a plain space: `request to https://h/x?token=REDACTED failed`. Text percent-encoded is read decoded up to eight times, and a status message holding a key only decoded, or encoded deeper, records `REDACTED` whole. A dashboard grouping on such a header, message or `url.full` sees it change, a `?key=` lookup included. Search captured header values, status messages and `url.full` with the regex in the status-message entry above for a match followed by anything but `REDACTED`, and rotate what it finds. - **`captureQuery` redacts a url a query key or value holds once decoded, at every level.** Its userinfo records `REDACTED` in place of the whole key or value, and a matched key's value `REDACTED` in place: since v2.3.0, `?next=https%3A%2F%2Ft.test%2Fx%3Ftoken%3D…` with `captureQuery` on exported the token in `url.full`, and now records `next=https%3A%2F%2Ft.test%2Fx%3Ftoken%3DREDACTED`. A url in a key is read with its value too, as a proxy taking `?<url>` reads it, and where that finds a credential both record `REDACTED`: `?https://t.test/x?token=…` and `?https://a@b=pw@evil.test`, whose userinfo runs across the `=`. `?//u:pw&w@evil.test`, whose userinfo runs across the `&`, records `REDACTED=REDACTED&REDACTED=REDACTED`; README → Credentials in a captured value says which pairs such userinfo takes. Search `url.full` with `(?i)%(25)*(3f|26|23|3b)[-_]*([^&=%]*(auth|authentication|authorization|consumer[-_]?id|credential|key|key[-_]?id|pass|pass[-_]?phrase|p(ass)?w(or)?d[12]?|secret|sig|sign|signature|signed|token)|code|googleaccessid|id[-_]?token[-_]?hint)[-_]*(=|%(25)*3d)`, and with `(?i)(^|[?&])[^&=]*%(25)*2F%(25)*2F\S*%(25)*40` for a match followed by anything but `REDACTED`, and rotate what it finds; a presigned SigV4 url only while unexpired, as v2.4.0 says. - **`captureQuery` redacts userinfo holding a `+`, `%2F`, `%3F` or `%23` in a kept query.** Since v2.3.0, `?//u:pw+x@host`, `?//u:p&a%2Fb&w@host` and `?next=//my+user:pw@cb.test/x`, with `captureQuery` on, exported the password in `url.full`: the query was read form-decoded only, where those turn into a space and delimiters that end userinfo. It is now read as typed too, and userinfo either reading finds records `REDACTED`. Text holding a url and later an `@`, with only `+` or `%20` between, records `REDACTED` too, as in `?text=Visit+https://app.test+or+mail+help@app.test`, so a dashboard grouping on such a `url.full` sees it change. Search `url.full` with `(?i)(//|%(25)*2F%(25)*2F)\S*(@|%(25)*40)` and rotate any password a match holds. - **`captureQuery` redacts the value of a query key that names a credential, by the key terms of Datadog's default rule.** A key's value records `REDACTED` when the key, in any casing and with `-` and `_` ignored, ends in a term such as `token`, `key`, `secret`, `password` or `auth`, or is `code`, `googleaccessid` or `idtokenhint`; README → Credentials in a captured value lists them. Since v2.3.0, `log.fetch("https://api.test/me?access_token=…")` with `captureQuery` on exported the token in `url.full`; search `url.full` with `(?i)[?&][-_]*([^&=]*(auth|authentication|authorization|consumer[-_]?id|credential|key|key[-_]?id|pass|pass[-_]?phrase|p(ass)?w(or)?d[12]?|secret|sig|sign|signature|signed|token)|code|googleaccessid|id[-_]?token[-_]?hint)[-_]*=` for a match followed by anything but `REDACTED`, and rotate what it finds. Search a spelling with a `-` or `_` inside a term, such as `pass_word`, for itself. A value that is no secret, such as a `key` lookup, a `token` pagination cursor or an `oauth` flag, records `REDACTED` too, so a dashboard grouping on such a `url.full` sees it change. - **A child or clone sending to another origin than its source's no longer inherits `otlpAdditionalHeaders`.** Since v1.4.0 for a child and v2.2.0 for a clone, `new Log({ parentLog, otlpHttpBaseURI: other })` sent the parent's headers, a bearer token included, to `other`; rotate any token that may have reached such a host. Set the headers on the child where that host should get them. - **A `Queue`'s `storage` no longer reaches a stringified `log.conf` or `queue.conf`.** `storage` is non-enumerable on `queue.conf`, so a `localStorage` given as one stays out of `JSON.stringify` and of a spread; the v2.4.0 entry says what to rotate. A `Queue` built from `{ ...queue.conf }` has no `storage`; pass `storage` to it by name. - **A credential header sent over plain `http:` to a host other than `localhost`, `127.0.0.0/8` or `::1` writes one `@larvit/log:` warning naming the host and the header, unless the `Queue` sets the new `acceptPlainHttpCredentials: true`.** A credential header is any whose name `log.fetch` redacts, such as `Authorization` or `api-key`, set by `user:pass@` in `otlpHttpBaseURI` or in `otlpAdditionalHeaders` at any time. Each line is written once per host, header and credential source: to each `report` function, or at `warn` to each `stderr` for a queue a `Log` built. The request still goes. Rotate a credential that has crossed a network you do not trust. On one you do, a `Log` using `otlpHttpBaseURI` moves its `otlp*` options to `otlpQueue: new Queue({ acceptPlainHttpCredentials: true, otlpHttpBaseURI })`, whose report lines then go to that queue's `report`, `console.error` unless you pass one. - **Userinfo holding any whitespace character but a space is redacted in text that isn't a whole url.** A url parser drops a tab, newline or carriage return, so `https://admin:hun<TAB>ter2@db.test/x` has the password `hunter2`, and keeps any other whitespace character percent-encoded, so `https://admin:hun<NBSP>ter2@db.test/x` has the password `hun%C2%A0ter2`. Since v2.3.0 a captured header value that isn't a whole url, and since v2.4.0 a status message from `end({ error })` or a failed `log.fetch`, exported such userinfo unchanged; so did `url.full` with `captureQuery`, when a tab sat in a query key and the `@` was percent-encoded, or another such character sat in a query key or value. Now no whitespace character but a space ends userinfo after `//`, `\\`, `/\` or `\/`: a status message records `REDACTED` in place of the userinfo, as in `retry https://REDACTED@db.test/x`, and a header value records `REDACTED` whole. Text with no credential in it is redacted too when such a character sits between its `//` and an `@`: `//note`, a line break and `@mention`. Search captured header values, status messages and `url.full` with `(?i)(https?:|([\\/]|%(25)*(2F|5C)){2})[^ ]*(@|%(25)*40)` and rotate any password a match holds; a match reading `REDACTED` before its `@` holds none. ##### Everything else - **The text format writes the time to the millisecond, as `2022-09-24T23:40:39.123Z [inf] …`.** It cut the time to whole seconds, so entries written within one second lost their order in a backend reading `stdout`. A parser of the text line sees it change; parse `format: "json"` instead, as README → Audience says. - **README → Audience promises that a credential records `REDACTED` in each shape README → Credentials in a captured value lists.** A minor may add a shape. A value holding no credential may record `REDACTED`, as one percent-encoded more than eight times or holding a ninth nested url does. A minor may change such a redaction and those limits, so the value may show again. A credential in any other shape exports as written, text you log and a url you base64-encode into a request path included. - **README → Runtimes says a React Native app installs a `URL` polyfill.** React Native's own `URL` and `URLSearchParams` throw "not implemented" from members that `new Log({ otlpHttpBaseURI })`, `new Queue` and `log.fetch` read, so those calls throw in an app with no polyfill. Nothing in the package changed; install one such as `react-native-url-polyfill` before the app's code uses it. - **`log.fetch(url, request)` sends a `Request` passed as `init` with its own method, body, signal and other settings.** Before, only its headers were kept, so `log.fetch(url, new Request(url, { method: "POST", body }))` sent a GET with no body, though the span named a POST. Now the request is the one `fetch(url, request)` sends, plus `traceparent`. - **A batch whose retry was reported survives the `maxItems` trim.** Before, a failed batch went back in front of the queue and the trim dropped it first, so an offline app at `maxItems` reported "OTLP export failed, will retry" for items the retry then found gone. Now the trim drops the oldest items behind that batch, also while entries are logged during the retry wait, and the batch is retried whole. - **A batch being sent stays in `storage` until its send settles.** Before, an entry logged during the send saved the queue without the batch, so a process that died then lost it. - **A `storage` whose `getItem` throws keeps what it holds.** Before, one failed read at startup deleted the stored queue, and the first save overwrote it. Now the queue reports "OTLP queue storage unreadable, stored queue kept and not written to", leaves the stored queue as it is, and writes nothing to it until the next start; new entries and spans are still sent from memory. Content that reads but isn't a list of payloads is still discarded. - **`log.enabled(level)` never writes, so a library author's check emits no line.** Before, an unknown `logLevel` made `enabled()` write the warning, and which caller warned depended on call order. Now only the level methods warn, once per `stderr` sink as before, and `enabled()` still treats an unknown `logLevel` as `info`. - **A pending batch no longer holds a Node, Bun or Deno process open, so `await end()` before exit.** A script that awaits neither `end()` nor `flush()` now exits without exporting what it queued. Before, a queued entry or span kept the process alive for up to `batchDelayMs`, and so did an entry logged while a successful export was in flight, after `await log.flush()` had returned. - **Spans and log records export under the instrumentation scope `@larvit/log`, at this package's version.** A span's scope was its span name, and records had none, so a query or dashboard grouping on the scope name sees it change; group on the span name instead. - **`user:pass@` in `otlpHttpBaseURI` beside an `Authorization` in `otlpAdditionalHeaders` writes one `@larvit/log:` line per `report` function, or per `stderr` for a queue a `Log` built, and throws from 3.0.0.** The `otlpAdditionalHeaders` `Authorization` is still sent and the userinfo is not, as in v2.4.0. Keep one of the two. - **`resolveFormatter(conf)` hands back the `EntryFormatter` a conf writes with.** Read `resolveFormatter(log.conf)` where you read `log.conf.entryFormatter`, which 3.0.0 removes. - **A 401 or 403 from the collector reports `OTLP export unauthorized, batch dropped`.** It read `OTLP export rejected, batch dropped`, so an alert matching that text sees it change. - **An invalid name in `captureRequestHeaders` or `captureResponseHeaders` is skipped, with one `warn` line per `stderr`.** It rejected every traced call, or turned a response the runtime delivered into a rejection. - **Chrome 80–84 and Firefox 74–78 parse the module again, and README → Runtimes states the browser floor: Chrome 80, Firefox 74 or Safari 14.** v2.4.0 added `??=`, which raised the floor to Chrome 85 and Firefox 79, so a bundler leaving `node_modules` untranspiled gave those browsers a `SyntaxError`. The build now targets ES2020, so it lowers newer syntax and rejects newer built-ins. </details> --- ### Configuration 📅 **Schedule**: (UTC) - Branch creation - At any time (no schedule defined) - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Enabled. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate CLI](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4yMjUuMSIsInVwZGF0ZWRJblZlciI6IjQ0LjIyNS4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->
renovate-bot added 1 commit 2026-11-11 05:18:57 +01:00
Update dependency @larvit/log to v2.5.0
CI / full-gate (push) Successful in 5m41s
Mirror / github-mirror (push) Successful in 2s
Release / retag-image (push) Successful in 16s
Release / publish-overview (push) Successful in 4s
e8480b8009
Release-Bump: minor
renovate-bot scheduled this pull request to auto merge when all checks succeed 2026-11-11 05:18:57 +01:00
renovate-bot merged commit e8480b8009 into main 2026-11-11 05:35:26 +01:00
renovate-bot deleted branch renovate/larvit-log-2.x 2026-11-11 05:35:26 +01:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: larvit/plainpages#238