Skip to content

Commit

Permalink
💥 custom CSP will always extend Shopify domain and default developmen…
Browse files Browse the repository at this point in the history
…t domain (#1593)

* ✨ add applyDefault option to createContentSecurityPolicy

* Update .changeset/heavy-coins-tickle.md

Co-authored-by: Bret Little <bret.little@shopify.com>

* 🔥 remove applyDefault option and make extension the default behaviour

---------

Co-authored-by: Bret Little <bret.little@shopify.com>
  • Loading branch information
michenly and blittle authored Jan 5, 2024
1 parent 94509b7 commit a69c21c
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 12 deletions.
5 changes: 5 additions & 0 deletions .changeset/heavy-coins-tickle.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@shopify/hydrogen': minor
---

💥 Change the behaviour of `createContentSecurityPolicy` where the custom rules passed in will extends the default Shopify and development domains instead of overriding them.
16 changes: 4 additions & 12 deletions packages/hydrogen/src/csp/csp.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,28 +25,20 @@ describe('createContentSecurityPolicy', () => {
it('adds custom directives', () => {
expect(
createContentSecurityPolicy({
styleSrc: [
"'self'",
'https://cdn.shopify.com',
'https://some-custom-css.cdn',
],
styleSrc: ['https://some-custom-css.cdn'],
}).header,
).toBe(
`base-uri 'self'; default-src 'self' 'nonce-somenonce' https://cdn.shopify.com https://shopify.com; frame-ancestors none; style-src 'self' https://cdn.shopify.com https://some-custom-css.cdn; connect-src 'self' https://monorail-edge.shopifysvc.com`,
`base-uri 'self'; default-src 'self' 'nonce-somenonce' https://cdn.shopify.com https://shopify.com; frame-ancestors none; style-src https://some-custom-css.cdn 'self' 'unsafe-inline' https://cdn.shopify.com; connect-src 'self' https://monorail-edge.shopifysvc.com`,
);
});

it('adds nonce to custom directives', () => {
expect(
createContentSecurityPolicy({
scriptSrc: [
"'self'",
'https://cdn.shopify.com',
'https://some-custom-css.cdn',
],
scriptSrc: ['https://some-custom-css.cdn'],
}).header,
).toBe(
`base-uri 'self'; default-src 'self' 'nonce-somenonce' https://cdn.shopify.com https://shopify.com; frame-ancestors none; style-src 'self' 'unsafe-inline' https://cdn.shopify.com; connect-src 'self' https://monorail-edge.shopifysvc.com; script-src 'self' https://cdn.shopify.com https://some-custom-css.cdn 'nonce-somenonce'`,
`base-uri 'self'; default-src 'self' 'nonce-somenonce' https://cdn.shopify.com https://shopify.com; frame-ancestors none; style-src 'self' 'unsafe-inline' https://cdn.shopify.com; connect-src 'self' https://monorail-edge.shopifysvc.com; script-src https://some-custom-css.cdn 'nonce-somenonce'`,
);
});
});
Expand Down
26 changes: 26 additions & 0 deletions packages/hydrogen/src/csp/csp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,16 @@ function createCSPHeader(

const combinedDirectives = Object.assign({}, defaultDirectives, directives);

//add defaults if it was override
for (const key in defaultDirectives) {
if (directives[key]) {
combinedDirectives[key] = addCspDirective(
directives[key],
defaultDirectives[key],
);
}
}

// Make sure that at least script-src includes a nonce directive.
// If someone doesn't want a nonce in their CSP, they probably
// shouldn't use our utilities and just manually create their CSP.
Expand All @@ -98,3 +108,19 @@ function createCSPHeader(
directives: combinedDirectives,
});
}

function addCspDirective(
currentValue: string[] | string | boolean,
value: string[] | string | boolean,
): boolean | string[] {
const normalizedValue = typeof value === 'string' ? [value] : value;
const normalizedCurrentValue = Array.isArray(currentValue)
? currentValue
: [String(currentValue)];

const newValue = Array.isArray(normalizedValue)
? [...normalizedCurrentValue, ...normalizedValue]
: normalizedValue;

return newValue;
}

0 comments on commit a69c21c

Please sign in to comment.