[{"data":1,"prerenderedAt":345},["ShallowReactive",2],{"blog-guides/cloudflare-pages":3},{"id":4,"title":5,"body":6,"category":324,"date":325,"dateModified":326,"description":327,"draft":328,"extension":329,"faq":330,"featured":328,"headerVariant":331,"image":330,"keywords":330,"meta":332,"navigation":333,"ogDescription":334,"ogTitle":330,"path":335,"readTime":336,"schemaOrg":337,"schemaType":338,"seo":339,"sitemap":340,"stem":341,"tags":342,"twitterCard":343,"__hash__":344},"blog/blog/guides/cloudflare-pages.md","Cloudflare Pages Security Guide: Edge Deployment Best Practices",{"type":7,"value":8,"toc":306},"minimark",[9,16,21,24,59,63,68,71,86,95,99,108,112,116,125,129,138,142,145,154,158,161,175,184,188,191,205,214,218,223,226,229,232,235,238,241,244,247,275,294],[10,11,12],"tldr",{},[13,14,15],"p",{},"Cloudflare Pages runs at the edge with built-in DDoS protection and automatic SSL. Use environment variables for secrets (they're encrypted), secure Pages Functions with proper authentication, and leverage Cloudflare's WAF for additional protection. Preview deployments are public, so protect sensitive features.",[17,18,20],"h2",{"id":19},"cloudflares-security-advantage","Cloudflare's Security Advantage",[13,22,23],{},"Deploying on Cloudflare Pages gives you access to Cloudflare's security infrastructure:",[25,26,27,35,41,47,53],"ul",{},[28,29,30,34],"li",{},[31,32,33],"strong",{},"Global edge network:"," Content served from 300+ locations worldwide",[28,36,37,40],{},[31,38,39],{},"DDoS protection:"," Automatic mitigation at no extra cost",[28,42,43,46],{},[31,44,45],{},"Automatic SSL:"," Free TLS certificates for all domains",[28,48,49,52],{},[31,50,51],{},"WAF integration:"," Web Application Firewall (on paid plans)",[28,54,55,58],{},[31,56,57],{},"Bot management:"," Protection against automated attacks",[17,60,62],{"id":61},"environment-variables","Environment Variables",[64,65,67],"h3",{"id":66},"production-vs-preview-variables","Production vs Preview Variables",[13,69,70],{},"Cloudflare Pages lets you set different variables for production and preview:",[72,73,75],"code-block",{"label":74},"Environment variable scopes",[76,77,82],"pre",{"className":78,"code":80,"language":81},[79],"language-text","# Production only\nAPI_KEY=prod_key_xxxxx\n\n# Preview only\nAPI_KEY=test_key_xxxxx\n\n# Both environments\nNEXT_PUBLIC_SITE_URL=https://example.com\n","text",[83,84,80],"code",{"__ignoreMap":85},"",[87,88,89],"warning-box",{},[13,90,91,94],{},[31,92,93],{},"Use different secrets for preview and production."," Preview deployments are public, and if secrets are compromised, you want to limit the damage.",[64,96,98],{"id":97},"accessing-variables-in-functions","Accessing Variables in Functions",[72,100,102],{"label":101},"Pages Functions environment access",[76,103,106],{"className":104,"code":105,"language":81},[79],"// functions/api/data.js\nexport async function onRequest(context) {\n  // Access environment variables from context.env\n  const apiKey = context.env.API_KEY;\n  const dbUrl = context.env.DATABASE_URL;\n\n  // Use the secrets...\n  const response = await fetch('https://api.example.com/data', {\n    headers: { 'Authorization': `Bearer ${apiKey}` }\n  });\n\n  return new Response(JSON.stringify(await response.json()), {\n    headers: { 'Content-Type': 'application/json' }\n  });\n}\n",[83,107,105],{"__ignoreMap":85},[17,109,111],{"id":110},"pages-functions-security","Pages Functions Security",[64,113,115],{"id":114},"authentication-in-functions","Authentication in Functions",[72,117,119],{"label":118},"Protected function with auth check",[76,120,123],{"className":121,"code":122,"language":81},[79],"// functions/api/protected.js\nexport async function onRequest(context) {\n  const authHeader = context.request.headers.get('Authorization');\n\n  if (!authHeader || !authHeader.startsWith('Bearer ')) {\n    return new Response(JSON.stringify({ error: 'Unauthorized' }), {\n      status: 401,\n      headers: { 'Content-Type': 'application/json' }\n    });\n  }\n\n  const token = authHeader.substring(7);\n\n  try {\n    // Verify the token (example with JWT)\n    const payload = await verifyJWT(token, context.env.JWT_SECRET);\n\n    // Continue with the request\n    return new Response(JSON.stringify({ user: payload.sub }), {\n      headers: { 'Content-Type': 'application/json' }\n    });\n  } catch (error) {\n    return new Response(JSON.stringify({ error: 'Invalid token' }), {\n      status: 401,\n      headers: { 'Content-Type': 'application/json' }\n    });\n  }\n}\n",[83,124,122],{"__ignoreMap":85},[64,126,128],{"id":127},"input-validation","Input Validation",[72,130,132],{"label":131},"Validate request data",[76,133,136],{"className":134,"code":135,"language":81},[79],"// functions/api/submit.js\nexport async function onRequest(context) {\n  if (context.request.method !== 'POST') {\n    return new Response('Method not allowed', { status: 405 });\n  }\n\n  let body;\n  try {\n    body = await context.request.json();\n  } catch {\n    return new Response(JSON.stringify({ error: 'Invalid JSON' }), {\n      status: 400,\n      headers: { 'Content-Type': 'application/json' }\n    });\n  }\n\n  // Validate required fields\n  if (!body.email || typeof body.email !== 'string') {\n    return new Response(JSON.stringify({ error: 'Email required' }), {\n      status: 400,\n      headers: { 'Content-Type': 'application/json' }\n    });\n  }\n\n  // Validate email format\n  const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n  if (!emailRegex.test(body.email)) {\n    return new Response(JSON.stringify({ error: 'Invalid email' }), {\n      status: 400,\n      headers: { 'Content-Type': 'application/json' }\n    });\n  }\n\n  // Process valid input...\n}\n",[83,137,135],{"__ignoreMap":85},[17,139,141],{"id":140},"security-headers","Security Headers",[13,143,144],{},"Add security headers using a _headers file or Pages Functions:",[72,146,148],{"label":147},"_headers file",[76,149,152],{"className":150,"code":151,"language":81},[79],"/*\n  X-Frame-Options: DENY\n  X-Content-Type-Options: nosniff\n  X-XSS-Protection: 1; mode=block\n  Referrer-Policy: strict-origin-when-cross-origin\n  Permissions-Policy: camera=(), microphone=(), geolocation=()\n\n/api/*\n  Access-Control-Allow-Origin: https://yourdomain.com\n  Access-Control-Allow-Methods: GET, POST, OPTIONS\n",[83,153,151],{"__ignoreMap":85},[17,155,157],{"id":156},"cloudflare-access-integration","Cloudflare Access Integration",[13,159,160],{},"For additional protection, use Cloudflare Access to require authentication:",[25,162,163,166,169,172],{},[28,164,165],{},"Protect preview deployments with login",[28,167,168],{},"Restrict access to specific email domains",[28,170,171],{},"Add MFA requirements",[28,173,174],{},"Integrate with identity providers (Google, Okta, etc.)",[176,177,178],"info-box",{},[13,179,180,183],{},[31,181,182],{},"Cloudflare Access"," sits in front of your application, so users must authenticate before even reaching your site. Great for internal tools or staging environments.",[17,185,187],{"id":186},"waf-configuration","WAF Configuration",[13,189,190],{},"On Cloudflare Pro and above, you can configure Web Application Firewall rules:",[25,192,193,196,199,202],{},[28,194,195],{},"Block SQL injection attempts",[28,197,198],{},"Prevent XSS attacks",[28,200,201],{},"Rate limit aggressive requests",[28,203,204],{},"Block known bad user agents",[72,206,208],{"label":207},"Example WAF rule (Dashboard or API)",[76,209,212],{"className":210,"code":211,"language":81},[79],"# Block requests with SQL injection patterns\nRule: (http.request.uri.query contains \"UNION SELECT\")\nAction: Block\n\n# Rate limit API endpoints\nRule: (http.request.uri.path matches \"^/api/\")\nRate Limit: 100 requests per minute per IP\n",[83,213,211],{"__ignoreMap":85},[17,215,217],{"id":216},"cloudflare-pages-security-checklist","Cloudflare Pages Security Checklist",[219,220,222],"h4",{"id":221},"before-going-to-production","Before Going to Production",[13,224,225],{},"All secrets in environment variables",[13,227,228],{},"Different secrets for preview vs production",[13,230,231],{},"Functions validate all input",[13,233,234],{},"Functions check authentication where needed",[13,236,237],{},"Security headers configured",[13,239,240],{},"CORS limited to your domain",[13,242,243],{},"Consider Cloudflare Access for sensitive paths",[13,245,246],{},"WAF rules reviewed (if available)",[248,249,250,257,263,269],"faq-section",{},[251,252,254],"faq-item",{"question":253},"Are my environment variables secure on Cloudflare Pages?",[13,255,256],{},"Yes, Cloudflare encrypts environment variables at rest. They're only accessible to your Pages Functions at runtime. They're not included in your static build output.",[251,258,260],{"question":259},"Can I protect preview deployments?",[13,261,262],{},"Preview deployments are public by default. Use Cloudflare Access to require authentication for preview URLs, or use different (non-sensitive) environment variables for previews.",[251,264,266],{"question":265},"How do Pages Functions compare to Workers?",[13,267,268],{},"Pages Functions are built on Workers technology. They run at the edge with the same security model. Pages Functions are just easier to set up for file-based routing within a Pages project.",[251,270,272],{"question":271},"Does Cloudflare see my traffic?",[13,273,274],{},"Cloudflare processes requests on your behalf. For end-to-end encryption of sensitive data, consider client-side encryption before transmission. Cloudflare has security certifications and doesn't access your data inappropriately.",[276,277,278,284,289],"related-articles",{},[279,280],"related-card",{"description":281,"href":282,"title":283},"Compare edge platforms","/blog/comparisons/vercel-vs-cloudflare","Vercel vs Cloudflare Pages",[279,285],{"description":286,"href":287,"title":288},"Platform security analysis","/blog/is-safe/cloudflare","Is Cloudflare Pages Safe?",[279,290],{"description":291,"href":292,"title":293},"Step-by-step guide","/blog/how-to/add-security-headers","Adding Security Headers",[295,296,299,303],"cta-box",{"href":297,"label":298},"/","Start Free Scan",[17,300,302],{"id":301},"deploying-to-cloudflare-pages","Deploying to Cloudflare Pages?",[13,304,305],{},"Scan your project for security issues before going live.",{"title":85,"searchDepth":307,"depth":307,"links":308},2,[309,310,315,319,320,321,322,323],{"id":19,"depth":307,"text":20},{"id":61,"depth":307,"text":62,"children":311},[312,314],{"id":66,"depth":313,"text":67},3,{"id":97,"depth":313,"text":98},{"id":110,"depth":307,"text":111,"children":316},[317,318],{"id":114,"depth":313,"text":115},{"id":127,"depth":313,"text":128},{"id":140,"depth":307,"text":141},{"id":156,"depth":307,"text":157},{"id":186,"depth":307,"text":187},{"id":216,"depth":307,"text":217},{"id":301,"depth":307,"text":302},"guides","2026-01-16","2026-02-11","Complete security guide for Cloudflare Pages. Learn to configure environment variables, secure Workers functions, and use Cloudflare's security features.",false,"md",null,"blue",{},true,"Secure your Cloudflare Pages deployments with proper configuration.","/blog/guides/cloudflare-pages","9 min read","[object Object]","Article",{"title":5,"description":327},{"loc":335},"blog/guides/cloudflare-pages",[],"summary_large_image","Emz4saZu_P49-NG_CwEdygf9X2qFjBO2DZYTA4iSxhc",1775843930277]