Skip to content

Commit

Permalink
Merge branch 'main' into renovate/all-minor-patch
Browse files Browse the repository at this point in the history
  • Loading branch information
bluwy committed Aug 13, 2024
2 parents f499bcb + fc24e1b commit e8ee4c6
Show file tree
Hide file tree
Showing 36 changed files with 329 additions and 94 deletions.
5 changes: 5 additions & 0 deletions .changeset/good-birds-clap.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'astro': patch
---

Fixes a case where omitting a semicolon and line ending with carriage return - CRLF - in the `prerender` option could throw an error.
9 changes: 9 additions & 0 deletions .changeset/hip-toys-shake.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
'@astrojs/node': patch
---

Move polyfills up before awaiting the env module in the Node.js adapter.

Previously the env setting was happening before the polyfills were applied. This means that if the Astro env code (or any dependencies) depended on `crypto`, it would not be polyfilled in time.

Polyfills should be applied ASAP to prevent races. This moves it to the top of the Node adapter.
9 changes: 9 additions & 0 deletions .changeset/little-humans-act.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
'astro': patch
---

Encrypt server island props

Server island props are not encrypted with a key generated at build-time. This is intended to prevent accidentally leaking secrets caused by exposing secrets through prop-passing. This is not intended to allow a server island to be trusted to skip authentication, or to protect against any other vulnerabilities other than secret leakage.

See the RFC for an explanation: https://github.com/withastro/roadmap/blob/server-islands/proposals/server-islands.md#props-serialization
5 changes: 5 additions & 0 deletions .changeset/nervous-garlics-beam.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'astro': patch
---

Fixes Astro Actions `input` validation when using `default` values with a form input.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ Join us on [Discord](https://astro.build/chat) to meet other maintainers. We'll
| [@astrojs/alpinejs](packages/integrations/alpinejs) | [![@astrojs/alpinejs version](https://img.shields.io/npm/v/@astrojs/alpinejs.svg?label=%20)](packages/integrations/alpinejs/CHANGELOG.md) |
| [@astrojs/mdx](packages/integrations/mdx) | [![@astrojs/mdx version](https://img.shields.io/npm/v/@astrojs/mdx.svg?label=%20)](packages/integrations/mdx/CHANGELOG.md) |
| [@astrojs/db](packages/db) | [![@astrojs/db version](https://img.shields.io/npm/v/@astrojs/db.svg?label=%20)](packages/db/CHANGELOG.md) |
| [@astrojs/rss](packages/integrations/astro-rss) | [![@astrojs/rss version](https://img.shields.io/npm/v/@astrojs/rss.svg?label=%20)](packages/astro-rss/CHANGELOG.md) |
| [@astrojs/rss](packages/astro-rss) | [![@astrojs/rss version](https://img.shields.io/npm/v/@astrojs/rss.svg?label=%20)](packages/astro-rss/CHANGELOG.md) |

[![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/6178/badge)](https://bestpractices.coreinfrastructure.org/projects/6178)

Expand Down
2 changes: 1 addition & 1 deletion biome.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"$schema": "https://biomejs.dev/schemas/1.8.1/schema.json",
"$schema": "https://biomejs.dev/schemas/1.8.3/schema.json",
"files": {
"ignore": [
"vendor",
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@
},
"devDependencies": {
"@astrojs/check": "^0.9.2",
"@biomejs/biome": "1.8.1",
"@biomejs/biome": "1.8.3",
"@changesets/changelog-github": "^0.5.0",
"@changesets/cli": "^2.27.7",
"@types/node": "^18.17.8",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
---
const { secret } = Astro.props;
---
<h2 id="island">I am an island</h2>
<slot />
<h3 id="secret">{secret}</h3>
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import Self from '../components/Self.astro';
<!-- Head Stuff -->
</head>
<body>
<Island server:defer>
<Island server:defer secret="test">
<h3 id="children">children</h3>
</Island>
<Self server:defer />
Expand Down
12 changes: 12 additions & 0 deletions packages/astro/e2e/server-islands.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,12 @@ test.describe('Server islands', () => {
await expect(el, 'element rendered').toBeVisible();
});

test('Props are encrypted', async ({ page, astro }) => {
await page.goto(astro.resolveUrl('/base/'));
let el = page.locator('#secret');
await expect(el).toHaveText('test');
});

test('Self imported module can server defer', async ({ page, astro }) => {
await page.goto(astro.resolveUrl('/base/'));
let el = page.locator('.now');
Expand Down Expand Up @@ -69,5 +75,11 @@ test.describe('Server islands', () => {
await expect(el, 'element rendered').toBeVisible();
await expect(el, 'should have content').toHaveText('I am an island');
});

test('Props are encrypted', async ({ page, astro }) => {
await page.goto(astro.resolveUrl('/'));
let el = page.locator('#secret');
await expect(el).toHaveText('test');
});
});
});
1 change: 1 addition & 0 deletions packages/astro/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@
"@babel/plugin-transform-react-jsx": "^7.25.2",
"@babel/traverse": "^7.25.3",
"@babel/types": "^7.25.2",
"@oslojs/encoding": "^0.4.1",
"@types/babel__core": "^7.20.5",
"@types/cookie": "^0.6.0",
"acorn": "^8.12.1",
Expand Down
3 changes: 2 additions & 1 deletion packages/astro/src/@types/astro.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2339,7 +2339,7 @@ export type GetDataEntryInfoReturnType = { data: Record<string, unknown>; rawDat

export interface AstroAdapterFeatures {
/**
* Creates and edge function that will communiate with the Astro middleware
* Creates an edge function that will communiate with the Astro middleware
*/
edgeMiddleware: boolean;
/**
Expand Down Expand Up @@ -3283,6 +3283,7 @@ export interface SSRResult {
cookies: AstroCookies | undefined;
serverIslandNameMap: Map<string, string>;
trailingSlash: AstroConfig['trailingSlash'];
key: Promise<CryptoKey>;
_metadata: SSRMetadata;
}

Expand Down
20 changes: 17 additions & 3 deletions packages/astro/src/actions/runtime/virtual/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,11 +134,25 @@ export function formDataToObject<T extends z.AnyZodObject>(
const obj: Record<string, unknown> = {};
for (const [key, baseValidator] of Object.entries(schema.shape)) {
let validator = baseValidator;
while (validator instanceof z.ZodOptional || validator instanceof z.ZodNullable) {

while (
validator instanceof z.ZodOptional ||
validator instanceof z.ZodNullable ||
validator instanceof z.ZodDefault
) {
// use default value when key is undefined
if (validator instanceof z.ZodDefault && !formData.has(key)) {
obj[key] = validator._def.defaultValue();
}
validator = validator._def.innerType;
}
if (validator instanceof z.ZodBoolean) {
obj[key] = formData.has(key);

if (!formData.has(key) && key in obj) {
// continue loop if form input is not found and default value is set
continue;
} else if (validator instanceof z.ZodBoolean) {
const val = formData.get(key);
obj[key] = val === 'true' ? true : val === 'false' ? false : formData.has(key);
} else if (validator instanceof z.ZodArray) {
obj[key] = handleFormDataGetAll(key, formData, validator);
} else {
Expand Down
2 changes: 2 additions & 0 deletions packages/astro/src/container/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import type {
import { getDefaultClientDirectives } from '../core/client-directive/index.js';
import { ASTRO_CONFIG_DEFAULTS } from '../core/config/schema.js';
import { validateConfig } from '../core/config/validate.js';
import { createKey } from '../core/encryption.js';
import { Logger } from '../core/logger/core.js';
import { nodeLogDestination } from '../core/logger/node.js';
import { removeLeadingForwardSlash } from '../core/path.js';
Expand Down Expand Up @@ -130,6 +131,7 @@ function createManifest(
checkOrigin: false,
middleware: manifest?.middleware ?? middleware ?? defaultMiddleware,
experimentalEnvGetSecretEnabled: false,
key: createKey(),
};
}

Expand Down
3 changes: 3 additions & 0 deletions packages/astro/src/core/app/common.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { decodeKey } from '../encryption.js';
import { deserializeRouteData } from '../routing/manifest/serialization.js';
import type { RouteInfo, SSRManifest, SerializedSSRManifest } from './types.js';

Expand All @@ -18,6 +19,7 @@ export function deserializeManifest(serializedManifest: SerializedSSRManifest):
const inlinedScripts = new Map(serializedManifest.inlinedScripts);
const clientDirectives = new Map(serializedManifest.clientDirectives);
const serverIslandNameMap = new Map(serializedManifest.serverIslandNameMap);
const key = decodeKey(serializedManifest.key);

return {
// in case user middleware exists, this no-op middleware will be reassigned (see plugin-ssr.ts)
Expand All @@ -31,5 +33,6 @@ export function deserializeManifest(serializedManifest: SerializedSSRManifest):
clientDirectives,
routes,
serverIslandNameMap,
key,
};
}
12 changes: 7 additions & 5 deletions packages/astro/src/core/app/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -416,13 +416,15 @@ export class App {
`${this.#baseWithoutTrailingSlash}/${status}${maybeDotHtml}`,
url,
);
const response = await fetch(statusURL.toString());
if (statusURL.toString() !== request.url) {
const response = await fetch(statusURL.toString());

// response for /404.html and 500.html is 200, which is not meaningful
// so we create an override
const override = { status };
// response for /404.html and 500.html is 200, which is not meaningful
// so we create an override
const override = { status };

return this.#mergeResponses(response, originalResponse, override);
return this.#mergeResponses(response, originalResponse, override);
}
}
const mod = await this.#pipeline.getModuleForRoute(errorRouteData);
try {
Expand Down
3 changes: 3 additions & 0 deletions packages/astro/src/core/app/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ export type SSRManifest = {
pageMap?: Map<ComponentPath, ImportComponentInstance>;
serverIslandMap?: Map<string, () => Promise<ComponentInstance>>;
serverIslandNameMap?: Map<string, string>;
key: Promise<CryptoKey>;
i18n: SSRManifestI18n | undefined;
middleware: MiddlewareHandler;
checkOrigin: boolean;
Expand All @@ -90,11 +91,13 @@ export type SerializedSSRManifest = Omit<
| 'inlinedScripts'
| 'clientDirectives'
| 'serverIslandNameMap'
| 'key'
> & {
routes: SerializedRouteInfo[];
assets: string[];
componentMetadata: [string, SSRComponentMetadata][];
inlinedScripts: [string, string][];
clientDirectives: [string, string][];
serverIslandNameMap: [string, string][];
key: string;
};
3 changes: 3 additions & 0 deletions packages/astro/src/core/build/generate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ export async function generatePages(options: StaticBuildOptions, internals: Buil
internals,
renderers.renderers as SSRLoadedRenderer[],
middleware,
options.key,
);
}
const pipeline = BuildPipeline.create({ internals, manifest, options });
Expand Down Expand Up @@ -521,6 +522,7 @@ function createBuildManifest(
internals: BuildInternals,
renderers: SSRLoadedRenderer[],
middleware: MiddlewareHandler,
key: Promise<CryptoKey>,
): SSRManifest {
let i18nManifest: SSRManifestI18n | undefined = undefined;
if (settings.config.i18n) {
Expand Down Expand Up @@ -551,6 +553,7 @@ function createBuildManifest(
buildFormat: settings.config.build.format,
middleware,
checkOrigin: settings.config.security?.checkOrigin ?? false,
key,
experimentalEnvGetSecretEnabled: false,
};
}
2 changes: 2 additions & 0 deletions packages/astro/src/core/build/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { resolveConfig } from '../config/config.js';
import { createNodeLogger } from '../config/logging.js';
import { createSettings } from '../config/settings.js';
import { createVite } from '../create-vite.js';
import { createKey } from '../encryption.js';
import type { Logger } from '../logger/core.js';
import { levels, timerMessage } from '../logger/core.js';
import { apply as applyPolyfill } from '../polyfill.js';
Expand Down Expand Up @@ -201,6 +202,7 @@ class AstroBuilder {
pageNames,
teardownCompiler: this.teardownCompiler,
viteConfig,
key: createKey(),
};

const { internals, ssrOutputChunkNames, contentFileNames } = await viteBuild(opts);
Expand Down
6 changes: 5 additions & 1 deletion packages/astro/src/core/build/plugins/plugin-manifest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import type {
SerializedRouteInfo,
SerializedSSRManifest,
} from '../../app/types.js';
import { encodeKey } from '../../encryption.js';
import { fileExtension, joinPaths, prependForwardSlash } from '../../path.js';
import { serializeRouteData } from '../../routing/index.js';
import { addRollupInput } from '../add-rollup-input.js';
Expand Down Expand Up @@ -132,7 +133,8 @@ async function createManifest(
}

const staticFiles = internals.staticFiles;
return buildManifest(buildOpts, internals, Array.from(staticFiles));
const encodedKey = await encodeKey(await buildOpts.key);
return buildManifest(buildOpts, internals, Array.from(staticFiles), encodedKey);
}

/**
Expand All @@ -150,6 +152,7 @@ function buildManifest(
opts: StaticBuildOptions,
internals: BuildInternals,
staticFiles: string[],
encodedKey: string,
): SerializedSSRManifest {
const { settings } = opts;

Expand Down Expand Up @@ -277,6 +280,7 @@ function buildManifest(
buildFormat: settings.config.build.format,
checkOrigin: settings.config.security?.checkOrigin ?? false,
serverIslandNameMap: Array.from(settings.serverIslandNameMap),
key: encodedKey,
experimentalEnvGetSecretEnabled:
settings.config.experimental.env !== undefined &&
(settings.adapter?.supportedAstroFeatures.envGetSecret ?? 'unsupported') !== 'unsupported',
Expand Down
7 changes: 6 additions & 1 deletion packages/astro/src/core/build/plugins/plugin-ssr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@ function vitePluginSSR(
inputs.add(getVirtualModulePageName(ASTRO_PAGE_MODULE_ID, pageData.component));
}

const adapterServerEntrypoint = options.settings.adapter?.serverEntrypoint;
if (adapterServerEntrypoint) {
inputs.add(adapterServerEntrypoint);
}

inputs.add(SSR_VIRTUAL_MODULE_ID);
return addRollupInput(opts, Array.from(inputs));
},
Expand Down Expand Up @@ -246,8 +251,8 @@ function generateSSRCode(settings: AstroSettings, adapter: AstroAdapter, middlew

const imports = [
`import { renderers } from '${RENDERERS_MODULE_ID}';`,
`import { manifest as defaultManifest } from '${SSR_MANIFEST_VIRTUAL_MODULE_ID}';`,
`import * as serverEntrypointModule from '${adapter.serverEntrypoint}';`,
`import { manifest as defaultManifest } from '${SSR_MANIFEST_VIRTUAL_MODULE_ID}';`,
edgeMiddleware ? `` : `import { onRequest as middleware } from '${middlewareId}';`,
settings.config.experimental.serverIslands
? `import { serverIslandMap } from '${VIRTUAL_ISLAND_MAP_ID}';`
Expand Down
2 changes: 2 additions & 0 deletions packages/astro/src/core/build/static-build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,8 @@ async function ssrBuild(
return 'renderers.mjs';
} else if (chunkInfo.facadeModuleId === RESOLVED_SSR_MANIFEST_VIRTUAL_MODULE_ID) {
return 'manifest_[hash].mjs';
} else if (chunkInfo.facadeModuleId === settings.adapter?.serverEntrypoint) {
return 'adapter_[hash].mjs';
} else if (
settings.config.experimental.contentCollectionCache &&
chunkInfo.facadeModuleId &&
Expand Down
1 change: 1 addition & 0 deletions packages/astro/src/core/build/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ export interface StaticBuildOptions {
pageNames: string[];
viteConfig: InlineConfig;
teardownCompiler: boolean;
key: Promise<CryptoKey>;
}

type ImportComponentInstance = () => Promise<ComponentInstance>;
Expand Down
Loading

0 comments on commit e8ee4c6

Please sign in to comment.