Skip to content

feat(sveltekit)!: Remove fetchProxyScriptNonce option #15123

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jan 22, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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 docs/migration/v8-to-v9.md
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,10 @@ The following changes are unlikely to affect users of the SDK. They are listed h
This function was primarily internally used.
It's functionality was misleading and should not be used.

### `@sentry/sveltekit`

- The `fetchProxyScriptNonce` option in `sentryHandle()` was removed due to security concerns. If you previously specified this option for your CSP policy, specify a [script hash](https://docs.sentry.io/platforms/javascript/guides/sveltekit/manual-setup/#configure-csp-for-client-side-fetch-instrumentation) in your CSP config or [disable](https://docs.sentry.io/platforms/javascript/guides/sveltekit/manual-setup/#disable-client-side-fetch-proxy-script) the injection of the script entirely.

## 5. Build Changes

Previously the CJS versions of the SDK code (wrongfully) contained compatibility statements for default exports in ESM:
Expand Down Expand Up @@ -483,6 +487,10 @@ Sentry.init({

- Deprecated the `hideSourceMaps` option. There are no replacements for this option. The SDK emits hidden sourcemaps by default.

### `@sentry/sveltekit`

- The `fetchProxyScriptNonce` option in `sentryHandle()` was deprecated due to security concerns. If you previously specified this option for your CSP policy, specify a [script hash](https://docs.sentry.io/platforms/javascript/guides/sveltekit/manual-setup/#configure-csp-for-client-side-fetch-instrumentation) in your CSP config or [disable](https://docs.sentry.io/platforms/javascript/guides/sveltekit/manual-setup/#disable-client-side-fetch-proxy-script) the injection of the script entirely.

## `@sentry/opentelemetry`

- Deprecated the `generateSpanContextForPropagationContext` method. There are no replacements for this method.
Expand Down
27 changes: 7 additions & 20 deletions packages/sveltekit/src/server/handle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,15 +43,6 @@ export type SentryHandleOptions = {
* @default true
*/
injectFetchProxyScript?: boolean;

/**
* If this option is set, the `sentryHandle` handler will add a nonce attribute to the script
* tag it injects into the page. This script is used to enable instrumentation of `fetch` calls
* in `load` functions.
*
* Use this if your CSP policy blocks the fetch proxy script injected by `sentryHandle`.
*/
fetchProxyScriptNonce?: string;
};

/**
Expand All @@ -68,21 +59,17 @@ export const FETCH_PROXY_SCRIPT = `
/**
* Adds Sentry tracing <meta> tags to the returned html page.
* Adds Sentry fetch proxy script to the returned html page if enabled in options.
* Also adds a nonce attribute to the script tag if users specified one for CSP.
*
* Exported only for testing
*/
export function addSentryCodeToPage(options: SentryHandleOptions): NonNullable<ResolveOptions['transformPageChunk']> {
const { fetchProxyScriptNonce, injectFetchProxyScript } = options;
// if injectFetchProxyScript is not set, we default to true
const shouldInjectScript = injectFetchProxyScript !== false;
const nonce = fetchProxyScriptNonce ? `nonce="${fetchProxyScriptNonce}"` : '';

export function addSentryCodeToPage(options: { injectFetchProxyScript: boolean }): NonNullable<
ResolveOptions['transformPageChunk']
> {
return ({ html }) => {
const metaTags = getTraceMetaTags();
const headWithMetaTags = metaTags ? `<head>\n${metaTags}` : '<head>';

const headWithFetchScript = shouldInjectScript ? `\n<script ${nonce}>${FETCH_PROXY_SCRIPT}</script>` : '';
const headWithFetchScript = options.injectFetchProxyScript ? `\n<script>${FETCH_PROXY_SCRIPT}</script>` : '';

const modifiedHead = `${headWithMetaTags}${headWithFetchScript}`;

Expand All @@ -106,7 +93,7 @@ export function addSentryCodeToPage(options: SentryHandleOptions): NonNullable<R
* ```
*/
export function sentryHandle(handlerOptions?: SentryHandleOptions): Handle {
const options = {
const options: Required<SentryHandleOptions> = {
handleUnknownRoutes: false,
injectFetchProxyScript: true,
...handlerOptions,
Expand Down Expand Up @@ -144,7 +131,7 @@ export function sentryHandle(handlerOptions?: SentryHandleOptions): Handle {

async function instrumentHandle(
{ event, resolve }: Parameters<Handle>[0],
options: SentryHandleOptions,
options: Required<SentryHandleOptions>,
): Promise<Response> {
if (!event.route?.id && !options.handleUnknownRoutes) {
return resolve(event);
Expand Down Expand Up @@ -174,7 +161,7 @@ async function instrumentHandle(
normalizedRequest: winterCGRequestToRequestData(event.request.clone()),
});
const res = await resolve(event, {
transformPageChunk: addSentryCodeToPage(options),
transformPageChunk: addSentryCodeToPage({ injectFetchProxyScript: options.injectFetchProxyScript }),
});
if (span) {
setHttpStatus(span, res.status);
Expand Down
20 changes: 4 additions & 16 deletions packages/sveltekit/test/server/handle.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -432,36 +432,24 @@ describe('addSentryCodeToPage', () => {
</html>`;

it("Adds add meta tags and fetch proxy script if there's no active transaction", () => {
const transformPageChunk = addSentryCodeToPage({});
const transformPageChunk = addSentryCodeToPage({ injectFetchProxyScript: true });
const transformed = transformPageChunk({ html, done: true });

expect(transformed).toContain('<meta name="sentry-trace"');
expect(transformed).toContain('<meta name="baggage"');
expect(transformed).not.toContain('sentry-transaction=');
expect(transformed).toContain(`<script >${FETCH_PROXY_SCRIPT}</script>`);
expect(transformed).toContain(`<script>${FETCH_PROXY_SCRIPT}</script>`);
});

it('adds meta tags and the fetch proxy script if there is an active transaction', () => {
const transformPageChunk = addSentryCodeToPage({});
const transformPageChunk = addSentryCodeToPage({ injectFetchProxyScript: true });
SentryNode.startSpan({ name: 'test' }, () => {
const transformed = transformPageChunk({ html, done: true }) as string;

expect(transformed).toContain('<meta name="sentry-trace"');
expect(transformed).toContain('<meta name="baggage"');
expect(transformed).toContain('sentry-transaction=test');
expect(transformed).toContain(`<script >${FETCH_PROXY_SCRIPT}</script>`);
});
});

it('adds a nonce attribute to the script if the `fetchProxyScriptNonce` option is specified', () => {
const transformPageChunk = addSentryCodeToPage({ fetchProxyScriptNonce: '123abc' });
SentryNode.startSpan({ name: 'test' }, () => {
const transformed = transformPageChunk({ html, done: true }) as string;

expect(transformed).toContain('<meta name="sentry-trace"');
expect(transformed).toContain('<meta name="baggage"');
expect(transformed).toContain('sentry-transaction=test');
expect(transformed).toContain(`<script nonce="123abc">${FETCH_PROXY_SCRIPT}</script>`);
expect(transformed).toContain(`<script>${FETCH_PROXY_SCRIPT}</script>`);
});
});

Expand Down
Loading