Skip to content

Commit

Permalink
feat: migration to SDK v2 (#40)
Browse files Browse the repository at this point in the history
* chore: in progress migration - migration handlers to tRPC and updating UI

* chore: ignore some typing and see if it will build

* feat: get form to work further

* feat: add functionality in new extension ui

* feat: add logging for buildconfig

* feat: last fixes with types

* feat: show success in deploy summary

* chore: last bits and bobs for extension migration

* chore: try to figure out why uninstall does not work

* chore: remove uninstall part

* chore: implement feedback

---------

Co-authored-by: Netlify Bot <[email protected]>
  • Loading branch information
khendrikse and netlify-bot authored Oct 2, 2024
1 parent d5bdc2b commit 9cb2744
Show file tree
Hide file tree
Showing 23 changed files with 15,351 additions and 3,306 deletions.
76 changes: 76 additions & 0 deletions details.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
Use a [nonce](https://content-security-policy.com/nonce/) for the `script-src` directive of your Content Security Policy (CSP) to help prevent [cross-site scripting (XSS)](https://developer.mozilla.org/en-US/docs/Web/Security/Types_of_attacks#cross-site_scripting_xss) attacks.

This extension deploys an edge function that adds a response header and transforms the HTML response body to contain a unique nonce on every request, along with an optional function to log CSP violations.

Scripts that do not contain a matching `nonce` attribute, or that were not created from a trusted script (see [strict-dynamic](https://content-security-policy.com/strict-dynamic/)), will not be allowed to run.

You can use this extension whether or not your site already has a CSP in place. If your site already has a CSP, the nonce will merge with your existing directives.

🧩 This extension is installed and configured in the Netlify UI. If you prefer a configuration-as-code approach, check out the [@netlify/plugin-csp-nonce](https://www.npmjs.com/package/@netlify/plugin-csp-nonce) npm package.

## Configuration options

- #### `reportOnly`

_Default: `true`_.

When true, uses the `Content-Security-Policy-Report-Only` header instead of the `Content-Security-Policy` header. Setting `reportOnly` to `true` is useful for testing the CSP with real production traffic without actually blocking resources. Be sure to monitor your logging function to observe potential violations.

- #### `reportUri`

_Default: `undefined`_.

The relative or absolute URL to report any violations. If left undefined, violations are reported to the `__csp-violations` function, which this extension deploys. If your site already has a `report-uri` directive defined in its CSP header, then that value will take precedence.

- #### `unsafeEval`

_Default: `true`._

When true, adds `'unsafe-eval'` to the CSP for easier adoption. Set to `false` to have a safer policy if your code and code dependencies does not use `eval()`.

- #### `path`

_Default: `/*`._

The glob expressions of path(s) that should invoke the CSP nonce edge function. Can be a string or array of strings.

- #### `excludedPath`

_Default: `[]`_

The glob expressions of path(s) that _should not_ invoke the CSP nonce edge function. Must be an array of strings. This value gets spread with common non-html filetype extensions (`*.css`, `*.js`, `*.svg`, etc).

## Debugging

### Limiting edge function invocations

By default, the edge function that inserts the nonce will be invoked on all requests whose path

- does not begin with `/.netlify/`
- does not end with common non-HTML filetype extensions

To further limit invocations, add globs to the `excludedPath` configuration option that are specific to your site.

Requests that invoke the nonce edge function will contain a `x-debug-csp-nonce: invoked` response header. Use this to determine if unwanted paths are invoking the edge function, and add those paths to the `excludedPath` array.

Also, monitor the edge function logs in the Netlify UI. If the edge function is invoked but the response is not transformed, the request's path will be logged.

### Not transforming as expected

If your HTML does not contain the `nonce` attribute on the `<script>` tags that you expect, ensure that all of these criteria are met:

- The request method is `GET`
- The `content-type` response header starts with `text/html`
- The path of the request is satisfied by the `path` config option, and not included in the `excludedPath` config option

### Controlling rollout

You may want to gradually rollout the effects of this extension while you monitor violation reports, without modifying code.

You can ramp up or ramp down the inclusion of the `Content-Security-Policy` header by setting the `CSP_NONCE_DISTRIBUTION` environment variable to a value between `0` and `1`.

- If `0`, the extension is completely skipped at build time, and no extra functions or edge functions get deployed. Functionally, this acts the same as if the extension isn't installed at all.
- If `1`, 100% of traffic for all matching paths will include the nonce. Functionally, this acts the same as if the `CSP_NONCE_DISTRIBUTION` environment variable was not defined.
- Any value in between `0` and `1` will include the nonce in randomly distributed traffic. For example, a value of `0.25` will put the nonce in the `Content-Security-Policy` header 25% of requests for matching paths. The other 75% of matching requests will have the nonce in the `Content-Security-Policy-Report-Only` header.

The `CSP_NONCE_DISTRIBUTION` environment variable needs to be scoped to both `Builds` and `Functions`.
9 changes: 9 additions & 0 deletions extension.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
config:
slug: yl9z8yms-migrate-csp-extension

# set this to true to add a global require shim to esbuild. Workaround for https://github.com/evanw/esbuild/issues/1921
use_cjs_shims: false

ui:
surfaces:
- extension-site-build-and-deploy-configuration
2 changes: 0 additions & 2 deletions integration.yaml

This file was deleted.

18 changes: 8 additions & 10 deletions netlify.toml
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
[build]
command="ntli build -a"
functions=".ntli/site/netlify/functions"
publish=".ntli/site/static"
command = "netlify-extension build"
publish = ".ntli/site/static"

[[headers]]
for="/ui/*"
[headers.values]
Access-Control-Allow-Origin="*"
Access-Control-Allow-Headers="*"
Access-Control-Allow-Methods="*"
[dev]
command = "netlify-extension dev"

[functions]
node_bundler = "esbuild"
directory = "src/endpoints"

[[plugins]]
package = "@netlify/netlify-plugin-netlify-extension"
33 changes: 27 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,34 @@
"main": "src/index.ts",
"type": "module",
"scripts": {
"build": "ntli build -a",
"dev": "ntli dev -a",
"preview": "ntli preview"
"build": "netlify-extension build",
"dev": "netlify-extension dev --open"
},
"dependencies": {
"@netlify/build": "^29.54.2",
"@netlify/functions": "^2.8.1",
"@netlify/plugin-csp-nonce": "^1.2.9",
"@netlify/sdk": "^1.5.0",
"typescript": "^5.1.6"
"@netlify/sdk": "^2.3.0",
"@tanstack/react-query": "^5.55.4",
"@trpc/client": "11.0.0-rc.477",
"@trpc/react-query": "11.0.0-rc.477",
"@trpc/server": "11.0.0-rc.477",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"typescript": "^5.1.6",
"zod": "^3.23.8"
},
"devDependencies": {
"@netlify/netlify-plugin-netlify-extension": "^1.0.0",
"@tsconfig/recommended": "^1.0.7",
"@tsconfig/strictest": "^2.0.5",
"@tsconfig/vite-react": "^3.0.2",
"@types/react": "^18.3.5",
"@types/react-dom": "^18.3.0",
"@vitejs/plugin-react": "^4.3.1",
"autoprefixer": "^10.4.20",
"netlify-cli": "^17.35.0",
"tailwindcss": "^3.4.10",
"vite": "^5.4.3"
}
}
}
Loading

0 comments on commit 9cb2744

Please sign in to comment.