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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions