Skip to content

[nightshift] security-footgun: security audit findings #3

@Microck

Description

@Microck

Security Analysis: micr-dev/projects

Summary

Automated security audit of the Next.js 16 portfolio showcase application. The codebase is a static/client-side portfolio site with no authentication, no database, and no user-submitted data. The attack surface is minimal. Findings below are ordered by severity.


P3 — External image sources without explicit Next.js remotePatterns configuration

Files: next.config.ts, app/layout.tsx
Severity: P3 (Low)

The Next.js config does not define images.remotePatterns or images.domains. While the current codebase serves images from public/ (not via <Image> from next/image), if any component or future change uses <Image> with external URLs (e.g., the Spotify widget source at Microck.pythonanywhere.com), the images would fail or require allowlisting.

Recommendation: No action needed for the current code, but if next/image is adopted for external sources, add remotePatterns to next.config.ts.


P3 — External third-party dependency in profile README (Spotify widget)

File: README.md (rendered on github.com, not part of the Next.js app)
Severity: P3 (Low)

The GitHub profile README loads an image from Microck.pythonanywhere.com with theme-aware sources. If this third-party service is compromised, it could serve malicious content. This is a GitHub-rendered context (not the Next.js app), so the risk is limited to the profile page.

Recommendation: Monitor the third-party service. Consider self-hosting the widget if reliability is a concern.


P3 — No Content Security Policy (CSP) headers configured

File: next.config.ts
Severity: P3 (Low)

The application doesn't define any Content Security Policy headers. While the app is a static portfolio with minimal attack surface (no forms, no API routes, no auth), adding CSP headers would be defense-in-depth against XSS if any third-party script is added later.

Recommendation: Add CSP headers in next.config.ts via headers() function. Example:

'Content-Security-Policy': "default-src 'self'; script-src 'self' 'unsafe-eval' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob:;"

P3 — Hardcoded dark mode class without user preference detection

File: app/layout.tsx:55
Severity: P3 (Low)

The <html> tag has className="dark" hardcoded, forcing dark mode for all users. While not a security issue, it means the light mode CSS variables in globals.css are never used. No security impact.


No Critical or High Issues Found

The codebase has:

  • ✅ No user input handling or form submissions
  • ✅ No API routes or server-side data mutations
  • ✅ No authentication or session management
  • ✅ No database access
  • ✅ No use of dangerouslySetInnerHTML
  • ✅ No client-side secrets or API keys
  • ✅ Proper suppressHydrationWarning on html tag
  • ✅ Clean fs.readFile usage in repo-sections.ts — reads from a local file, not user input
  • typeof window checks before accessing browser APIs in portfolio-shell.tsx

Overall Assessment: The project has a minimal and well-managed attack surface. No P0 or P1 issues. The three P3 findings are defensive recommendations for future-proofing.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions