Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
f069987
Bump nanoid from 3.3.15 to 3.3.18 in /docs
dependabot[bot] Aug 10, 2026
ce57a54
Bump js-yaml from 4.3.0 to 4.3.1
dependabot[bot] Aug 10, 2026
7ccae0e
Bump postcss from 8.5.19 to 8.5.26
dependabot[bot] Aug 10, 2026
5c20142
Bump fast-uri from 3.1.3 to 3.1.7
dependabot[bot] Sep 2, 2026
6e804d7
Mask inside logged errors instead of passing them through
nkuba Sep 4, 2026
b934375
Document masking inside errors
nkuba Sep 4, 2026
6853241
Bump svgo from 4.0.1 to 4.1.0 in /docs
dependabot[bot] Sep 9, 2026
4ccd6d6
Bump astro from 7.0.7 to 7.3.2 in /docs
dependabot[bot] Sep 10, 2026
9e12cc9
Bump js-yaml from 4.3.0 to 4.3.2 in /docs
dependabot[bot] Sep 10, 2026
44dd860
Bump smol-toml from 1.7.0 to 1.8.0 in /docs
dependabot[bot] Sep 10, 2026
54e10c1
Bump sharp from 0.35.3 to 0.35.4 in /docs
dependabot[bot] Sep 10, 2026
f993582
Bump baseline-browser-mapping from 2.10.43 to 2.11.21
dependabot[bot] Sep 10, 2026
efe1cd2
Merge pull request #368 from fullstack-build/dependabot/npm_and_yarn/…
terehov Sep 10, 2026
bbf9e7e
Merge pull request #367 from fullstack-build/dependabot/npm_and_yarn/…
terehov Sep 10, 2026
9af807a
Merge pull request #366 from fullstack-build/dependabot/npm_and_yarn/…
terehov Sep 10, 2026
6c8730f
Merge pull request #365 from fullstack-build/dependabot/npm_and_yarn/…
terehov Sep 10, 2026
c134b0c
Merge pull request #363 from fullstack-build/dependabot/npm_and_yarn/…
terehov Sep 10, 2026
0eb7fa6
Merge pull request #356 from fullstack-build/dependabot/npm_and_yarn/…
terehov Sep 10, 2026
c9b7f89
Merge pull request #369 from fullstack-build/dependabot/npm_and_yarn/…
terehov Sep 10, 2026
f518079
Merge pull request #359 from fullstack-build/dependabot/npm_and_yarn/…
terehov Sep 10, 2026
dc422e1
Merge pull request #358 from fullstack-build/dependabot/npm_and_yarn/…
terehov Sep 10, 2026
7d4db27
Keep DOMException name and message when masking errors
terehov Sep 10, 2026
97fa236
Merge pull request #357 from fullstack-build/dependabot/npm_and_yarn/…
terehov Sep 10, 2026
434b7e2
Fix flaky timestamp check in browser JSON test
terehov Sep 10, 2026
c5e3a56
Bump vitest to 4.1 to fix the mocker path traversal advisory
terehov Sep 10, 2026
f2b01ec
Fix masking a DOMException on Node 20
terehov Sep 10, 2026
1a414c5
Bump browserslist and docs postcss for security advisories
terehov Sep 10, 2026
cb2b5e3
Regenerate lockfile for npm 10 compatibility
terehov Sep 10, 2026
58d386a
Merge pull request #362 from nkuba/mask-inside-errors
terehov Sep 10, 2026
23d7fe0
Restore 100% coverage after the Vitest 4 bump and error masking
terehov Sep 10, 2026
936a108
Mask the whole stack header of a multi-line error message
terehov Sep 10, 2026
27687c8
Date the 5.2.0 changelog entry
terehov Sep 10, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@

