Skip to content

Security: veridatum-labs/earnproof-frontend

Security

SECURITY.md

Security Policy

EarnProof handles wallet authentication and privacy-sensitive proof workflows. Please report vulnerabilities privately before opening a public issue.

Reporting a Vulnerability

Email the maintainers at security@veridatum.dev with:

  • affected repository and version or commit;
  • vulnerability description;
  • reproduction steps;
  • expected impact;
  • suggested remediation, if known.

Do not include private keys, seed phrases, real salary data, or private payment records in reports.

Supported Scope

The current project targets Stellar testnet only. Mainnet deployments and production financial claims are out of scope until explicitly documented.

Browser security policy

The Next.js app ships an explicit Content Security Policy and related headers from config/security-headers.ts. Proxy refreshes the CSP with a per-request nonce so Next.js can attach that nonce to its own runtime scripts. 'unsafe-inline' is not allowed for scripts or style elements; it is only allowed by style-src-attr for reviewed inline style attributes emitted by Next/Image and width/progress UI.

Directive / header Default Why
default-src 'self' Deny unlisted fetches by default.
script-src 'self' 'nonce-…' 'strict-dynamic' Next.js runtime scripts are nonce-tagged. 'strict-dynamic' is not a host wildcard; it only trusts scripts loaded by an already-nonced script.
style-src / style-src-elem 'self' 'nonce-…' Tailwind/App Router CSS plus nonce-tagged font fallback styles. No 'unsafe-inline' for style elements.
style-src-attr 'unsafe-inline' Narrow allowance for reviewed style attributes generated by Next/Image and dynamic progress-width UI.
connect-src app origin, API origin, Stellar Horizon Wallet sessions talk to the EarnProof API. Freighter itself is an extension and does not need an extra host. Horizon is listed for documented testnet network calls.
frame-src / frame-ancestors / X-Frame-Options 'none' / DENY Proof and QR pages must not be framed.
object-src 'none' Block plugins.
img-src 'self' data: blob: Logo, QR camera frames, and generated QR images.
Referrer-Policy strict-origin-when-cross-origin Avoid leaking proof IDs in referrers.
Permissions-Policy camera=(self); mic/geo/payment/usb disabled QR scanning on /verify/scan is the only camera use.
Strict-Transport-Security set when NEXT_PUBLIC_APP_URL is https: Local HTTP must keep working.

Required origins

Production (VERCEL_ENV=production) fails to boot when NEXT_PUBLIC_APP_URL, NEXT_PUBLIC_API_URL, NEXT_PUBLIC_STELLAR_NETWORK, NEXT_PUBLIC_STELLAR_NETWORK_PASSPHRASE, or NEXT_PUBLIC_STELLAR_HORIZON_URL are missing or invalid. Preview deployments use Vercel's generated preview URL plus the documented testnet defaults when project environment variables are not configured.

Local development and CI next build (no Vercel env) use the defaults in .env.example. Set EARNPROOF_REQUIRE_SECURITY_ORIGINS=true to force the fail-closed check.

External links

Untrusted URLs are never written into href. ExternalLink and toSafeExternalHref allow only configured HTTPS origins (help centre, optional explorer) and always set rel="noopener noreferrer". javascript:, data:, file:, and blob: schemes are rejected.

Nonce justification

Next.js emits small inline bootstrap scripts. A per-request base64 nonce is generated in proxy.ts, applied to Content-Security-Policy, and forwarded on the request CSP header so the framework can tag those scripts. That is the reason a nonce source appears in script-src, style-src, and style-src-elem. Do not add 'unsafe-inline' or * to script or style element directives without a new, documented justification.

There aren't any published security advisories