You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Harden the portfolio app's security posture by implementing OWASP-recommended HTTP security headers, defining and documenting a Content Security Policy (CSP), and establishing environment variable documentation with security annotations. This stage extends the threat model to cover deployment and runtime misconfiguration surfaces and formalizes a dependency audit policy for proactive vulnerability management.
Objectives
Add security headers to all HTTP responses (X-Frame-Options, X-Content-Type-Options, X-XSS-Protection, Referrer-Policy, Permissions-Policy, Content-Security-Policy)
Define and document CSP policy with clear rationale and trade-off analysis
Expand .env.example with security-related environment variables and annotations
Validate that no hardcoded secrets or sensitive configuration exist in codebase
Enable automated dependency vulnerability scanning and audit policy
Default fallback: only allow resources from the same origin. Restrictive by default, exceptions added per-directive.
script-src
'self' 'unsafe-inline' https://cdn.vercel-*
Allows same-origin scripts, inline scripts (needed for Next.js), and Vercel Analytics CDN. Trade-off:unsafe-inline reduces security but is necessary for Next.js inline script execution.
style-src
'self' 'unsafe-inline'
Allows same-origin stylesheets and inline styles. Trade-off:unsafe-inline required for Tailwind CSS and Next.js styling.
img-src
'self' https: data:
Allows same-origin images, HTTPS external images (CDNs), and data URIs (base64-encoded images).
font-src
'self'
Allows same-origin fonts only. If external font CDNs needed, add them explicitly (e.g., https://fonts.googleapis.com).
connect-src
'self' https://vitals.vercel-analytics.com
Allows fetch/WebSocket/XMLHttpRequest to same-origin and Vercel Analytics telemetry endpoint.
CSP Trade-offs Documented:
unsafe-inline for scripts and styles: Reduces XSS protection but is necessary for Next.js. Consider in future:
Using script hashes or nonces for inline scripts (requires build-time integration)
Migrating to CSS-in-JS with dynamic class names (reduces inline styles need)
Vercel Analytics exception: Required for telemetry; consider removing if analytics becomes optional.
data: for images: Allows embedded images but could theoretically smuggle data. Considered acceptable risk for this app.
Testing CSP:
# View CSP header in responses
curl -I https://portfolio.example.com/
# Browser DevTools Console will warn about CSP violations# Example: If inline script blocked, you'll see:# "Refused to execute inline script because it violates the following CSP directive: ..."
Environment Variable Security Contract
Variables to document in .env.example:
# Application URL (public-safe; no secrets)NEXT_PUBLIC_SITE_URL=http://localhost:3000# Documentation Base URL (public-safe)NEXT_PUBLIC_DOCS_BASE_URL=https://portfolio-docs.example.com/docs/# GitHub URLs (public-safe)NEXT_PUBLIC_GITHUB_URL=https://github.com/bryce-seefieldtNEXT_PUBLIC_DOCS_GITHUB_URL=https://github.com/bryce-seefieldt/portfolio-docs# Environment Name (production/staging/preview/development)VERCEL_ENV=development# Build-time variables (not exposed to browser)NEXT_PUBLIC_ANALYTICS_ID=# Optional: analytics service ID if added# Security: Never add API keys, database credentials, or private URLs here# All variables prefixed with NEXT_PUBLIC_ are exposed to the browser and visible to clients.
Security Validation Rules:
No variable contains API keys, tokens, passwords, or private URLs
All public variables are documented with their purpose and security implications
Environment variable names follow NEXT_PUBLIC_* convention for client-exposed config
.env.example is committed; actual secrets are in Vercel dashboard only
All existing tests pass (pnpm quality, pnpm test:e2e)
PR created with title: feat: Stage 4.4 - Security posture deepening
Related Documentation
Security configuration guide (new or reference document)
OWASP Top 10 and OWASP Secure Headers guidelines (external reference)
Threat Model v2 (being created in parallel docs issue)
Dependency Audit Policy runbook (being created in parallel docs issue)
Environment variable security contract (in .env.example)
Notes & Considerations
CSP unsafe-inline trade-off: This is a documented security compromise necessary for Next.js. Future iterations could explore nonces or script hashing if external scripts are added.
Analytics dependency: CSP includes exceptions for Vercel Analytics. If analytics is disabled, simplify CSP by removing those directives.
Build-time validation: Consider adding build-time checks to validate .env.example format and that no secrets are committed.
Monitoring: The health check endpoint (GET /api/health) can be extended in future to report security status (e.g., CSP violations, failed dependency audits).
Post-incident: If security incident occurs, runbooks should reference this documentation and CSP configuration for root cause analysis.
Type: Feature / Enhancement / Security Hardening
Phase: Phase 4 — Enterprise-Grade Platform Maturity
Stage: 4.4
Linked Issue: Stage 4.4: Security Posture Deepening — Docs (#66)
Duration Estimate: 4–6 hours
Assignee: Bryce Seefieldt
Overview
Harden the portfolio app's security posture by implementing OWASP-recommended HTTP security headers, defining and documenting a Content Security Policy (CSP), and establishing environment variable documentation with security annotations. This stage extends the threat model to cover deployment and runtime misconfiguration surfaces and formalizes a dependency audit policy for proactive vulnerability management.
Objectives
.env.examplewith security-related environment variables and annotationsScope
Files to Create
.env.example(expanded version) — Comprehensive environment variable template with security annotationsNEXT_PUBLIC_*variables for portfolio appdocs/40-security/security-configuration.md(NEW, may be referenced from next.config.ts or dossier) — Security configuration reference guideFiles to Update
next.config.ts— Add security headers configurationheaders()async function returning array of header configurationspackage.json— Dependency audit configurationpnpm auditis documented as part of CI/CD processpnpm audit --audit-level moderateor similarsrc/lib/config.ts— Security-related configuration helpers (if needed).env.example(existing) — Add security-related variablesREADME.md— Add security sectionDesign & Architecture
System Overview
Security hardening layers:
graph TD Browser["User Browser"] App["Portfolio App<br/>next.config.ts<br/>Security Headers"] Vercel["Vercel Deployment<br/>HTTPS Enforcement<br/>DDoS Protection"] Headers["HTTP Security Headers<br/>CSP, X-Frame-Options, etc."] Monitor["Vercel Logs<br/>Security Events"] Browser --> App App --> Vercel App --> Headers Headers --> MonitorOWASP Security Headers Configuration
Content Security Policy (CSP) Breakdown & Rationale
Full Policy:
Directive Explanation:
default-src'self'script-src'self' 'unsafe-inline' https://cdn.vercel-*unsafe-inlinereduces security but is necessary for Next.js inline script execution.style-src'self' 'unsafe-inline'unsafe-inlinerequired for Tailwind CSS and Next.js styling.img-src'self' https: data:font-src'self'https://fonts.googleapis.com).connect-src'self' https://vitals.vercel-analytics.comCSP Trade-offs Documented:
unsafe-inlinefor scripts and styles: Reduces XSS protection but is necessary for Next.js. Consider in future:Vercel Analytics exception: Required for telemetry; consider removing if analytics becomes optional.
data:for images: Allows embedded images but could theoretically smuggle data. Considered acceptable risk for this app.Testing CSP:
Environment Variable Security Contract
Variables to document in
.env.example:Security Validation Rules:
NEXT_PUBLIC_*convention for client-exposed configImplementation Tasks
Break the work into concrete, sequential phases.
Phase 1: Security Headers Configuration (1–2 hours)
Implement HTTP security headers in Next.js configuration.
Tasks
Add security headers to
next.config.tsheaders()async functionpnpm dev→ curl http://localhost:3000 and verify headers presentVerify CSP policy doesn't break existing functionality
pnpm devand load each route in browserDocument security headers rationale in code
Success Criteria for Phase 1
pnpm build && pnpm startPhase 2: Environment Variable Documentation (1–2 hours)
Document all environment variables with security annotations.
Tasks
Expand
.env.examplewith all variablesNEXT_PUBLIC_*variables used by the appAdd security validation rules to documentation
.env.localfor local developmentUpdate
src/lib/config.tsif neededCreate or update
docs/40-security/security-configuration.mdSuccess Criteria for Phase 2
.env.exampleis comprehensive and well-documentedpnpm secrets:scanpasses without false positivesPhase 3: Dependency Audit Policy Integration (1–2 hours)
Formalize and document dependency vulnerability management.
Tasks
Review and document Dependabot configuration
.github/dependabot.ymlexists and is configuredAdd
pnpm auditvalidationpnpm auditand document baseline (expected 0 vulnerabilities)--audit-levelcheck if using npm workspacesUpdate
README.mdwith security section.env.exampleand public-safe variablesUpdate package.json scripts if needed
pnpm auditlocallySuccess Criteria for Phase 3
pnpm auditruns clean (or baseline vulnerabilities documented)Testing Strategy
Security Header Validation
Manual header inspection
pnpm devand curl http://localhost:3000 with-Iflagpnpm build && pnpm startBrowser DevTools inspection
CSP functionality testing
E2E test validation
pnpm test:e2eto ensure Playwright tests still passEnvironment Variable Validation
No secrets in source code
pnpm secrets:scanand verify passes.env.examplefor any hardcoded sensitive valuesConfiguration loading
src/lib/config.tscorrectly exports all variables.env.localoverridesDependency Audit
Baseline audit
pnpm installandpnpm auditDependabot configuration
Test Commands
Success Criteria
.env.examplepnpm secrets:scanpasses)pnpm auditpasses with 0 critical/high vulnerabilities (or documented risk acceptance)pnpm quality,pnpm test:e2e)feat: Stage 4.4 - Security posture deepeningRelated Documentation
.env.example)Notes & Considerations
CSP
unsafe-inlinetrade-off: This is a documented security compromise necessary for Next.js. Future iterations could explore nonces or script hashing if external scripts are added.Analytics dependency: CSP includes exceptions for Vercel Analytics. If analytics is disabled, simplify CSP by removing those directives.
Build-time validation: Consider adding build-time checks to validate
.env.exampleformat and that no secrets are committed.Monitoring: The health check endpoint (
GET /api/health) can be extended in future to report security status (e.g., CSP violations, failed dependency audits).Post-incident: If security incident occurs, runbooks should reference this documentation and CSP configuration for root cause analysis.