All notable changes to this project are documented here. This project adheres to [Semantic Versioning](https://semver.org/).

## [5.2.0] - 2026-09-11

### Changed
- **Logged errors are cloned** — with `mask` configured, an `Error` argument is replaced by a masked clone like every other argument, and that clone is what transports receive as `nativeError`. It is a real `Error` with the source's prototype (no subclass constructor runs), so `instanceof`, JSON error detection and Sentry-style transports keep working, and the caller's instance is never modified. Without `mask`, errors pass through untouched as before.

### Fixed
- **Masking inside errors** — a secret in an error's message, in a property assigned to the error or down the `cause` chain no longer reaches the JSON line, the pretty error block or `nativeError` in plaintext. `mask.regex` covers the message and the `<name>: <message>` header of a V8 stack (frames are left alone, so a broad pattern cannot corrupt positions), `mask.keys`/`regex`/`paths` cover every other own property and the whole `cause` chain. `name`, `message` and `stack` are exempt from `mask.keys`, so `keys: ["name"]` does not blank every error, while `mask.paths` can still target them. (#214, #361)

## [5.1.0] - 2026-07-17

### Added
Expand Down
9 changes: 7 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -496,7 +496,12 @@ const log = new Logger({
});
```

Masking is leak-proof by construction: `regex` patterns are always applied **globally** (every occurrence in a string is redacted, whether or not you wrote the `g` flag), shared references and circular structures resolve to the same *masked* clone (a secret can never escape through a second reference to the same object), and `mask.keys` / `regex` also apply **inside `Map` and `Set`** contents (`mask.paths` does not descend into them).
Masking is leak-proof by construction:

- `regex` patterns are always applied **globally**: every occurrence in a string is redacted, whether or not you wrote the `g` flag.
- Shared references and circular structures resolve to the same *masked* clone, so a secret can never escape through a second reference to the same object.
- `keys` and `regex` also apply **inside `Map` and `Set`** contents (`paths` does not descend into them).
- **Errors are masked like any other object.** A logged `Error`, top-level or nested, is replaced by a masked clone and the caller's instance stays untouched. `regex` covers the `message` and the `<name>: <message>` header of a V8-style stack, but never the frames, so a broad pattern cannot corrupt `line:col` positions. `keys`, `regex` and `paths` cover every other own property (`code`, `extensions`, ...) and the `cause` chain. `keys` skips `name`, `message` and `stack`, so `keys: ["name"]` does not blank every error, while `paths` can still target them (`paths: ["message"]`).

The `censor` option controls *how* a **`paths`-matched** value is replaced (`keys`- and `regex`-matched values always use `placeholder`, with one exception below):

Expand Down Expand Up @@ -700,7 +705,7 @@ Error trackers and log platforms plug in as transports — no vendor-specific lo

[Sentry](https://sentry.io) has two ingestion paths: **issues** (error tracking) and **[Sentry Logs](https://docs.sentry.io/platforms/javascript/guides/node/logs/)** (structured logs, searchable next to your traces). A tslog transport covers each — run one or both.

**Errors → Sentry issues.** Forward `ERROR`/`FATAL` records while keeping your normal console/JSON output. The record a transport receives still carries the **native `Error` instance** (as `nativeError` on the serialized error), so Sentry gets the real exception — full stack and `cause` chain, proper issue grouping — not a stringified copy:
**Errors → Sentry issues.** Forward `ERROR`/`FATAL` records while keeping your normal console/JSON output. The record a transport receives still carries the **native `Error` instance** (as `nativeError` on the serialized error), so Sentry gets the real exception — full stack and `cause` chain, proper issue grouping — not a stringified copy. With `mask` configured, `nativeError` is the masked clone: still a real `Error` with the same stack and `cause` chain, so grouping works and secrets stay out of Sentry too:

```typescript
import * as Sentry from "@sentry/node";
Expand Down
2 changes: 1 addition & 1 deletion RECIPES.md
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ const detach = log.attachTransport({

## 7b. Send errors and logs to Sentry

Errors as Sentry issues: the record a transport receives still carries the native `Error` instance (as `nativeError` on the serialized error), so Sentry gets the real exception — full stack and `cause` chain — not a stringified copy.
Errors as Sentry issues: the record a transport receives still carries the native `Error` instance (as `nativeError` on the serialized error), so Sentry gets the real exception — full stack and `cause` chain — not a stringified copy. With `mask` configured, `nativeError` is the masked clone: still a real `Error` with the same stack and `cause` chain, so secrets stay out of Sentry too.

```ts
import * as Sentry from "@sentry/node";
Expand Down
Loading
Loading