@zerotal/core 1.15.1 → 1.15.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.
- package/CHANGELOG.md +22 -0
- package/package.json +1 -1
- package/src/dev/buildEnv.ts +8 -0
- package/src/pipeline/HttpContext.ts +28 -4
package/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,28 @@ follows the Zerotal monorepo's unified versioning.
|
|
|
8
8
|
|
|
9
9
|
## [Unreleased]
|
|
10
10
|
|
|
11
|
+
## [1.15.2] — 2026-10-23
|
|
12
|
+
|
|
13
|
+
### Fixed
|
|
14
|
+
|
|
15
|
+
- **A production build ships React's production build.** `browserEnvDefines()` defined
|
|
16
|
+
`import.meta.env` but not `process.env.NODE_ENV`, which is the switch React and most of
|
|
17
|
+
npm read — and Bun.build leaves that expression to whatever the shell has. An app that ran
|
|
18
|
+
`inertia:build --production` without `NODE_ENV` in its environment shipped React's
|
|
19
|
+
development build: a 522 KB vendor chunk where 322 KB would do, the DevTools notice in
|
|
20
|
+
every visitor's console, and full hydration diffs. The define now states it from the same
|
|
21
|
+
flag. Found on a live consumer app (Trekly).
|
|
22
|
+
|
|
23
|
+
- **`back()` works behind a proxy that terminates TLS.** `safeRedirectPath` — which
|
|
24
|
+
`ctx.back()`, `validate()`'s redirect on failure, `FormRequest`, the intended-URL helpers
|
|
25
|
+
and flow all use — accepted a Referer only from the request's own origin. Behind Caddy or
|
|
26
|
+
nginx the request reaches the process as `http://…` while every browser sends
|
|
27
|
+
`https://…`, so every Referer was refused and "back" was always `/`: a form with one
|
|
28
|
+
mistake in it sent the user to the home page, its errors flashed to a page that never
|
|
29
|
+
shows them. The configured `app.url`'s origin now counts as the app's own as well; every
|
|
30
|
+
other site is still refused. Found on a live consumer app (Trekly), which had worked
|
|
31
|
+
round it in its exception handler.
|
|
32
|
+
|
|
11
33
|
## [1.15.1] — 2026-09-13
|
|
12
34
|
|
|
13
35
|
### Added
|
package/package.json
CHANGED
package/src/dev/buildEnv.ts
CHANGED
|
@@ -37,5 +37,13 @@ export function browserEnvDefines(isProduction: boolean): Record<string, string>
|
|
|
37
37
|
PROD: isProduction,
|
|
38
38
|
MODE: isProduction ? "production" : "development",
|
|
39
39
|
}),
|
|
40
|
+
// The other half of the convention, and the one that costs the most to miss.
|
|
41
|
+
// React and most of npm choose their production build with
|
|
42
|
+
// `process.env.NODE_ENV === "production"`, and Bun.build leaves the expression
|
|
43
|
+
// to the environment it runs in. A deploy that ran `inertia:build --production`
|
|
44
|
+
// without NODE_ENV set shipped React's development build — a 522 KB vendor
|
|
45
|
+
// chunk where 322 KB would do, the DevTools notice in every visitor's console,
|
|
46
|
+
// and full hydration diffs to anyone who looked. Stated here, the flag decides.
|
|
47
|
+
"process.env.NODE_ENV": JSON.stringify(isProduction ? "production" : "development"),
|
|
40
48
|
};
|
|
41
49
|
}
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
DEFAULT_MD_OPTIONS,
|
|
15
15
|
type BunMarkdownOptions,
|
|
16
16
|
} from "../helpers/markdown.ts";
|
|
17
|
+
import { config } from "../helpers/config.ts";
|
|
17
18
|
import type { SessionContract, TransactionContext } from "../contracts/index.ts";
|
|
18
19
|
import type { ContextRegistry, ContextKey } from "./ContextRegistry.ts";
|
|
19
20
|
|
|
@@ -868,14 +869,24 @@ const _prototypeMethods: ReadonlyArray<[string, (...args: unknown[]) => unknown]
|
|
|
868
869
|
})();
|
|
869
870
|
|
|
870
871
|
/**
|
|
871
|
-
* Return `url` only when it belongs to the
|
|
872
|
+
* Return `url` only when it belongs to the app, otherwise `undefined`.
|
|
872
873
|
* Guards `ctx.back()` and similar helpers against open-redirect attacks by
|
|
873
874
|
* rejecting absent, malformed, or cross-origin URLs.
|
|
874
875
|
*
|
|
876
|
+
* "Belongs to the app" is the request's own `origin` **or the configured
|
|
877
|
+
* `app.url`'s**. The second matters behind a reverse proxy that terminates TLS:
|
|
878
|
+
* the request reaches the process as `http://…`, while every browser sends its
|
|
879
|
+
* `Referer` as `https://…`, so a same-origin check alone refused every one of
|
|
880
|
+
* them and `back()` — and `validate()`'s redirect on failure — fell back to "/"
|
|
881
|
+
* on every request in production. A form with one mistake in it sent the user
|
|
882
|
+
* to the home page, its errors flashed to a page that never shows them. The
|
|
883
|
+
* configured URL is the app's own address by definition, so accepting it opens
|
|
884
|
+
* nothing to anyone else.
|
|
885
|
+
*
|
|
875
886
|
* @param url - Candidate redirect target (e.g. a `Referer` header value).
|
|
876
887
|
* @param origin - The current request origin to match against.
|
|
877
|
-
* @returns The
|
|
878
|
-
*
|
|
888
|
+
* @returns The `url`, or `undefined` when it is absent, unparseable, or points
|
|
889
|
+
* anywhere but this app.
|
|
879
890
|
*
|
|
880
891
|
* @internal
|
|
881
892
|
*/
|
|
@@ -885,7 +896,20 @@ export function safeRedirectPath(
|
|
|
885
896
|
): string | undefined {
|
|
886
897
|
if (!url) return undefined;
|
|
887
898
|
try {
|
|
888
|
-
|
|
899
|
+
const target = new URL(url).origin;
|
|
900
|
+
if (target === origin) return url;
|
|
901
|
+
return target === configuredOrigin() ? url : undefined;
|
|
902
|
+
} catch {
|
|
903
|
+
return undefined;
|
|
904
|
+
}
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
/** The configured `app.url`'s origin, or `undefined` off-app or when it is unset or malformed. */
|
|
908
|
+
function configuredOrigin(): string | undefined {
|
|
909
|
+
const base = config.safe("app.url", "") as string;
|
|
910
|
+
if (!base) return undefined;
|
|
911
|
+
try {
|
|
912
|
+
return new URL(base).origin;
|
|
889
913
|
} catch {
|
|
890
914
|
return undefined;
|
|
891
915
|
}
|