Skip to content
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

@W-14446652@ Change CSP enforcement to an opt-in middleware. #1528

Merged
merged 8 commits into from
Nov 7, 2023

Conversation

wjhsf
Copy link
Contributor

@wjhsf wjhsf commented Nov 7, 2023

In v3.2.0, to facilitate adoption of Storefront Preview, we introduced logic to enforce a Content-Security-Policy header containing all the directives that are required for PWA Kit / Storefront Preview to function. However, while making CSP management easier for those who use it, this is a breaking change for users who explicitly do not use the Content-Security-Policy header. 🤕 Oops.

This PR simply removes the middleware function from the internal logic of pwa-kit-runtime and exports it so that end users must opt in to using the function.

Description

Types of Changes

  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Documentation update
  • Breaking change (could cause existing functionality to not work as expected)
  • Other changes (non-breaking changes that does not fit any of the above)

Breaking changes include:

  • Removing a public function or component or prop
  • Adding a required argument to a function
  • Changing the data type of a function parameter or return value
  • Adding a new peer dependency to package.json

Changes

  • (change1)

How to Test-Drive This PR

  • Check out v3.2.0, launch the app, save the CSP header.
  • Check out this code, launch the app. CSP header should be the same.
  • Remove the two security header middleware functions. Restart the app. CSP header should not be present.
    app.use(defaultSecurityHeaders)
    // Set custom HTTP security headers
    app.use(
    helmet({
    contentSecurityPolicy: {
    useDefaults: true,
    directives: {
    'img-src': [
    // Default source for product images - replace with your CDN
    '*.commercecloud.salesforce.com'
    ],
    'script-src': [
    // Used by the service worker in /worker/main.js
    'storage.googleapis.com'
    ],
    'connect-src': [
    // Connect to Einstein APIs
    'api.cquotient.com'
    ]
    }
    }
    })
    )
  • Bonus fun: move the defaultSecurityHeaders middleware to after the helmet middleware and see that it doesn't change the CSP!

Checklists

General

  • Changes are covered by test cases
  • CHANGELOG.md updated with a short description of changes (not required for documentation updates)

Accessibility Compliance

You must check off all items in one of the follow two lists:

  • There are no changes to UI

or...

Localization

  • Changes include a UI text update in the Retail React App (which requires translation)

@wjhsf wjhsf requested a review from a team as a code owner November 7, 2023 17:30
@@ -34,11 +34,11 @@ const options = {
const runtime = getRuntime()

const {handler} = runtime.createHandler(options, (app) => {
// Set HTTP security headers
// Use default HTTP security headers required by PWA Kit
app.use(defaultSecurityHeaders)
Copy link
Collaborator

@kevinxh kevinxh Nov 7, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does "default" mean in this context? 🤔 we might want to be a bit more specific and call it likestorefrontPreviewSecurityHeaders(prob also a bad name) ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By "default" I just mean "mandatory for PWA Kit to work". So it's not just Storefront Preview, even though that was the motivation for the change. And they're not strictly required if a project is using pwa-kit-runtime for something other than the retail react app.

Naming things is hard. 🤔

Copy link
Collaborator

@kevinxh kevinxh Nov 7, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I'm a developer, I would want to know the benefit of opting in defaultSecurityHeaders

The answer is: you can't use storefront preview on runtime admin... <- this might not be clear to end users.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wait... i think i might have misunderstanding...

if it is "mandatory for PWA Kit to work", why do we make it an opt-in?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because some users don't want to have any CSP header, and @johnboxall said we should make it opt-in, rather than opt-out.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On naming: https://chat.openai.com/share/d5a18a26-08b3-47ea-a1ac-952dee512285

I don't have strong feelings, but the name should communicate that a) it is a express.js middleware [can also be implied from import] b) it sets security related headers required for using the PWA Kit

Yes, folks should be allowed to opt into these headers – LWR sites as an example don't want the PWA Kit CSP.

Also, some customers struggle to create a CSP. They're hard. Sometimes letting them go is the only way they can truly be free.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My vote is on adding 'pwakit' to the name, like defaultPwaKitSecurityHeaders, so that it's more distinguishable. Because helmet also has a similar concept of defaults (see useDefaults on line 43).

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 agree defaultPwaKitSecurityHeaders is preferable

@@ -34,11 +34,11 @@ const options = {
const runtime = getRuntime()

const {handler} = runtime.createHandler(options, (app) => {
Copy link
Collaborator

@kevinxh kevinxh Nov 7, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The behavior of enabling default headers seems more natural to me if it’s a configuration value…

const options = {
   ...,
   enableDefaultSecurityHeaders: true
}

kevinxh
kevinxh previously approved these changes Nov 7, 2023
@@ -460,3 +463,102 @@ export const getRuntime = () => {

return boundRuntime
}

/**
* Patches `res.setHeader` to ensure that the Content-Security-Policy header always includes the
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment describes part of what this function does:

  1. It is an express.js middleware that sets default security headers including CSP + HSTS for PWA Kit sites.
  2. It patches res.setHeader to include defaults normally required for PWA Kit operation.

packages/pwa-kit-runtime/CHANGELOG.md Show resolved Hide resolved
@@ -34,11 +34,11 @@ const options = {
const runtime = getRuntime()

const {handler} = runtime.createHandler(options, (app) => {
// Set HTTP security headers
// Use default HTTP security headers required by PWA Kit
app.use(defaultSecurityHeaders)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My vote is on adding 'pwakit' to the name, like defaultPwaKitSecurityHeaders, so that it's more distinguishable. Because helmet also has a similar concept of defaults (see useDefaults on line 43).

Copy link
Collaborator

@bfeister bfeister left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think @johnboxall's point about extending the existing patch and then the PWA Kit namespacing of the mixin variable need some resolution before we merge this

@vmarta
Copy link
Contributor

vmarta commented Nov 7, 2023

@wjhsf Let's review what the target branch should be for this PR. If we want this to be a hot fix, then we'll want to merge it into the release-3.2.x branch instead.

@wjhsf wjhsf changed the base branch from develop to release-3.2.x November 7, 2023 22:10
@wjhsf wjhsf requested a review from vmarta November 7, 2023 22:42
@wjhsf wjhsf merged commit 6a614ba into release-3.2.x Nov 7, 2023
20 checks passed
@wjhsf wjhsf deleted the wjh/v3-fix-csp branch November 7, 2023 23:25
wjhsf added a commit that referenced this pull request Nov 8, 2023
* Declare constant in file that uses it.

* Update CHANGELOGs.

* Move CSP middleware to utils.

* Naming things is hard.

* Renaming things is hard.

* Don't touch files that don't need to be touched.

* Re-delete moved code.

* Remove outdated comment.
@vmarta vmarta mentioned this pull request Nov 8, 2023
12 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants