{"id":22389529,"url":"https://github.com/davidbuck/example-nextjs-csp-setup","last_synced_at":"2025-03-26T21:26:23.905Z","repository":{"id":247675780,"uuid":"826533850","full_name":"DavidBuck/example-nextjs-csp-setup","owner":"DavidBuck","description":"A simple example showing how to get the default Next.js template working with a secure Content Security Policy (CSP)","archived":false,"fork":false,"pushed_at":"2024-07-09T23:35:12.000Z","size":88,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-02-01T03:26:14.863Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"CSS","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/DavidBuck.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-07-09T22:26:27.000Z","updated_at":"2024-08-20T02:38:37.000Z","dependencies_parsed_at":"2024-07-10T02:47:20.250Z","dependency_job_id":"7c6e554d-bcf8-4b48-b40d-e3278b3d1550","html_url":"https://github.com/DavidBuck/example-nextjs-csp-setup","commit_stats":null,"previous_names":["davidbuck/example-nextjs-csp-setup"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DavidBuck%2Fexample-nextjs-csp-setup","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DavidBuck%2Fexample-nextjs-csp-setup/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DavidBuck%2Fexample-nextjs-csp-setup/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DavidBuck%2Fexample-nextjs-csp-setup/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/DavidBuck","download_url":"https://codeload.github.com/DavidBuck/example-nextjs-csp-setup/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245737744,"owners_count":20664163,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-12-05T03:12:12.068Z","updated_at":"2025-03-26T21:26:23.883Z","avatar_url":"https://github.com/DavidBuck.png","language":"CSS","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Example NextJS CSP Setup\n\nA simple example showing how to get the default Next.js template working with a secure Content Security Policy (CSP).\n\nThe project was created using: `$ npx create-next-app@latest`\n\n## 1. Add a nonce-based CSP using middleware\n\nin /middleware.js\n\n```javascript\nimport { NextResponse } from 'next/server'\n \nexport function middleware(request) {\n  const nonce = Buffer.from(crypto.randomUUID()).toString('base64')\n  const cspHeader = `\n  default-src 'self';\n  script-src 'self'  'nonce-${nonce}'  ${\n    process.env.NODE_ENV === \"production\" ? `` : `'unsafe-eval'`\n  };\n  style-src 'self' 'unsafe-inline';\n  img-src 'self' blob: data:;\n  font-src 'self';\n  object-src 'none';\n  base-uri 'self';\n  form-action 'self';\n  frame-ancestors 'none';\n  upgrade-insecure-requests;\n`;\n\n  // Replace newline characters and spaces\n  const contentSecurityPolicyHeaderValue = cspHeader\n    .replace(/\\s{2,}/g, ' ')\n    .trim()\n \n  const requestHeaders = new Headers(request.headers)\n  requestHeaders.set('x-nonce', nonce)\n  requestHeaders.set(\n    'Content-Security-Policy',\n    contentSecurityPolicyHeaderValue\n  )\n \n  const response = NextResponse.next({\n    request: {\n      headers: requestHeaders,\n    },\n  })\n  response.headers.set(\n    'Content-Security-Policy',\n    contentSecurityPolicyHeaderValue\n  )\n \n  return response\n}\n```\n\n## 2. Force dynamic rendering\n\nin /app/layout.js\n\n```javascript\nexport const dynamic = \"force-dynamic\";\n```\n\n## 3. Remove next/image inline styles\n\nOverride the default Next/Image component and remove the  inline style `(style=\"color:transparent\" )` \n\nin /app/\\_components/image.js\n\n\n```javascript\nimport { getImageProps } from \"next/image\"\n\nexport default function Image(props) {\n  const { props: nextProps } = getImageProps({\n    ...props\n  })\n\n  const { style: _omit, ...delegated } = nextProps\n\n  return \u003cimg {...delegated} /\u003e\n}\n```\n\n\nFinally, update the imports in /app/page.js\n\n```javascript\n// import Image from \"next/image\";\nimport Image from \"./_components/image\";\n```\n\nThe CSP should now work in development and production modes without error.\n`$ npm run dev`\n`$ npm run build \u0026\u0026 npm run start`\n\n# References\n\n[Middleware Setup](https://nextjs.org/docs/pages/building-your-application/configuring/content-security-policy#adding-a-nonce-with-middleware)\n\n[Remove Next/image inline style](https://github.com/vercel/next.js/issues/45184#issuecomment-1988319088)\n\nIssues relating to next/image, inline syles and CSP - [#61388](https://github.com/vercel/next.js/issues/61388), [#45184](https://github.com/vercel/next.js/issues/45184).\n\n\n\n\n\n\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdavidbuck%2Fexample-nextjs-csp-setup","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdavidbuck%2Fexample-nextjs-csp-setup","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdavidbuck%2Fexample-nextjs-csp-setup/lists"}