Skip to content
Merged
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
2 changes: 1 addition & 1 deletion website/public/staticwebapp.config.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
}
},
"globalHeaders": {
"content-security-policy": "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data: https:; connect-src 'self' https:; frame-ancestors 'none'; base-uri 'self'; form-action 'self'",
"content-security-policy": "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data: https:; connect-src 'self' https:; frame-ancestors 'none'; base-uri 'self'; form-action 'self'",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== candidate files =="
git ls-files | rg '(^|/)(staticwebapp\.config\.json|package\.json|next\.config\.(js|mjs)|README|docs?|SECURITY|Dockerfile|github/workflows|package-lock\.json|pnpm-lock\.yaml|yarn\.lock)$' || true

echo
echo "== staticwebapp config =="
if [ -f website/public/staticwebapp.config.json ]; then
  cat -n website/public/staticwebapp.config.json
fi

echo
echo "== next config files outline/contents =="
for f in $(git ls-files | rg 'next\.config\.(js|mjs)$' || true); do
  echo "--- $f ($(wc -l < "$f") lines) ---"
  sed -n '1,220p' "$f"
done

echo
echo "== package scripts/deps snippets =="
if [ -f package.json ]; then
  node - <<'JS'
const fs=require('fs');
const p=JSON.parse(fs.readFileSync('package.json','utf8'));
console.log(JSON.stringify({scripts:p.scripts, dependencies:p.dependencies, devDependencies:p.devDependencies, packageManager:p.packageManager}, null, 2));
JS
fi

echo
echo "== security/csp mentions =="
rg -n -i "unsafe-inline|content-security-policy|csp|nonce|hash|static.*export|next export|output\s*[:=]|trailingSlash|security|xss|vulnerab" README package.json website docs .github 2>/dev/null || true

echo
echo "== staticwebapp occurrences =="
rg -n "content-security-policy|staticwebapp|staticWebApp|headers|securityHeaders" .

Repository: phoenixvc/codeflow-engine

Length of output: 50382


🌐 Web query:

Next.js static export script-src unsafe-inline CSP script runtime environment client side rendering

💡 Result:

When using Next.js with static exports, enforcing a Content Security Policy (CSP) that excludes 'unsafe-inline' is challenging because Next.js injects mandatory inline scripts (such as self.next_f.push for state management and hydration) into the generated HTML [1][2]. Since static pages are generated at build time, they cannot utilize request-specific nonces, which are the standard mechanism for allowing legitimate inline scripts in dynamic Next.js applications [3][4]. Key Technical Constraints: 1. Static Limitation: CSP nonces require dynamic server-side rendering because every request must generate a fresh, unique nonce [3][5]. Static exports lack this request-response cycle, making nonce-based CSPs incompatible with standard static deployment [3][4]. 2. Inline Script Injection: Next.js relies on inline scripts for core functionality, including client-side hydration and dynamic component loading [1][2]. Without 'unsafe-inline', these scripts are blocked, typically resulting in a broken, non-functional application [2]. Workarounds and Approaches: - Allowing 'unsafe-inline': The most straightforward, albeit less secure, approach is to include 'unsafe-inline' in your CSP script-src directive [6][7]. - Post-Build HTML Rewriting: Some developers bypass this by implementing a post-build script that extracts inline scripts into external files, updates the HTML to reference these files, and then serves the application with a stricter CSP that only allows 'self' [1]. - CSP Hashes: Theoretically, you could use hash-based CSPs for static inline scripts [8]. However, Next.js does not provide built-in support for automatically generating and applying these hashes during static export, making it a complex manual task to maintain as build outputs change [1][8]. - Moving to Dynamic Rendering: If a strict CSP (without 'unsafe-inline') is a hard requirement, you must move away from static export and use dynamic rendering (e.g., SSR or Server Components), which enables the injection of per-request nonces [3][9][5]. For applications requiring high security, prioritize evaluating if the trade-off of disabling static optimization in favor of dynamic rendering is acceptable to enable a strict, nonce-based CSP [4]. If you must stick with static exports, be aware that you are trading off strict CSP compliance for the performance benefits of static site generation [4].

Citations:


Document the script-src 'unsafe-inline' exception.

The CSP now allows inline script execution globally, which can let an HTML-injection flaw run arbitrary JavaScript. Since this static-export Next.js build needs inline scripts, add a focused CSP-violation scan/test and monitoring, and document why nonce/hash-based CSP is not feasible; otherwise narrow the policy.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@website/public/staticwebapp.config.json` at line 21, Update the CSP
configuration around the content-security-policy entry to document why the
static-export Next.js build requires script-src 'unsafe-inline' and why
nonce/hash-based protection is not feasible. Add a focused CSP-violation scan or
test and monitoring for inline-script violations; if the build does not require
the exception, remove it and narrow script-src instead.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Avoid allowing arbitrary inline scripts

Because this header is applied globally in Azure Static Web Apps, adding script-src 'unsafe-inline' does more than permit the Next-generated static snippets: it also authorizes any injected inline <script> or inline event handler on every route. That removes the XSS mitigation the previous script-src 'self' provided; for a static export, prefer build-time CSP hashes for the deterministic Next inline scripts, or another page-specific CSP mechanism, instead of globally allowing all inline script execution.

Useful? React with 👍 / 👎.

"strict-transport-security": "max-age=31536000; includeSubDomains; preload",
"x-content-type-options": "nosniff",
"x-frame-options": "DENY",
Expand Down
Loading