[{"data":1,"prerenderedAt":586},["ShallowReactive",2],{"guide-url-security-best-practices":3},{"id":4,"title":5,"body":6,"date":577,"description":578,"extension":579,"meta":580,"navigation":581,"path":582,"readingTime":262,"seo":583,"stem":584,"__hash__":585},"guides\u002Fguides\u002Furl-security-best-practices.md","URL Security Best Practices: Protect Links and User Data",{"type":7,"value":8,"toc":554},"minimark",[9,14,18,21,25,30,119,123,126,136,140,143,147,178,281,285,288,292,357,361,367,371,374,378,401,407,411,418,422,472,479,483,486,512,516,537,541,550],[10,11,13],"h2",{"id":12},"why-url-security-matters","Why URL Security Matters",[15,16,17],"p",{},"URLs are visible in browser history, server logs, referrer headers, and analytics tools. Any sensitive data placed in a URL is exposed to anyone who can see those records. Session tokens, passwords, and personal IDs routinely leak through careless URL construction.",[15,19,20],{},"Security through URL design is not optional. A single leaked token in a shared link can compromise an entire account.",[10,22,24],{"id":23},"never-put-secrets-in-the-url","Never Put Secrets in the URL",[26,27,29],"h3",{"id":28},"what-counts-as-a-secret","What Counts as a Secret",[31,32,33,49],"table",{},[34,35,36],"thead",{},[37,38,39,43,46],"tr",{},[40,41,42],"th",{},"Data Type",[40,44,45],{},"Example",[40,47,48],{},"Risk",[50,51,52,67,80,93,106],"tbody",{},[37,53,54,58,64],{},[55,56,57],"td",{},"Session tokens",[55,59,60],{},[61,62,63],"code",{},"?token=abc123",[55,65,66],{},"Browser history, referrer leak",[37,68,69,72,77],{},[55,70,71],{},"Passwords",[55,73,74],{},[61,75,76],{},"?pwd=hunter2",[55,78,79],{},"Visible in address bar",[37,81,82,85,90],{},[55,83,84],{},"API keys",[55,86,87],{},[61,88,89],{},"?key=sk_live_xxx",[55,91,92],{},"Logged by proxies and CDNs",[37,94,95,98,103],{},[55,96,97],{},"Personal IDs",[55,99,100],{},[61,101,102],{},"?ssn=123-45-6789",[55,104,105],{},"PII exposure, compliance violation",[37,107,108,111,116],{},[55,109,110],{},"Medical data",[55,112,113],{},[61,114,115],{},"?diagnosis=flu",[55,117,118],{},"HIPAA violation",[26,120,122],{"id":121},"where-to-put-them-instead","Where to Put Them Instead",[15,124,125],{},"Use request headers or request bodies. Headers travel alongside the URL but are not logged in browser history or sent in referrer headers. Bodies are invisible to URLs entirely.",[127,128,133],"pre",{"className":129,"code":131,"language":132},[130],"language-text","\u002F\u002F Bad — token in query string\nGET \u002Fapi\u002Fuser?token=abc123\n\n\u002F\u002F Good — token in Authorization header\nGET \u002Fapi\u002Fuser\nAuthorization: Bearer abc123\n","text",[61,134,131],{"__ignoreMap":135},"",[10,137,139],{"id":138},"prevent-open-redirect-vulnerabilities","Prevent Open Redirect Vulnerabilities",[15,141,142],{},"An open redirect occurs when your application takes a user-supplied URL and redirects to it without validation. Attackers use open redirects to trick users into visiting phishing sites that appear to come from your domain.",[26,144,146],{"id":145},"how-to-fix-it","How to Fix It",[148,149,150,158,172],"ol",{},[151,152,153,157],"li",{},[154,155,156],"strong",{},"Whitelist allowed redirect targets."," Only allow paths or domains you control.",[151,159,160,163,164,167,168,171],{},[154,161,162],{},"Use relative paths instead of full URLs."," Redirect to ",[61,165,166],{},"\u002Fdashboard"," rather than ",[61,169,170],{},"https:\u002F\u002Fevil.com",".",[151,173,174,177],{},[154,175,176],{},"Validate the destination."," Parse the URL and check that the hostname matches your domain.",[127,179,183],{"className":180,"code":181,"language":182,"meta":135,"style":135},"language-javascript shiki shiki-themes github-light github-dark","function safeRedirect(url) {\n  const parsed = new URL(url, window.location.origin)\n  if (parsed.hostname !== window.location.hostname) {\n    return '\u002F' \u002F\u002F fallback to home\n  }\n  return parsed.pathname\n}\n","javascript",[61,184,185,209,231,246,260,266,275],{"__ignoreMap":135},[186,187,190,194,198,202,206],"span",{"class":188,"line":189},"line",1,[186,191,193],{"class":192},"szBVR","function",[186,195,197],{"class":196},"sScJk"," safeRedirect",[186,199,201],{"class":200},"sVt8B","(",[186,203,205],{"class":204},"s4XuR","url",[186,207,208],{"class":200},") {\n",[186,210,212,215,219,222,225,228],{"class":188,"line":211},2,[186,213,214],{"class":192},"  const",[186,216,218],{"class":217},"sj4cs"," parsed",[186,220,221],{"class":192}," =",[186,223,224],{"class":192}," new",[186,226,227],{"class":196}," URL",[186,229,230],{"class":200},"(url, window.location.origin)\n",[186,232,234,237,240,243],{"class":188,"line":233},3,[186,235,236],{"class":192},"  if",[186,238,239],{"class":200}," (parsed.hostname ",[186,241,242],{"class":192},"!==",[186,244,245],{"class":200}," window.location.hostname) {\n",[186,247,249,252,256],{"class":188,"line":248},4,[186,250,251],{"class":192},"    return",[186,253,255],{"class":254},"sZZnC"," '\u002F'",[186,257,259],{"class":258},"sJ8bj"," \u002F\u002F fallback to home\n",[186,261,263],{"class":188,"line":262},5,[186,264,265],{"class":200},"  }\n",[186,267,269,272],{"class":188,"line":268},6,[186,270,271],{"class":192},"  return",[186,273,274],{"class":200}," parsed.pathname\n",[186,276,278],{"class":188,"line":277},7,[186,279,280],{"class":200},"}\n",[10,282,284],{"id":283},"validate-and-sanitize-url-input","Validate and Sanitize URL Input",[15,286,287],{},"Any URL component taken from user input — query parameters, path segments, fragments — must be validated before use.",[26,289,291],{"id":290},"common-validation-rules","Common Validation Rules",[31,293,294,307],{},[34,295,296],{},[37,297,298,301,304],{},[40,299,300],{},"Input",[40,302,303],{},"Check",[40,305,306],{},"Why",[50,308,309,320,335,346],{},[37,310,311,314,317],{},[55,312,313],{},"Redirect URL",[55,315,316],{},"Whitelist hostname",[55,318,319],{},"Prevent open redirect",[37,321,322,325,332],{},[55,323,324],{},"File path in URL",[55,326,327,328,331],{},"Reject ",[61,329,330],{},".."," segments",[55,333,334],{},"Prevent path traversal",[37,336,337,340,343],{},[55,338,339],{},"Query parameter",[55,341,342],{},"Length limit + charset",[55,344,345],{},"Prevent buffer overflow, injection",[37,347,348,351,354],{},[55,349,350],{},"URL-encoded data",[55,352,353],{},"Decode then validate",[55,355,356],{},"Prevent double-encoding attacks",[26,358,360],{"id":359},"path-traversal-example","Path Traversal Example",[127,362,365],{"className":363,"code":364,"language":132},[130],"\u002F\u002F Dangerous — user controls the path\nGET \u002Ffiles\u002F..\u002F..\u002F..\u002Fetc\u002Fpasswd\n\n\u002F\u002F Fix — resolve and verify the path stays within the allowed directory\nconst resolved = path.resolve(baseDir, userInput)\nif (!resolved.startsWith(baseDir)) throw new Error('Invalid path')\n",[61,366,364],{"__ignoreMap":135},[10,368,370],{"id":369},"enforce-https-everywhere","Enforce HTTPS Everywhere",[15,372,373],{},"HTTP URLs transmit data in plaintext.任何人 on the network can read and modify the traffic. HTTPS encrypts the connection and lets the browser verify the server's identity.",[26,375,377],{"id":376},"steps-to-enforce-https","Steps to Enforce HTTPS",[379,380,381,384,391,398],"ul",{},[151,382,383],{},"Redirect all HTTP requests to HTTPS at the server level.",[151,385,386,387,390],{},"Set the ",[61,388,389],{},"Strict-Transport-Security"," header to tell browsers to always use HTTPS.",[151,392,393,394,397],{},"Use the ",[61,395,396],{},"Secure"," flag on cookies so they are never sent over HTTP.",[151,399,400],{},"Submit your domain to the HSTS preload list for browser-level enforcement.",[127,402,405],{"className":403,"code":404,"language":132},[130],"Strict-Transport-Security: max-age=31536000; includeSubDomains; preload\n",[61,406,404],{"__ignoreMap":135},[10,408,410],{"id":409},"be-careful-with-referrer-headers","Be Careful with Referrer Headers",[15,412,413,414,417],{},"When a user clicks a link from your site, the browser sends a ",[61,415,416],{},"Referer"," header to the destination. This header includes the full URL of the originating page — including any query parameters.",[26,419,421],{"id":420},"how-to-control-referrer-leakage","How to Control Referrer Leakage",[31,423,424,434],{},[34,425,426],{},[37,427,428,431],{},[40,429,430],{},"Method",[40,432,433],{},"What It Does",[50,435,436,446,461],{},[37,437,438,443],{},[55,439,440],{},[61,441,442],{},"\u003Cmeta name=\"referrer\" content=\"no-referrer\">",[55,444,445],{},"Sends no referrer for all links on the page",[37,447,448,458],{},[55,449,450,453,454,457],{},[61,451,452],{},"rel=\"noreferrer\""," on ",[61,455,456],{},"\u003Ca>"," tags",[55,459,460],{},"Blocks referrer for a specific link",[37,462,463,469],{},[55,464,465,468],{},[61,466,467],{},"Referrer-Policy: same-origin"," header",[55,470,471],{},"Sends full referrer only to same-origin requests",[15,473,474,475,478],{},"Use ",[61,476,477],{},"no-referrer"," on any page whose URLs contain session tokens or sensitive query parameters.",[10,480,482],{"id":481},"secure-url-shorteners-and-redirects","Secure URL Shorteners and Redirects",[15,484,485],{},"If you run a URL shortener or redirect service:",[379,487,488,494,500,506],{},[151,489,490,493],{},[154,491,492],{},"Rate-limit redirect creation"," to prevent abuse.",[151,495,496,499],{},[154,497,498],{},"Show an interstitial page"," for flagged destinations so users know they are leaving your site.",[151,501,502,505],{},[154,503,504],{},"Log all redirects"," for abuse review.",[151,507,508,511],{},[154,509,510],{},"Scan destination URLs"," against phishing and malware databases.",[10,513,515],{"id":514},"key-takeaways","Key Takeaways",[379,517,518,521,524,527,534],{},[151,519,520],{},"Never place session tokens, passwords, API keys, or PII in URLs — use headers or request bodies instead.",[151,522,523],{},"Validate all user-supplied URL components and whitelist redirect targets.",[151,525,526],{},"Enforce HTTPS with HSTS headers and the preload list.",[151,528,529,530,533],{},"Control referrer leakage with meta tags or the ",[61,531,532],{},"Referrer-Policy"," header.",[151,535,536],{},"Treat URL shorteners and redirect endpoints as high-risk surfaces that need rate limiting and logging.",[10,538,540],{"id":539},"try-it-yourself","Try It Yourself",[15,542,543,544,549],{},"Parse and inspect any URL for security issues with the ",[545,546,548],"a",{"href":547},"\u002Ftools\u002Furl-parser","URL Parser"," tool — check query parameters, hostname, and path segments at a glance.",[551,552,553],"style",{},"html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":135,"searchDepth":211,"depth":211,"links":555},[556,557,561,564,568,571,574,575,576],{"id":12,"depth":211,"text":13},{"id":23,"depth":211,"text":24,"children":558},[559,560],{"id":28,"depth":233,"text":29},{"id":121,"depth":233,"text":122},{"id":138,"depth":211,"text":139,"children":562},[563],{"id":145,"depth":233,"text":146},{"id":283,"depth":211,"text":284,"children":565},[566,567],{"id":290,"depth":233,"text":291},{"id":359,"depth":233,"text":360},{"id":369,"depth":211,"text":370,"children":569},[570],{"id":376,"depth":233,"text":377},{"id":409,"depth":211,"text":410,"children":572},[573],{"id":420,"depth":233,"text":421},{"id":481,"depth":211,"text":482},{"id":514,"depth":211,"text":515},{"id":539,"depth":211,"text":540},"2026-05-28","Learn how to secure URLs — avoid sensitive data leaks, validate inputs, prevent open redirects, and enforce HTTPS across your application.","md",{"immutable":581},true,"\u002Fguides\u002Furl-security-best-practices",{"title":5,"description":578},"guides\u002Furl-security-best-practices","nndnCtL7wHFCmZRodsHrWqh4XS3iwlljLEtzLWBKkVE",1780401326815]