Apply the origin check to Astro Actions regardless of pipeline order#17250
Conversation
🦋 Changeset detectedLatest commit: d8eb8ea The changes in this PR will be included in the next version bump. This PR includes changesets to release 394 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
Merging this PR will improve performance by 31.13%
Performance Changes
Tip Curious why this is faster? Comment Comparing Footnotes |
| // The origin check normally runs in the origin-check middleware, but the | ||
| // action dispatch can run before that middleware depending on how the | ||
| // pipeline is composed. Apply the same check here so it holds regardless | ||
| // of ordering. |
There was a problem hiding this comment.
Wouldn't it make more sense to apply the check in one place, instead of fragmenting it? I'm sure we can do it in the fetch state. Maybe a hook or something?
There was a problem hiding this comment.
I don't think there's 1 place that we can do that, it's the design of the astro/fetch API that things are composable in any order the user wants.
We can't put it in FetchState, that's just an object, it doesn't check or reject requests.
Perhaps a more correct place would be turning origin checks into a separate handler checkOrigin that you can then compose yourself, and then making the middleware check by deprecated functionality. But that feels a little weird since origin check is a config option.
There was a problem hiding this comment.
I see, thank you. I suppose that's the drawback of this design, but now I wonder: if an user decides to use a custom fetch, and doesn't use any of our fetch handlers, does that mean that check origin isn't triggered at all? If so, it's a flaw. Do we have a test for this? Or should we document it?
There was a problem hiding this comment.
If the user uses a browser fetch() instead of Actions then it still gets the Origin header and since we check in pages() in this PR it will pass the check. If the Origin is omitted it will fail the check, as expected. So we're covered for Actions or handling it inside of a page/endpoint.
Remember though that this feature is just a defense-in-depth since anyone can forge the Origin header in a request.
This PR contains the following updates: | Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) | |---|---|---|---| | [@astrojs/markdown-remark](https://astro.build) ([source](https://github.com/withastro/astro/tree/HEAD/packages/markdown/remark)) | [`7.2.0` → `7.2.1`](https://renovatebot.com/diffs/npm/@astrojs%2fmarkdown-remark/7.2.0/7.2.1) |  |  | | [astro](https://astro.build) ([source](https://github.com/withastro/astro/tree/HEAD/packages/astro)) | [`7.0.4` → `7.0.6`](https://renovatebot.com/diffs/npm/astro/7.0.4/7.0.6) |  |  | --- ### Release Notes <details> <summary>withastro/astro (@​astrojs/markdown-remark)</summary> ### [`v7.2.1`](https://github.com/withastro/astro/blob/HEAD/packages/markdown/remark/CHANGELOG.md#721) [Compare Source](https://github.com/withastro/astro/compare/@astrojs/[email protected]...@astrojs/[email protected]) ##### Patch Changes - Updated dependencies \[[`eb6f97e`](withastro/astro@eb6f97e)]: - [@​astrojs/internal-helpers](https://github.com/astrojs/internal-helpers)@​0.10.1 </details> <details> <summary>withastro/astro (astro)</summary> ### [`v7.0.6`](https://github.com/withastro/astro/blob/HEAD/packages/astro/CHANGELOG.md#706) [Compare Source](https://github.com/withastro/astro/compare/[email protected]@7.0.6) ##### Patch Changes - [#​17261](withastro/astro#17261) [`79aa99c`](withastro/astro@79aa99c) Thanks [@​astrobot-houston](https://github.com/astrobot-houston)! - Fixes a false deprecation warning for `markdown.gfm` and `markdown.smartypants` when using the Container API - [#​17247](withastro/astro#17247) [`f94280d`](withastro/astro@f94280d) Thanks [@​chatman-media](https://github.com/chatman-media)! - Fixes route generation throwing "Missing parameter" (or silently dropping the segment) when a dynamic param's value is `0`. The generator used truthy checks instead of checking for `undefined`, so `paginate(posts, { params: { categoryId: 0 } })` would crash even though `0` is a perfectly valid param value. - [#​17278](withastro/astro#17278) [`6f11739`](withastro/astro@6f11739) Thanks [@​astrobot-houston](https://github.com/astrobot-houston)! - Fixes missing CSS for virtual style modules (e.g., responsive image layout styles) in dev mode when JavaScript is disabled - [#​17250](withastro/astro#17250) [`0b30b35`](withastro/astro@0b30b35) Thanks [@​matthewp](https://github.com/matthewp)! - Fixes the `security.checkOrigin` check so it is applied consistently to Astro Actions and on-demand endpoints, regardless of how the request pipeline is composed. Previously, the origin check could be skipped in the composable `astro/hono` pipeline depending on the order of the `middleware()` primitive (or when it was omitted). - [#​17274](withastro/astro#17274) [`8c3579b`](withastro/astro@8c3579b) Thanks [@​astrobot-houston](https://github.com/astrobot-houston)! - Fixes missing `render()` type overload for live collection entries. Previously, calling `render()` on a `LiveDataEntry` produced a TypeScript error when using only `live.config.ts` without a `content.config.ts`. - [#​17257](withastro/astro#17257) [`4208297`](withastro/astro@4208297) Thanks [@​astrobot-houston](https://github.com/astrobot-houston)! - Fixes `astro check` failing to find `@astrojs/check` and `typescript` when astro is installed in a directory outside the project tree (e.g. pnpm virtual store) - [#​17272](withastro/astro#17272) [`b428648`](withastro/astro@b428648) Thanks [@​matthewp](https://github.com/matthewp)! - Fixes island component paths so that extensionless imports (e.g. `import { Counter } from '../components/Counter'`) resolve to the real file on disk, matching Vite's extension order and directory `index` resolution. This makes the `include`/`exclude` options of JSX renderer integrations (React, Preact, Solid) match components imported without a file extension, and removes the spurious React 19 "Invalid hook call" warning logged on every request in dev when `include` was set alongside another JSX renderer - [#​17279](withastro/astro#17279) [`2aeaa44`](withastro/astro@2aeaa44) Thanks [@​astrobot-houston](https://github.com/astrobot-houston)! - Fixes a bug where `<Picture inferSize>` with a remote image could fail with `FailedToFetchRemoteImageDimensions` when the image server rate-limits requests (e.g. HTTP 429). Remote dimensions are now resolved once per render instead of once per output format. - [#​17251](withastro/astro#17251) [`5240e26`](withastro/astro@5240e26) Thanks [@​matthewp](https://github.com/matthewp)! - Hardens the handling of attribute rendering when using with custom elements. - [#​17248](withastro/astro#17248) [`429bd62`](withastro/astro@429bd62) Thanks [@​astrobot-houston](https://github.com/astrobot-houston)! - Fixes a crash when using Astro's `getViteConfig` with Vitest browser mode (e.g., Storybook vitest runner). Astro now skips dev server setup inside Vitest, preventing errors. - [#​17260](withastro/astro#17260) [`14524c0`](withastro/astro@14524c0) Thanks [@​matthewp](https://github.com/matthewp)! - Fixes a regression where a `<script>` inside a component rendered through `Astro.slots.render()` was hoisted out of its original position instead of staying next to its component content - Updated dependencies \[[`eb6f97e`](withastro/astro@eb6f97e)]: - [@​astrojs/internal-helpers](https://github.com/astrojs/internal-helpers)@​0.10.1 - [@​astrojs/markdown-remark](https://github.com/astrojs/markdown-remark)@​7.2.1 - [@​astrojs/markdown-satteri](https://github.com/astrojs/markdown-satteri)@​0.3.3 ### [`v7.0.5`](https://github.com/withastro/astro/blob/HEAD/packages/astro/CHANGELOG.md#705) [Compare Source](https://github.com/withastro/astro/compare/[email protected]@7.0.5) ##### Patch Changes - [#​17242](withastro/astro#17242) [`9c05ba4`](withastro/astro@9c05ba4) Thanks [@​matthewp](https://github.com/matthewp)! - Fixes an error that could occur after the dev server restarts when using an adapter such as `@astrojs/cloudflare`, where a request would fail with a `500` referencing a missing pre-bundled dependency: ``` The file does not exist at "node_modules/.vite/deps_ssr/astro_compiler-runtime.js?v=6419660d" which is in the optimize deps directory. The dependency might be incompatible with the dep optimizer. Try adding it to `optimizeDeps.exclude`. ``` - [#​17202](withastro/astro#17202) [`c6d254d`](withastro/astro@c6d254d) Thanks [@​matthewp](https://github.com/matthewp)! - Refactors path alias resolution to use Vite's native `tsconfigPaths` option This is an internal change with no expected impact on user projects. Astro now defers tsconfig and jsconfig `paths` alias resolution to Vite, keeping a small fallback for a few CSS cases Vite does not yet handle. - [#​17123](withastro/astro#17123) [`72e29bd`](withastro/astro@72e29bd) Thanks [@​martrapp](https://github.com/martrapp)! - Fixes an issue where the ClientRouter wipes head elements after page transitions if the `<head>` contains a `server:defer` component. - [#​17232](withastro/astro#17232) [`257505e`](withastro/astro@257505e) Thanks [@​matthewp](https://github.com/matthewp)! - Fixes a bug where `<style>` tags from components such as a content collection's `Content` could be silently dropped from the output when an `await` appeared before the component in an `.astro` file's markup. - [#​17193](withastro/astro#17193) [`a7352fd`](withastro/astro@a7352fd) Thanks [@​jan-kubica](https://github.com/jan-kubica)! - Fixes the background dev server failing to start when `astro` is hoisted outside the project's `node_modules` (for example bun workspaces). The background process is now spawned from Astro's own resolved location instead of a path assumed under the project root. - [#​17255](withastro/astro#17255) [`581d171`](withastro/astro@581d171) Thanks [@​astrobot-houston](https://github.com/astrobot-houston)! - Fixes prefetch not working for links inside `server:defer` components </details> --- ### Configuration 📅 **Schedule**: (UTC) - Branch creation - At any time (no schedule defined) - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 👻 **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://github.com/renovatebot/renovate/discussions) if that's undesired. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4yNDYuMSIsInVwZGF0ZWRJblZlciI6IjQzLjI0Ni4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->
Changes
security.checkOrigincheck at the request dispatch points (Astro Actions and on-demand endpoints/pages), so it holds consistently regardless of how the composableastro/honopipeline is ordered. Previously the check only ran inside themiddleware()primitive, so it could be skipped depending on primitive order — or whenmiddleware()was omitted entirely.core/app/origin-check.ts(a predicate + response builder) consumed by the pipeline middleware, the actions dispatch, and thepages()endpoint dispatch. No behavior change to the classic pipeline: the check remains a no-op at the dispatch sinks when the middleware already ran, for prerendered/static routes, for safe methods, and whencheckOriginis disabled.Testing
action-origin-check.test.ts: composes a Hono app withactions()beforemiddleware()and asserts a cross-origin action request is rejected before the handler runs, while same-origin succeeds.pages-origin-check.test.ts: composes a Hono app withpages()and nomiddleware()and asserts a cross-originPOSTto an on-demand endpoint is rejected before the handler runs, while same-origin succeeds.Docs
security.checkOriginbehavior is unchanged from the user's perspective.