← Stack-gidsen

Vercel

Beveiliging bij het deployen naar Vercel

Vercel deployt met een git push, en elk gemak verbergt een beveiligingsbeslissing: omgevingsvariabelen, bereikbare preview-deployments, source maps en headers. Scan je deployment en bevestig het.

Typische risico's bij Vercel

Verkeerd gebruikte publieke variabelen

Variabelen met een publiek voorvoegsel worden in de bundle gebakken. Bewaar daar alleen wat je gerust mag laten zien; privésleutels gaan zonder voorvoegsel, alleen server-side.

Publieke preview-deployments

Elke branch genereert een preview-URL die bereikbaar is voor iedereen die hem kent, vaak gekoppeld aan echte data of sleutels. Behandel ze niet als privé.

Source maps en headers

Vercel serveert HTTPS maar voegt geen defensieve headers toe. En als je source maps publiceert, reconstrueert iedereen je code. Beide stel je in het project in.

"Vercel-beveiliging" valt uiteen in twee helften die je beter gescheiden houdt. De eerste is wat Vercel voor je beheert en wat het je in het dashboard laat configureren: deploymentbescherming, variabelen per omgeving, firewall, teamrollen. De tweede is wat Cursor, v0 of Bolt in je project schrijven en wat Vercel ongewijzigd deployt, met zijn publieke sleutels en onbeschermde routes. Deze gids legt het model van Vercel uit, loopt door wat de AI verkeerd doet bij het deployen daar, geeft je een kant-en-klare vercel.json, een reviewprompt en vier controles van buitenaf. De details van elke fout staan in beveiliging bij het deployen op Vercel.

Deel 1: hoe beveiliging werkt op Vercel

Wat Vercel zelf doet

TLS-certificaat automatisch uitgegeven en vernieuwd, redirect van HTTP naar HTTPS, serverless functies geïsoleerd tussen projecten, een wereldwijd netwerk met DDoS-mitigatie en een logboek van elke deployment met wie hem deed en vanaf welke commit. Niets hiervan hoef je te configureren. Het zet ook een header zodat zoekmachines previews niet indexeren.

Wat jouw configuratie is

  • Deployment Protection. Standaard zijn previews publiek voor iedereen met de URL. Onder Settings kun je een Vercel-account van het team eisen (gratis), een wachtwoord (betaalde plannen) of beperken op IP. Het is het eerste vinkje om te zetten.
  • Omgevingsvariabelen per omgeving. Elke variabele wordt toegewezen aan Production, Preview of Development. Productiesleutels horen niet in Preview te bestaan, en gevoelige markeer je als Sensitive zodat ze niet meer uit het dashboard te lezen zijn.
  • Firewall. Vercel Firewall brengt beheerde regels, een challenge-modus tegen bots en eigen rate-limitregels per IP of per route. Ze worden ingeschakeld vanuit het dashboard zonder code aan te raken en zijn het antwoord op "iemand verbruikt mijn OpenAI-quotum".
  • Git en deployments. Elke push naar elke branch deployt. Bescherm de productiebranch op GitHub, controleer welke accounts toegang hebben tot het project en dwing tweestapsverificatie af in het team.
  • Tokens en diensten. CLI-tokens, tokens van Vercel Blob of van de geïntegreerde databases zijn servergeheimen. Een Vercel-token met teambereik deployt wat het wil in al je projecten.

Wat van het framework afhangt, niet van Vercel

Welke variabelen de browser bereiken (NEXT_PUBLIC_, VITE_, NUXT_PUBLIC_), of source maps gepubliceerd worden en welke headers worden verstuurd, bepalen je framework en je configuratie, niet het platform. Vercel voert alleen de build uit. Daarom kunnen twee apps op Vercel een A en een F scoren op headers.

Deel 2: wat de AI verkeerd doet bij het deployen op Vercel

  • Geheime sleutels met het publieke voorvoegsel omdat de component ze "nodig had". Ze reizen in de bundle naar elke bezoeker. Zoek naar sk_live, service_role of AKIA in je chunks.
  • Gedeployde testroutes. /api/debug, /api/seed of /api/admin, aangemaakt om te testen en zonder authenticatie naar productie gepusht.
  • Cron zonder secret. Vercel roept je cronroute aan met een Authorization-header die je CRON_SECRET draagt; als de handler die niet controleert, start iedereen de taak.
  • Functies zonder limieten. Een endpoint dat een model aanroept of e-mails verstuurt zonder plafond per gebruiker en zonder firewallregel.
  • Bestanden in public/. Een gekopieerde .env, een backup.json, een config.yml. Alles in die map is publiek.
  • CORS met wildcard en credentials op de API-routes, omdat "het zo werkte vanaf localhost".
  • Geen vercel.json. Geen beveiligingsheaders en geen redirect van het .vercel.app-domein naar je eigen domein, dat dubbel in Google belandt.

