[{"data":1,"prerenderedAt":294},["ShallowReactive",2],{"blog-guides/deno-deploy":3},{"id":4,"title":5,"body":6,"category":274,"date":275,"dateModified":275,"description":276,"draft":277,"extension":278,"faq":279,"featured":277,"headerVariant":280,"image":279,"keywords":281,"meta":282,"navigation":283,"ogDescription":284,"ogTitle":279,"path":285,"readTime":279,"schemaOrg":286,"schemaType":287,"seo":288,"sitemap":289,"stem":290,"tags":291,"twitterCard":292,"__hash__":293},"blog/blog/guides/deno-deploy.md","Deno Deploy Security Guide for Vibe Coders",{"type":7,"value":8,"toc":255},"minimark",[9,13,17,23,28,31,34,38,41,46,57,61,67,80,84,87,93,97,100,106,110,116,120,126,130,164,168,174,202,206,209,229,236],[10,11,5],"h1",{"id":12},"deno-deploy-security-guide-for-vibe-coders",[14,15,16],"p",{},"Published on January 23, 2026 - 10 min read",[18,19,20],"tldr",{},[14,21,22],{},"Deno Deploy provides a secure-by-default runtime with explicit permissions, but you still need to handle secrets and user data carefully. Store secrets in environment variables via the dashboard (not in code). Use Deno KV with proper key scoping to prevent data leaks between users. Validate all request input. Deno's permission model doesn't apply in Deploy (all permissions are granted), so security is entirely in your code.",[24,25,27],"h2",{"id":26},"why-deno-deploy-security-matters-for-vibe-coding","Why Deno Deploy Security Matters for Vibe Coding",[14,29,30],{},"Deno Deploy runs your TypeScript/JavaScript at the edge globally. While Deno is known for its security-first permission model, those permissions don't apply in Deploy. Your code has full network and environment access, making secure coding practices essential.",[14,32,33],{},"AI tools generating Deno code often assume the CLI permission model applies. In Deploy, you're responsible for all security validation.",[24,35,37],{"id":36},"environment-secrets","Environment Secrets",[14,39,40],{},"Store all sensitive configuration in environment variables through the Deno Deploy dashboard.",[42,43,45],"h3",{"id":44},"setting-secrets","Setting Secrets",[47,48,53],"pre",{"className":49,"code":51,"language":52},[50],"language-text","# Via deployctl CLI\ndeployctl env set API_KEY=sk-your-secret-key\ndeployctl env set DATABASE_URL=postgres://...\ndeployctl env set JWT_SECRET=your-jwt-secret\n\n# Or set in the Deno Deploy dashboard:\n# Project Settings > Environment Variables\n","text",[54,55,51],"code",{"__ignoreMap":56},"",[42,58,60],{"id":59},"accessing-secrets-in-code","Accessing Secrets in Code",[47,62,65],{"className":63,"code":64,"language":52},[50],"// Access environment variables\nconst apiKey = Deno.env.get(\"API_KEY\");\nconst databaseUrl = Deno.env.get(\"DATABASE_URL\");\n\nif (!apiKey) {\n  throw new Error(\"API_KEY environment variable not set\");\n}\n\n// Use in your handler\nDeno.serve(async (req) => {\n  // apiKey is available here\n  const response = await fetch(\"https://api.example.com\", {\n    headers: { Authorization: `Bearer ${apiKey}` },\n  });\n  return response;\n});\n",[54,66,64],{"__ignoreMap":56},[68,69,70,74],"warning-box",{},[42,71,73],{"id":72},"never-hardcode-secrets","Never Hardcode Secrets",[47,75,78],{"className":76,"code":77,"language":52},[50],"// DANGEROUS: Secrets in code\nconst API_KEY = \"sk-abc123\";  // Committed to git!\n\n// SAFE: Use environment variables\nconst API_KEY = Deno.env.get(\"API_KEY\");\n",[54,79,77],{"__ignoreMap":56},[24,81,83],{"id":82},"request-validation","Request Validation",[14,85,86],{},"Validate all incoming requests before processing:",[47,88,91],{"className":89,"code":90,"language":52},[50],"import { z } from \"https://deno.land/x/zod@v3.22.4/mod.ts\";\n\nconst CreateUserSchema = z.object({\n  email: z.string().email().max(255),\n  name: z.string().min(1).max(100),\n});\n\nDeno.serve(async (req) => {\n  const url = new URL(req.url);\n\n  if (url.pathname === \"/api/users\" && req.method === \"POST\") {\n    // Validate content type\n    const contentType = req.headers.get(\"content-type\");\n    if (!contentType?.includes(\"application/json\")) {\n      return new Response(\"Invalid content type\", { status: 415 });\n    }\n\n    // Parse and validate body\n    let body: unknown;\n    try {\n      body = await req.json();\n    } catch {\n      return new Response(\"Invalid JSON\", { status: 400 });\n    }\n\n    const result = CreateUserSchema.safeParse(body);\n    if (!result.success) {\n      return Response.json(\n        { error: \"Validation failed\", details: result.error.flatten() },\n        { status: 400 }\n      );\n    }\n\n    // Safe to use result.data\n    const { email, name } = result.data;\n\n    // Process the request...\n    return Response.json({ success: true });\n  }\n\n  return new Response(\"Not found\", { status: 404 });\n});\n",[54,92,90],{"__ignoreMap":56},[24,94,96],{"id":95},"deno-kv-security","Deno KV Security",[14,98,99],{},"Deno KV is a built-in key-value store. Secure it with proper key scoping:",[47,101,104],{"className":102,"code":103,"language":52},[50],"const kv = await Deno.openKv();\n\nDeno.serve(async (req) => {\n  const userId = await getUserId(req); // Your auth logic\n\n  // SAFE: User-scoped keys\n  const userPrefsKey = [\"users\", userId, \"preferences\"];\n  const prefs = await kv.get(userPrefsKey);\n\n  // SAFE: Setting user data\n  await kv.set([\"users\", userId, \"profile\"], {\n    name: \"User Name\",\n    updatedAt: Date.now(),\n  });\n\n  // DANGEROUS: User-controlled key\n  const key = new URL(req.url).searchParams.get(\"key\");\n  // const data = await kv.get([key]); // User could access any key!\n\n  // SAFE: Validate and scope\n  if (key && /^[a-z0-9-]+$/.test(key)) {\n    const scopedKey = [\"users\", userId, key];\n    const data = await kv.get(scopedKey);\n    return Response.json(data.value);\n  }\n\n  return Response.json(prefs.value);\n});\n",[54,105,103],{"__ignoreMap":56},[42,107,109],{"id":108},"kv-atomic-operations","KV Atomic Operations",[47,111,114],{"className":112,"code":113,"language":52},[50],"// Atomic operations for data integrity\nconst kv = await Deno.openKv();\n\nasync function transferCredits(fromUserId: string, toUserId: string, amount: number) {\n  const fromKey = [\"users\", fromUserId, \"credits\"];\n  const toKey = [\"users\", toUserId, \"credits\"];\n\n  // Get current values\n  const fromEntry = await kv.get\u003Cnumber>(fromKey);\n  const toEntry = await kv.get\u003Cnumber>(toKey);\n\n  const fromCredits = fromEntry.value ?? 0;\n  const toCredits = toEntry.value ?? 0;\n\n  if (fromCredits \u003C amount) {\n    throw new Error(\"Insufficient credits\");\n  }\n\n  // Atomic update with version checks\n  const result = await kv.atomic()\n    .check(fromEntry) // Fails if value changed\n    .check(toEntry)\n    .set(fromKey, fromCredits - amount)\n    .set(toKey, toCredits + amount)\n    .commit();\n\n  if (!result.ok) {\n    throw new Error(\"Transaction failed, please retry\");\n  }\n\n  return { success: true };\n}\n",[54,115,113],{"__ignoreMap":56},[24,117,119],{"id":118},"authentication-patterns","Authentication Patterns",[47,121,124],{"className":122,"code":123,"language":52},[50],"import { verify } from \"https://deno.land/x/djwt@v3.0.1/mod.ts\";\n\nconst JWT_SECRET = Deno.env.get(\"JWT_SECRET\");\n\nasync function getUser(req: Request) {\n  const authHeader = req.headers.get(\"authorization\");\n\n  if (!authHeader?.startsWith(\"Bearer \")) {\n    return null;\n  }\n\n  const token = authHeader.slice(7);\n\n  try {\n    const key = await crypto.subtle.importKey(\n      \"raw\",\n      new TextEncoder().encode(JWT_SECRET),\n      { name: \"HMAC\", hash: \"SHA-256\" },\n      false,\n      [\"verify\"]\n    );\n\n    const payload = await verify(token, key);\n    return payload;\n  } catch {\n    return null;\n  }\n}\n\nDeno.serve(async (req) => {\n  const user = await getUser(req);\n\n  if (!user) {\n    return new Response(\"Unauthorized\", { status: 401 });\n  }\n\n  // User is authenticated\n  return Response.json({ userId: user.sub });\n});\n",[54,125,123],{"__ignoreMap":56},[42,127,129],{"id":128},"deno-deploy-security-checklist","Deno Deploy Security Checklist",[131,132,133,137,140,143,146,149,152,155,158,161],"ul",{},[134,135,136],"li",{},"All secrets stored in environment variables",[134,138,139],{},"No hardcoded API keys or credentials in code",[134,141,142],{},"Request input validated with Zod or similar",[134,144,145],{},"Authentication checked on protected routes",[134,147,148],{},"Deno KV keys scoped to authenticated user",[134,150,151],{},"Atomic operations used for critical data updates",[134,153,154],{},"Error responses don't leak sensitive information",[134,156,157],{},"CORS configured appropriately",[134,159,160],{},"Rate limiting on sensitive endpoints",[134,162,163],{},"No eval() or dynamic code execution with user input",[24,165,167],{"id":166},"file-serving-security","File Serving Security",[47,169,172],{"className":170,"code":171,"language":52},[50],"Deno.serve(async (req) => {\n  const url = new URL(req.url);\n  let path = url.pathname;\n\n  // Prevent directory traversal\n  if (path.includes(\"..\") || path.includes(\"//\")) {\n    return new Response(\"Invalid path\", { status: 400 });\n  }\n\n  // Normalize path\n  path = path.replace(/^\\/+/, \"/\");\n\n  // Only serve from specific directory\n  const safePath = `/static${path}`;\n\n  // Check file exists and serve\n  try {\n    const file = await Deno.readFile(safePath);\n    return new Response(file);\n  } catch {\n    return new Response(\"Not found\", { status: 404 });\n  }\n});\n",[54,173,171],{"__ignoreMap":56},[175,176,177,184,190,196],"faq-section",{},[178,179,181],"faq-item",{"question":180},"Does Deno's permission model apply in Deploy?",[14,182,183],{},"No. In Deno Deploy, your code has full permissions. The --allow-net, --allow-env, etc. flags from the CLI don't apply. Security is entirely dependent on how you write your code.",[178,185,187],{"question":186},"Is Deno KV data encrypted?",[14,188,189],{},"Yes, Deno KV data is encrypted at rest. However, you should still scope keys properly to prevent users from accessing each other's data. For highly sensitive data, consider application-level encryption.",[178,191,193],{"question":192},"How do I handle different environments?",[14,194,195],{},"Create separate projects in Deno Deploy for development, staging, and production. Each project has its own environment variables. Never share secrets between environments.",[178,197,199],{"question":198},"Can I use npm packages securely?",[14,200,201],{},"Yes, Deno supports npm packages via npm: specifiers. However, audit your dependencies as you would in Node.js. Prefer well-maintained packages and pin versions to avoid supply chain attacks.",[24,203,205],{"id":204},"what-checkyourvibe-detects","What CheckYourVibe Detects",[14,207,208],{},"When scanning your Deno Deploy project, CheckYourVibe identifies:",[131,210,211,214,217,220,223,226],{},[134,212,213],{},"Hardcoded secrets and API keys",[134,215,216],{},"Missing request validation",[134,218,219],{},"Deno KV keys without user scoping",[134,221,222],{},"Path traversal vulnerabilities",[134,224,225],{},"Missing authentication on protected routes",[134,227,228],{},"Unsafe use of eval() or dynamic imports",[14,230,231,232,235],{},"Run ",[54,233,234],{},"npx checkyourvibe scan"," to catch these issues before they reach production.",[237,238,239,245,250],"related-articles",{},[240,241],"related-card",{"description":242,"href":243,"title":244},"Security guide for Claude Code users. Learn how to review AI-generated code, protect secrets, and deploy secure applicat","/blog/guides/claude-code","Claude Code Security Guide: Protecting AI-Generated Projects",[240,246],{"description":247,"href":248,"title":249},"Complete security guide for Clerk authentication. Learn to properly integrate Clerk, protect routes, verify sessions, an","/blog/guides/clerk","Clerk Security Guide: Authentication Done Right",[240,251],{"description":252,"href":253,"title":254},"Complete security guide for Cloudflare Pages. Learn to configure environment variables, secure Workers functions, and us","/blog/guides/cloudflare-pages","Cloudflare Pages Security Guide: Edge Deployment Best Practices",{"title":56,"searchDepth":256,"depth":256,"links":257},2,[258,259,265,266,269,272,273],{"id":26,"depth":256,"text":27},{"id":36,"depth":256,"text":37,"children":260},[261,263,264],{"id":44,"depth":262,"text":45},3,{"id":59,"depth":262,"text":60},{"id":72,"depth":262,"text":73},{"id":82,"depth":256,"text":83},{"id":95,"depth":256,"text":96,"children":267},[268],{"id":108,"depth":262,"text":109},{"id":118,"depth":256,"text":119,"children":270},[271],{"id":128,"depth":262,"text":129},{"id":166,"depth":256,"text":167},{"id":204,"depth":256,"text":205},"guides","2026-01-21","Secure your Deno Deploy applications when vibe coding. Learn environment secrets, permission handling, KV security, and edge function best practices.",false,"md",null,"blue","Deno Deploy security, vibe coding Deno, Deno KV security, edge functions security, Deno permissions",{},true,"Secure your Deno Deploy applications with proper secrets management and permission handling.","/blog/guides/deno-deploy","[object Object]","TechArticle",{"title":5,"description":276},{"loc":285},"blog/guides/deno-deploy",[],"summary_large_image","FhOr8yRdD-0mU8X3y40RAPXu3Jv7Mh3afi3gkWMl0pk",1775843930132]