@lenne.tech/nest-server 11.41.1 → 11.41.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -169,7 +169,7 @@ Two ordering rules, both enforced by the contract test:
|
|
|
169
169
|
Package overrides live in the `overrides:` section of **`pnpm-workspace.yaml`** (they moved out of `package.json`'s `pnpm.overrides` in the pnpm 11 upgrade). They force transitive dependencies to a security-patched version.
|
|
170
170
|
|
|
171
171
|
**Keep the set minimal.** On the pnpm 11 upgrade the list was pruned from 36 to the 9 then still
|
|
172
|
-
load-bearing (it has since grown back to
|
|
172
|
+
load-bearing (it has since grown back to 18 as new advisories landed) — an override is only necessary if removing it lets the package resolve back INTO its vulnerable range (verify with a with/without lockfile diff; `pnpm audit` is the arbiter). Each surviving entry carries its CVE rationale as a comment. Remove an entry once its parent dependency ships a fixed version.
|
|
173
173
|
|
|
174
174
|
### Rule: Override Targets MUST Be Fixed Versions
|
|
175
175
|
|
package/.claude/rules/testing.md
CHANGED
|
@@ -266,7 +266,7 @@ pnpm run check:mutations -- --id=<id> # one mutation
|
|
|
266
266
|
pnpm run check:mutations -- --list # the registry, without running anything
|
|
267
267
|
pnpm run check:mutations -- --allow-dirty # when the fix and its evidence share a working tree
|
|
268
268
|
pnpm run check:mutations -- --jobs=4 # N mutations at a time (default: 2, or 4 on >=12 cores)
|
|
269
|
-
pnpm run check:mutations -- --no-infra # only the
|
|
269
|
+
pnpm run check:mutations -- --no-infra # only the 67 that need no MongoDB
|
|
270
270
|
pnpm run check:mutations -- --since=<ref> # only mutations touching files changed since <ref>
|
|
271
271
|
```
|
|
272
272
|
|
|
@@ -285,7 +285,7 @@ when the registry, a vitest config or a setup file changed, since those can move
|
|
|
285
285
|
commit, so selective re-running would save ~10 minutes a release. The price is a cache that has to
|
|
286
286
|
model each spec's full dependency closure correctly, and getting that wrong produces a stale PASS
|
|
287
287
|
for a test that has since gone vacuous — exactly what the gate is there to prevent. Bad trade
|
|
288
|
-
at
|
|
288
|
+
at 113 mutations — past the threshold this paragraph has carried since the gate was written,
|
|
289
289
|
now reached exactly. The full run is approaching half an hour. **The re-evaluation is due now**: the
|
|
290
290
|
next person to add a mutation should decide whether selective re-running has become worth its
|
|
291
291
|
failure mode (a stale PASS for a test that has since gone vacuous), not bump this number again.
|
|
@@ -329,7 +329,7 @@ exactly the environment where the answer matters.
|
|
|
329
329
|
|
|
330
330
|
Worth knowing before optimising the wrong thing: the specs behind all 46 e2e mutations add up to
|
|
331
331
|
**~40 seconds**. The step takes ~740s. The remaining ~700s is paying vitest's startup — process
|
|
332
|
-
spawn, transform, module graph, mongod connect, DB create and drop — once per mutation,
|
|
332
|
+
spawn, transform, module graph, mongod connect, DB create and drop — once per mutation, 113 times.
|
|
333
333
|
That work is largely single-threaded I/O and barely scales with cores: the full registry measures
|
|
334
334
|
**744s on a 12-core laptop and 777s on a 4-vCPU CI runner**.
|
|
335
335
|
|
package/FRAMEWORK-API.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @lenne.tech/nest-server — Framework API Reference
|
|
2
2
|
|
|
3
|
-
> Auto-generated from source code as of 2026-09-
|
|
3
|
+
> Auto-generated from source code as of 2026-09-21 (v11.41.3)
|
|
4
4
|
> File: `FRAMEWORK-API.md` — compact, machine-readable API surface for Claude Code
|
|
5
5
|
|
|
6
6
|
## CoreModule.forRoot()
|
|
@@ -11,17 +11,18 @@ A green `pnpm audit` inside the framework repo says nothing about your tree.
|
|
|
11
11
|
|
|
12
12
|
## What this concretely means for you
|
|
13
13
|
|
|
14
|
-
The framework pulls in
|
|
14
|
+
The framework pulls in three transitive packages that resolve to a **vulnerable** version unless you
|
|
15
15
|
override them yourself:
|
|
16
16
|
|
|
17
17
|
| Package | Advisory | Why it cannot resolve forward on its own |
|
|
18
18
|
|---------|----------|------------------------------------------|
|
|
19
19
|
| `ws` | [GHSA-96hv-2xvq-fx4p](https://github.com/advisories/GHSA-96hv-2xvq-fx4p) — high: memory-exhaustion DoS + uninitialized memory disclosure. Patched `>=8.21.0` | `@nestjs/graphql` declares `"ws": "8.20.1"` — an **exact pin**, not a caret. No amount of updating moves it |
|
|
20
20
|
| `js-yaml` | [GHSA-pm4m-ph32-ghv5](https://github.com/advisories/GHSA-pm4m-ph32-ghv5) — high: exponential parsing time in flow collections (DoS). Patched `>=5.2.2` | `@nestjs/swagger` declares `"js-yaml": "5.2.1"` — an **exact pin**, the same shape as the `ws` case. It cannot resolve forward |
|
|
21
|
+
| `multer` | [GHSA-wc9g-mqfw-jrwm](https://github.com/advisories/GHSA-wc9g-mqfw-jrwm), [GHSA-535w-7cp7-47q4](https://github.com/advisories/GHSA-535w-7cp7-47q4), [GHSA-qfvm-cv95-jqjf](https://github.com/advisories/GHSA-qfvm-cv95-jqjf) — high: DoS via crafted multipart input; [GHSA-qvfw-j98x-7q72](https://github.com/advisories/GHSA-qvfw-j98x-7q72) — low: file size limit bypass. Patched `>=2.3.0` | `@nestjs/platform-express` declares `"multer": "2.2.0"` — an **exact pin** in every 11.2.x. The framework's own `multer: 2.3.0` dependency does not move it: you get both copies, and FileInterceptor uses the vulnerable one |
|
|
21
22
|
|
|
22
23
|
`@nestjs/graphql` is a plain `dependencies` entry, so `ws` is installed even when you run with
|
|
23
|
-
`graphQl: false`. `@nestjs/swagger`
|
|
24
|
-
practice.
|
|
24
|
+
`graphQl: false`. `@nestjs/swagger` and `@nestjs/platform-express` are likewise plain `dependencies`
|
|
25
|
+
entries. None of them is optional in practice.
|
|
25
26
|
|
|
26
27
|
## The fix
|
|
27
28
|
|
|
@@ -40,6 +41,11 @@ overrides:
|
|
|
40
41
|
# Same shape as the ws entry: an exact pin cannot resolve forward.
|
|
41
42
|
# Remove once @nestjs/swagger stops pinning it.
|
|
42
43
|
'js-yaml@>=5.0.0 <5.2.2': '5.2.2'
|
|
44
|
+
|
|
45
|
+
# @nestjs/platform-express exact-pins multer@2.2.0 (GHSA-wc9g-mqfw-jrwm and three more, patched >=2.3.0).
|
|
46
|
+
# Keep the target in LOCKSTEP with the multer version @lenne.tech/nest-server declares.
|
|
47
|
+
# Remove once @nestjs/platform-express requests >=2.3.0 itself.
|
|
48
|
+
'multer@>=2.0.0 <2.3.0': '2.3.0'
|
|
43
49
|
```
|
|
44
50
|
|
|
45
51
|
### Retired: `@hono/node-server` (removed 2026-08-22, nest-server 11.36.1)
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# Migration Guide: 11.41.1 → 11.41.2
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
| Category | Effort | Applies to |
|
|
6
|
+
|----------|--------|-----------|
|
|
7
|
+
| **Security** | none | `nodemailer` 9.0.5 → 9.1.1 (four advisories, one high) arrives through this package's `dependencies` |
|
|
8
|
+
| **Security** | one override, ~2 min | `multer` 2.2.0 → 2.3.0 (three high, one low): **your project has to add an override** — see below |
|
|
9
|
+
| Tooling | none | Framework repo only: `oxlint --fix-suggestions` removed, `.gitattributes`, non-blocking Windows CI |
|
|
10
|
+
|
|
11
|
+
No API change and no configuration change. The multer fix does enforce file size limits that crafted uploads could previously bypass.
|
|
12
|
+
|
|
13
|
+
## Quick Migration
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
pnpm update @lenne.tech/nest-server
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
# Is a vulnerable multer still in your tree? Anything below 2.3.0 means: add the override below.
|
|
21
|
+
pnpm why multer
|
|
22
|
+
pnpm audit
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Security: multer needs an override in your project
|
|
26
|
+
|
|
27
|
+
`@lenne.tech/nest-server` now declares `multer: 2.3.0`, but that does not reach the copy that
|
|
28
|
+
uploads actually go through. `@nestjs/platform-express` declares `"multer": "2.2.0"` as an **exact
|
|
29
|
+
pin** in every 11.2.x, so your tree ends up with both versions, and `FileInterceptor` uses 2.2.0.
|
|
30
|
+
The advisories ([GHSA-wc9g-mqfw-jrwm](https://github.com/advisories/GHSA-wc9g-mqfw-jrwm),
|
|
31
|
+
[GHSA-535w-7cp7-47q4](https://github.com/advisories/GHSA-535w-7cp7-47q4),
|
|
32
|
+
[GHSA-qfvm-cv95-jqjf](https://github.com/advisories/GHSA-qfvm-cv95-jqjf) — DoS via crafted multipart
|
|
33
|
+
input; [GHSA-qvfw-j98x-7q72](https://github.com/advisories/GHSA-qvfw-j98x-7q72) — file size limit
|
|
34
|
+
bypass) are in that copy.
|
|
35
|
+
|
|
36
|
+
Overrides declared in this package do not travel with it (see
|
|
37
|
+
[docs/security-overrides.md](../docs/security-overrides.md)). Add the entry to your project's
|
|
38
|
+
`pnpm-workspace.yaml` (pnpm 11+; `pnpm.overrides` in `package.json` on pnpm 10 and earlier):
|
|
39
|
+
|
|
40
|
+
```yaml
|
|
41
|
+
overrides:
|
|
42
|
+
# @nestjs/platform-express exact-pins multer@2.2.0 (GHSA-wc9g-mqfw-jrwm and three more, patched >=2.3.0).
|
|
43
|
+
# Keep the target in LOCKSTEP with the multer version @lenne.tech/nest-server declares.
|
|
44
|
+
# Remove once @nestjs/platform-express requests >=2.3.0 itself.
|
|
45
|
+
'multer@>=2.0.0 <2.3.0': '2.3.0'
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
If your project declares `multer` directly, raise it to `2.3.0` as well, so the tree carries exactly
|
|
49
|
+
one copy.
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
pnpm install
|
|
53
|
+
pnpm why multer # expect a single multer@2.3.0
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Projects created from nest-server-starter after 2026-09-15 already carry both.
|
|
57
|
+
|
|
58
|
+
Vendor-mode projects adopt the `multer` and `nodemailer` bumps through the core update instead of
|
|
59
|
+
`pnpm update`. The override is needed there all the same, because `@nestjs/platform-express` is
|
|
60
|
+
installed from npm in both modes.
|
|
61
|
+
|
|
62
|
+
## Under the hood
|
|
63
|
+
|
|
64
|
+
Changes to the framework repository that do not reach consumers:
|
|
65
|
+
|
|
66
|
+
- `oxlint --fix-suggestions` is gone from `lint:fix`, the pre-commit `lint-staged` config and
|
|
67
|
+
`scripts/check.mjs`. oxlint's `no-console` suggestion deletes the whole call, so a commit or a
|
|
68
|
+
`pnpm run check:fix` silently removed `console.log` statements from `src/` and `tests/`.
|
|
69
|
+
- The `hono` and `js-yaml` 4.x overrides were raised to 4.13.7 and 4.3.2. Both are inert: their
|
|
70
|
+
consumers reach the fixed versions on their own ranges. Nothing to mirror.
|
|
71
|
+
- `.gitattributes` pins LF line endings, so a Windows checkout no longer turns
|
|
72
|
+
`docker-entrypoint.sh`, the `Dockerfile` and `bin/migrate.js` into CRLF.
|
|
73
|
+
- `extras/sync-version.ts` stages the lockfile with `execFileSync`, so a repository path containing
|
|
74
|
+
a space works.
|
|
75
|
+
- A non-blocking Windows CI job (`windows.yml`) runs install, build and unit tests.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lenne.tech/nest-server",
|
|
3
|
-
"version": "11.41.
|
|
3
|
+
"version": "11.41.3",
|
|
4
4
|
"description": "Modern, fast, powerful Node.js web framework in TypeScript based on Nest with a GraphQL API and a connection to MongoDB (or other databases).",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"node",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"build:copy-types": "mkdir -p dist/types && cp src/types/*.d.ts dist/types/",
|
|
21
21
|
"build:dev": "pnpm run build",
|
|
22
22
|
"build:framework-api": "tsx scripts/generate-framework-api.ts",
|
|
23
|
-
"build:pack": "pnpm pack && echo
|
|
23
|
+
"build:pack": "pnpm pack && echo \"use file:/ROOT_PATH_TO_TGZ_FILE to integrate the package\"",
|
|
24
24
|
"c": "pnpm run check",
|
|
25
25
|
"cf": "pnpm run check:fix",
|
|
26
26
|
"check": "node scripts/check.mjs",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"format": "oxfmt --write src/ scripts/",
|
|
40
40
|
"format:check": "oxfmt --check src/ scripts/",
|
|
41
41
|
"lint": "oxlint --ignore-path .oxlintignore src/ tests/ scripts/",
|
|
42
|
-
"lint:fix": "oxlint --fix --
|
|
42
|
+
"lint:fix": "oxlint --fix --ignore-path .oxlintignore src/ tests/ scripts/",
|
|
43
43
|
"prepack": "pnpm run prestart:prod",
|
|
44
44
|
"prepublishOnly": "pnpm run lint && pnpm run test:ci",
|
|
45
45
|
"prestart:prod": "pnpm run build",
|
|
@@ -53,10 +53,10 @@
|
|
|
53
53
|
"start:debug": "nodemon --config nodemon-debug.json",
|
|
54
54
|
"start:dev": "nodemon",
|
|
55
55
|
"start:dev:swc": "nest start -b swc -w --type-check",
|
|
56
|
-
"start:local": "NODE_ENV=local nodemon",
|
|
57
|
-
"start:local:swc": "NODE_ENV=local nest start -b swc -w --type-check",
|
|
56
|
+
"start:local": "cross-env NODE_ENV=local nodemon",
|
|
57
|
+
"start:local:swc": "cross-env NODE_ENV=local nest start -b swc -w --type-check",
|
|
58
58
|
"start:nodemon": "ts-node -r tsconfig-paths/register src/main.ts",
|
|
59
|
-
"start:prod": "NODE_ENV=production node dist/main.js",
|
|
59
|
+
"start:prod": "cross-env NODE_ENV=production node dist/main.js",
|
|
60
60
|
"test": "pnpm run vitest:unit && pnpm run vitest",
|
|
61
61
|
"test:ci": "pnpm run vitest:unit && pnpm run vitest:ci",
|
|
62
62
|
"test:cleanup": "find tests -type f \\( -name '*.txt' -o -name '*.bin' -o -name '*.png' \\) -not -name '.gitkeep' -delete && echo 'Test artifacts cleaned up'",
|
|
@@ -68,12 +68,12 @@
|
|
|
68
68
|
"test:types": "tsc --noEmit --skipLibCheck -p tests/types/tsconfig.json",
|
|
69
69
|
"test:unit:watch": "vitest --config vitest.config.ts",
|
|
70
70
|
"typecheck:tests": "tsc --noEmit -p tsconfig.tests.json",
|
|
71
|
-
"vitest": "NODE_ENV=e2e vitest run --config vitest-e2e.config.ts",
|
|
72
|
-
"vitest:ci": "NODE_ENV=ci vitest run --config vitest-e2e.config.ts",
|
|
73
|
-
"vitest:cov": "NODE_ENV=e2e vitest run --coverage --config vitest-e2e.config.ts",
|
|
71
|
+
"vitest": "cross-env NODE_ENV=e2e vitest run --config vitest-e2e.config.ts",
|
|
72
|
+
"vitest:ci": "cross-env NODE_ENV=ci vitest run --config vitest-e2e.config.ts",
|
|
73
|
+
"vitest:cov": "cross-env NODE_ENV=e2e vitest run --coverage --config vitest-e2e.config.ts",
|
|
74
74
|
"vitest:unit": "vitest run --config vitest.config.ts",
|
|
75
75
|
"vitest:unit:cov": "vitest run --coverage --config vitest.config.ts",
|
|
76
|
-
"vitest:watch": "NODE_ENV=e2e vitest --config vitest-e2e.config.ts",
|
|
76
|
+
"vitest:watch": "cross-env NODE_ENV=e2e vitest --config vitest-e2e.config.ts",
|
|
77
77
|
"watch": "npm-watch"
|
|
78
78
|
},
|
|
79
79
|
"repository": {
|
|
@@ -127,9 +127,9 @@
|
|
|
127
127
|
"lodash": "4.18.1",
|
|
128
128
|
"mongodb": "7.5.0",
|
|
129
129
|
"mongoose": "9.9.3",
|
|
130
|
-
"multer": "2.
|
|
130
|
+
"multer": "2.3.0",
|
|
131
131
|
"node-mailjet": "6.0.11",
|
|
132
|
-
"nodemailer": "9.
|
|
132
|
+
"nodemailer": "9.1.1",
|
|
133
133
|
"passport": "0.7.0",
|
|
134
134
|
"passport-jwt": "4.0.1",
|
|
135
135
|
"reflect-metadata": "0.2.2",
|
|
@@ -201,6 +201,7 @@
|
|
|
201
201
|
"ansi-colors": "4.1.3",
|
|
202
202
|
"better-auth": "1.7.1",
|
|
203
203
|
"bullmq": "6.2.0",
|
|
204
|
+
"cross-env": "10.1.0",
|
|
204
205
|
"find-file-up": "2.0.1",
|
|
205
206
|
"husky": "9.1.7",
|
|
206
207
|
"ioredis": "6.0.0",
|