Een kant-en-klare vercel.json

Beveiligingsheaders voor alle routes en een redirect van het Vercel-subdomein naar je domein. Vervang de twee namen en, als je Next.js gebruikt, kun je de headers in plaats daarvan in next.config zetten:

{
  "headers": [
    {
      "source": "/(.*)",
      "headers": [
        { "key": "Strict-Transport-Security", "value": "max-age=63072000; includeSubDomains; preload" },
        { "key": "X-Content-Type-Options", "value": "nosniff" },
        { "key": "X-Frame-Options", "value": "DENY" },
        { "key": "Referrer-Policy", "value": "strict-origin-when-cross-origin" },
        { "key": "Permissions-Policy", "value": "camera=(), microphone=(), geolocation=()" }
      ]
    }
  ],
  "redirects": [
    {
      "source": "/(.*)",
      "has": [{ "type": "host", "value": "mijn-project.vercel.app" }],
      "destination": "https://jouwdomein.com/$1",
      "permanent": true
    }
  ]
}

De Content-Security-Policy gaat apart omdat die van je scripts afhangt; begin in report-only-modus zoals uitgelegd in HTTP-beveiligingsheaders.

Een reviewprompt vóór het deployen

Beoordeel de beveiliging van dit op Vercel gedeployde project en verander nog niets. Antwoord met een lijst:
1. Variabelen met een publiek voorvoegsel (NEXT_PUBLIC_, VITE_, NUXT_PUBLIC_) die geheime sleutels bevatten.
2. API-routes zonder sessiecontrole, test- of debugroutes, en cronroutes die CRON_SECRET niet verifiëren.
3. Endpoints die betaalde diensten aanroepen zonder limiet per gebruiker.
4. Bestanden in public/ die niet publiek horen te zijn.
5. API-routes met Access-Control-Allow-Origin: * en credentials.
6. Of er een vercel.json of next.config met beveiligingsheaders bestaat en of source maps in productie zijn uitgeschakeld.
Stel voor elk punt de exacte wijziging voor en wacht op mijn bevestiging.

Controleer het resultaat van buitenaf

curl -sI https://jouwdomein.com | grep -iE "strict-transport|x-frame|x-content-type|content-security"
curl -sI https://mijn-project.vercel.app | grep -iE "^HTTP|^location"
curl -sI https://mijn-project-git-main-team.vercel.app | grep -iE "^HTTP"
for p in .env .env.local config.json backup.zip api/debug api/seed; do printf "%-14s " "$p"; curl -s -o /dev/null -w "%{http_code}\n" "https://jouwdomein.com/$p"; done

Verwacht: headers aanwezig, een 301 naar je domein op de .vercel.app-URL, een 401 op de preview-URL als de bescherming aan staat, en 404 op elke route in de lijst. Scanaris voert deze controles en zo'n veertig andere uit in 30 seconden: het detecteert dat de app op Vercel staat en met welk framework, zoekt geheimen in de bundle, controleert source maps, headers, CSP, cookies, CORS, TLS en blootgestelde bestanden, en geeft je voor elke fout een fix prompt om in Cursor, v0 of Bolt te plakken. Is je app Next.js, dan legt de Next.js-gids uit welke code op de server draait en wat de browser bereikt.

Veelgestelde vragen

Zijn de previews van Vercel privé?

Niet standaard: iedereen met de URL opent ze, ook al worden ze niet geïndexeerd. Schakel Vercel Authentication in onder Deployment Protection; het is beschikbaar in het gratis plan.

Beschermt Vercel mijn API-routes?

Nee. Een API-route is een publieke URL; de sessie controleer jij in de code. De firewall kan verzoeken beperken en bots afremmen, maar beslist niet wie geautoriseerd is.

Heb ik vercel.json nodig als ik Next.js gebruik?

Voor de headers niet: next.config heeft de functie headers(). Voor de redirect van het .vercel.app-domein naar het jouwe kun je een van beide gebruiken. Belangrijk is dat hij in een van de twee bestaat.

Gerelateerde checks

Doorstaat je Vercel-app deze checks?

Scan hem gratis en krijg een fixprompt voor elk probleem dat we vinden.

Mijn site gratis scannen