Implement security headers for ZAP compliance in frontend and backend#4101
Implement security headers for ZAP compliance in frontend and backend#4101saichethana28 wants to merge 1 commit intoOWASP:mainfrom
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review infoConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro 📒 Files selected for processing (3)
🚧 Files skipped from review as they are similar to previous changes (2)
Summary by CodeRabbit
WalkthroughAdds clickjacking middleware and several Django security settings (SELF_CONSTANT, X_FRAME_OPTIONS, SECURE_REFERRER_POLICY, SECURE_HSTS_SECONDS, SECURE_HSTS_INCLUDE_SUBDOMAINS, SECURE_HSTS_PRELOAD), plus a Next.js exported async headers() providing global security headers with conditional CSP/HSTS for non-local environments. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Suggested reviewers
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
frontend/next.config.ts (1)
17-21: Consider documenting the'unsafe-inline'tradeoff.Using
'unsafe-inline'inscript-srcweakens XSS protection but is often necessary for Next.js hydration. This is a reasonable tradeoff for initial ZAP compliance. For stronger security in the future, consider migrating to nonce-based CSP using Next.js's built-in support.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@frontend/next.config.ts` around lines 17 - 21, Add a short inline comment next to the Content-Security-Policy object in next.config.ts explaining that the current script-src includes 'unsafe-inline' to support Next.js hydration (XSS risk tradeoff) and recommending a future migration path to a nonce-based CSP using Next.js's built-in nonce support (or other server-side nonce injection) to remove 'unsafe-inline' for stronger protection; mention the exact policy key name (Content-Security-Policy) and the script-src token so reviewers can find and follow the guidance.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@backend/settings/base.py`:
- Around line 237-242: The CSP_* settings (CSP_DEFAULT_SRC, CSP_SCRIPT_SRC,
CSP_STYLE_SRC, CSP_IMG_SRC) are unused because Django's SecurityMiddleware
doesn't set CSP; either remove these unused settings or enable django-csp by
installing the package and wiring its middleware and app: add 'csp' to
INSTALLED_APPS and 'csp.middleware.CSPMiddleware' to MIDDLEWARE (ensure ordering
as required by django-csp), then keep the CSP_* variables (they match django-csp
names) to have the backend emit CSP headers; alternatively confirm frontend
Next.js CSP is sufficient for ZAP and delete the backend CSP_* constants if not
needed.
In `@frontend/next.config.ts`:
- Around line 9-26: The Content-Security-Policy set in the headers() function is
too restrictive for external integrations; update the Content-Security-Policy
header value (inside headers() in next.config.ts) to expand connect-src to
include Sentry ingestion endpoints (e.g., *.ingest.sentry.io or org-specific
o<id>.ingest.sentry.io), PostHog (us.i.posthog.com), and the GitHub
contributions API (github-contributions-api.jogruber.de) so those requests are
allowed; keep the existing 'self' and any required schemes (https:) and ensure
you also allow any necessary websockets or data endpoints if used by those
services.
---
Nitpick comments:
In `@frontend/next.config.ts`:
- Around line 17-21: Add a short inline comment next to the
Content-Security-Policy object in next.config.ts explaining that the current
script-src includes 'unsafe-inline' to support Next.js hydration (XSS risk
tradeoff) and recommending a future migration path to a nonce-based CSP using
Next.js's built-in nonce support (or other server-side nonce injection) to
remove 'unsafe-inline' for stronger protection; mention the exact policy key
name (Content-Security-Policy) and the script-src token so reviewers can find
and follow the guidance.
There was a problem hiding this comment.
3 issues found across 2 files
Confidence score: 3/5
- Security headers may not be emitted because CSP and X-Frame options are configured without enabling the corresponding middleware in
backend/settings/base.py, which could leave clickjacking/XSS defenses inactive. frontend/next.config.tspermits'unsafe-inline'for scripts/styles, weakening CSP protections and increasing XSS exposure.- Given the medium-severity, user-facing security implications, this carries some risk despite limited code changes.
- Pay close attention to
backend/settings/base.pyandfrontend/next.config.ts- security headers/CSP behavior.
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="backend/settings/base.py">
<violation number="1" location="backend/settings/base.py:234">
P2: X_FRAME_OPTIONS is configured but XFrameOptionsMiddleware isn’t in MIDDLEWARE, so Django won’t emit the X-Frame-Options header and clickjacking protection won’t be active.</violation>
<violation number="2" location="backend/settings/base.py:239">
P2: CSP settings are declared but no CSP middleware is enabled, and Django’s SecurityMiddleware does not consume CSP_* settings. As written, no Content-Security-Policy header will be generated despite the comment, so CSP hardening is effectively absent.</violation>
</file>
<file name="frontend/next.config.ts">
<violation number="1" location="frontend/next.config.ts:20">
P2: CSP allows 'unsafe-inline' for scripts/styles, which weakens XSS protection by permitting any inline code execution.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
879ec12 to
ef026b3
Compare
There was a problem hiding this comment.
🧹 Nitpick comments (1)
backend/settings/base.py (1)
245-245: Remove unusedSELF_CONSTANTconstant.This constant is not referenced anywhere in the codebase and appears to be leftover from incomplete or removed CSP configuration. It adds no value and should be removed to keep the settings file clean.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@backend/settings/base.py` at line 245, Remove the unused constant SELF_CONSTANT (value "'self'") from the settings module: delete the declaration of SELF_CONSTANT and any associated comments so the constant is no longer defined; run a quick project-wide search to confirm there are no remaining references before committing to ensure no accidental usages are removed.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@backend/settings/base.py`:
- Line 245: Remove the unused constant SELF_CONSTANT (value "'self'") from the
settings module: delete the declaration of SELF_CONSTANT and any associated
comments so the constant is no longer defined; run a quick project-wide search
to confirm there are no remaining references before committing to ensure no
accidental usages are removed.
|
@cubic-dev-ai review |
@saichethana28 I have started the AI code review. It will take a few minutes to complete. |
There was a problem hiding this comment.
2 issues found across 2 files
Confidence score: 3/5
- Security middleware won’t emit HSTS because
SECURE_HSTS_SECONDSisn’t set inbackend/settings/base.py, which leaves transport security weaker than expected in production. - Global CSP in
frontend/next.config.tsmay break Next.js dev tooling (HMR/scripts) if used locally, which is a mild but real developer-impact risk. - Given a moderate-severity security configuration gap, there’s some risk despite the small diff, so a cautious score is appropriate.
- Pay close attention to
backend/settings/base.pyandfrontend/next.config.ts- security headers configuration and dev tooling compatibility.
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="frontend/next.config.ts">
<violation number="1" location="frontend/next.config.ts:21">
P2: CSP is applied to all routes without a dev guard and omits `unsafe-eval`/WebSocket allowances needed by Next.js dev tooling. This can break HMR or dev script execution locally.</violation>
</file>
<file name="backend/settings/base.py">
<violation number="1" location="backend/settings/base.py:250">
P2: HSTS is still disabled in base settings. Django’s SecurityMiddleware only sends Strict-Transport-Security when SECURE_HSTS_SECONDS is a positive value, but this setting is never defined here, so the backend won’t emit HSTS despite adding other security headers.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
ef026b3 to
82a38a1
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
backend/settings/base.py (1)
245-245: Remove unusedSELF_CONSTANT.This constant is defined but not used anywhere in the configuration. It appears to be a leftover from CSP settings that were removed (per past review feedback about django-csp requirement). Dead code should be removed.
🧹 Proposed fix
- SELF_CONSTANT = "'self'" SECURE_CONTENT_TYPE_NOSNIFF = True🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@backend/settings/base.py` at line 245, Remove the dead constant SELF_CONSTANT from the settings module: delete the line defining SELF_CONSTANT = "'self'". Before removal, verify there are no remaining references to SELF_CONSTANT (search for "SELF_CONSTANT") and if any are found, replace them with the appropriate literal or refactor to the canonical value; otherwise simply remove the unused symbol to clean up dead code.frontend/next.config.ts (1)
19-25: Consider hardening CSP with additional directives.The CSP addresses the main concerns but could be strengthened with a few additional directives commonly flagged by security scanners:
🛡️ Suggested CSP improvements
value: [ "default-src 'self'", "script-src 'self' 'unsafe-inline'", "style-src 'self' 'unsafe-inline'", "img-src 'self' data: https:", - "connect-src 'self' https://*.ingest.sentry.io https://us.i.posthog.com https://github-contributions-api.jogruber.de" + "connect-src 'self' https://*.ingest.sentry.io https://us.i.posthog.com https://github-contributions-api.jogruber.de", + "object-src 'none'", + "base-uri 'self'", + "form-action 'self'", + "frame-ancestors 'none'" ].join('; '),
object-src 'none'– prevents plugin-based attacks (Flash, Java applets)base-uri 'self'– prevents<base>tag hijackingform-action 'self'– restricts form submission targetsframe-ancestors 'none'– modern CSP equivalent ofX-Frame-Options: DENY🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@frontend/next.config.ts` around lines 19 - 25, Update the CSP value array (the value: [ ... ].join('; ') block that builds the Content-Security-Policy string) to include the recommended directives: add "object-src 'none'", "base-uri 'self'", "form-action 'self'", and "frame-ancestors 'none'" to the list so they are joined into the final policy; ensure each directive is a separate entry in the array alongside the existing "default-src", "script-src", "style-src", "img-src", and "connect-src" entries and that spacing/semicolon separation matches the existing join('; ') formatting.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@frontend/next.config.ts`:
- Around line 9-31: The headers() export is missing the
Strict-Transport-Security header; update the headers() function (the returned
headers array) to include a Strict-Transport-Security entry (e.g.,
"max-age=63072000; includeSubDomains; preload") alongside the other security
headers and ensure it is only applied in non-local environments using the
existing isLocal guard (same pattern as the Content-Security-Policy entry) so
HSTS is served when the frontend is accessed directly.
---
Nitpick comments:
In `@backend/settings/base.py`:
- Line 245: Remove the dead constant SELF_CONSTANT from the settings module:
delete the line defining SELF_CONSTANT = "'self'". Before removal, verify there
are no remaining references to SELF_CONSTANT (search for "SELF_CONSTANT") and if
any are found, replace them with the appropriate literal or refactor to the
canonical value; otherwise simply remove the unused symbol to clean up dead
code.
In `@frontend/next.config.ts`:
- Around line 19-25: Update the CSP value array (the value: [ ... ].join('; ')
block that builds the Content-Security-Policy string) to include the recommended
directives: add "object-src 'none'", "base-uri 'self'", "form-action 'self'",
and "frame-ancestors 'none'" to the list so they are joined into the final
policy; ensure each directive is a separate entry in the array alongside the
existing "default-src", "script-src", "style-src", "img-src", and "connect-src"
entries and that spacing/semicolon separation matches the existing join('; ')
formatting.
82a38a1 to
7a4c4f5
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
frontend/next.config.ts (2)
24-32: Consider strengthening CSP with additional directives.The CSP is functional but could be hardened with a few additional directives for defense-in-depth:
frame-ancestors 'none'— aligns withX-Frame-Options: DENYfor modern browsers (CSP takes precedence)object-src 'none'— explicitly blocks plugin-based content (Flash, Java applets)base-uri 'self'— prevents<base>tag injection attacks🛡️ Optional CSP enhancement
{ key: 'Content-Security-Policy', value: [ "default-src 'self'", "script-src 'self' 'unsafe-inline'", "style-src 'self' 'unsafe-inline'", "img-src 'self' data: https:", - "connect-src 'self' https://*.ingest.sentry.io https://us.i.posthog.com https://github-contributions-api.jogruber.de" + "connect-src 'self' https://*.ingest.sentry.io https://us.i.posthog.com https://github-contributions-api.jogruber.de", + "frame-ancestors 'none'", + "object-src 'none'", + "base-uri 'self'" ].join('; '), }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@frontend/next.config.ts` around lines 24 - 32, The Content-Security-Policy header value (the object with key: 'Content-Security-Policy' in frontend/next.config.ts) should be hardened by appending the directives "frame-ancestors 'none'", "object-src 'none'", and "base-uri 'self'" to the array of policy strings before joining; update the array that currently contains default-src, script-src, style-src, img-src, and connect-src to also include these three directives so the final joined CSP string includes them.
27-28: Note:'unsafe-inline'weakens CSP protection.Using
'unsafe-inline'forscript-srcandstyle-srcis often necessary for Next.js (hydration scripts, CSS-in-JS), but it does reduce XSS protection. If you want to strengthen this in the future, consider implementing CSP nonces via Next.js middleware—though this adds complexity and may not be needed for current ZAP compliance goals.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@frontend/next.config.ts` around lines 27 - 28, The CSP entries in next.config.ts currently include "script-src 'self' 'unsafe-inline'" and "style-src 'self' 'unsafe-inline'", which weakens XSS protection; replace the inline allowances by implementing per-request nonces: add a Next.js middleware that generates a nonce and attaches it to the response header (e.g., Content-Security-Policy with script-src 'self' 'nonce-{nonce}' and style-src 'self' 'nonce-{nonce}'), then update your rendering to inject that nonce into inline scripts/styles (e.g., pass the nonce into _document.tsx / Document and into next/script tags via the nonce prop) so you can remove 'unsafe-inline' from the CSP entries in next.config.ts.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@frontend/next.config.ts`:
- Line 30: Remove the unused GitHub contributions API host from the CSP
connect-src string in frontend/next.config.ts by editing the connect-src
directive value (the string that currently includes "connect-src 'self'
https://*.ingest.sentry.io https://us.i.posthog.com
https://github-contributions-api.jogruber.de") and delete the
"https://github-contributions-api.jogruber.de" entry so the directive only lists
the actively used endpoints (https://*.ingest.sentry.io and
https://us.i.posthog.com).
---
Nitpick comments:
In `@frontend/next.config.ts`:
- Around line 24-32: The Content-Security-Policy header value (the object with
key: 'Content-Security-Policy' in frontend/next.config.ts) should be hardened by
appending the directives "frame-ancestors 'none'", "object-src 'none'", and
"base-uri 'self'" to the array of policy strings before joining; update the
array that currently contains default-src, script-src, style-src, img-src, and
connect-src to also include these three directives so the final joined CSP
string includes them.
- Around line 27-28: The CSP entries in next.config.ts currently include
"script-src 'self' 'unsafe-inline'" and "style-src 'self' 'unsafe-inline'",
which weakens XSS protection; replace the inline allowances by implementing
per-request nonces: add a Next.js middleware that generates a nonce and attaches
it to the response header (e.g., Content-Security-Policy with script-src 'self'
'nonce-{nonce}' and style-src 'self' 'nonce-{nonce}'), then update your
rendering to inject that nonce into inline scripts/styles (e.g., pass the nonce
into _document.tsx / Document and into next/script tags via the nonce prop) so
you can remove 'unsafe-inline' from the CSP entries in next.config.ts.
ℹ️ Review info
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
backend/settings/base.pyfrontend/next.config.ts
🚧 Files skipped from review as they are similar to previous changes (1)
- backend/settings/base.py
7a4c4f5 to
77be1ee
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
backend/settings/base.py (1)
245-245: Remove the unusedSELF_CONSTANTconstant.This constant is not referenced anywhere in the codebase and appears to be leftover from CSP settings that have been removed.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@backend/settings/base.py` at line 245, Remove the unused constant SELF_CONSTANT from settings/base.py by deleting the line defining SELF_CONSTANT = "'self'"; search the codebase for any references to SELF_CONSTANT to confirm it's safe to remove and run tests/lint to ensure no regressions.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@backend/settings/base.py`:
- Around line 252-255: Update HSTS configuration so SECURE_HSTS_PRELOAD is only
True if nest.owasp.org has been submitted to hstspreload.org; if submission is
not verified set SECURE_HSTS_PRELOAD = False in base settings (symbol:
SECURE_HSTS_PRELOAD). Add environment-specific overrides for HSTS: for Local
settings set SECURE_HSTS_SECONDS = 0 (symbol: SECURE_HSTS_SECONDS) to disable
HSTS during tunneled HTTPS; for Staging settings set SECURE_HSTS_SECONDS = 0 and
explicitly set SECURE_HSTS_PRELOAD = False so nest.owasp.dev is never preloaded;
ensure Test/E2E/Fuzz keep their SECURE_HSTS_SECONDS = 0 overrides as already
present.
---
Nitpick comments:
In `@backend/settings/base.py`:
- Line 245: Remove the unused constant SELF_CONSTANT from settings/base.py by
deleting the line defining SELF_CONSTANT = "'self'"; search the codebase for any
references to SELF_CONSTANT to confirm it's safe to remove and run tests/lint to
ensure no regressions.
ℹ️ Review info
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
backend/settings/base.pyfrontend/next.config.ts
🚧 Files skipped from review as they are similar to previous changes (1)
- frontend/next.config.ts
77be1ee to
b3eb5cb
Compare
|
@cubic-dev-ai review |
@saichethana28 I have started the AI code review. It will take a few minutes to complete. |
|
|
@coderabbitai resume |
✅ Actions performedReviews resumed. |
|
Summary of the fix: I’ve migrated the security headers directly into the Django and Next.js configs. I figured doing it at the app level is better than infra/Terraform because it makes the security portable and keeps us from having to mess with CloudFront every time we move things around. A couple of things I focused on:
I'm keeping an eye on the CI/CD pipeline now, but the logic is solid and follows the ZAP requirements. Ready for a review whenever you're free @arkid15r! |



Proposed change
Resolves #4090
Following the security vulnerabilities identified by the ZAP scan, this PR implements several essential security headers across both the Next.js frontend and the Django backend to harden the application against common attack vectors.
Key changes include:
X-Frame-Options,X-Content-Type-Options,Strict-Transport-Security, andPermissions-Policyvianext.config.ts.base.py(including HSTS and frame options) to ensure defense-in-depth.These headers mitigate risks related to clickjacking, MIME-type sniffing, and insecure connections, bringing the project closer to full ZAP scan compliance.
Note: I encountered a timeout failure in
CreateModule.test.tsxduring local testing. After investigation, this appears to be an existing flaky test/environment timeout issue and is unrelated to these configuration-based security changes.Checklist
make check-testlocally: all warnings addressed, tests passed