{"id":993,"date":"2026-08-24T17:02:59","date_gmt":"2026-08-24T17:02:59","guid":{"rendered":"https:\/\/www.osto.one\/resources\/?p=993"},"modified":"2026-08-24T17:02:59","modified_gmt":"2026-08-24T17:02:59","slug":"do-you-need-a-waf","status":"publish","type":"post","link":"https:\/\/www.osto.one\/resources\/guides\/do-you-need-a-waf\/","title":{"rendered":"Do You Need a WAF If You Already Use AWS or Cloudflare?"},"content":{"rendered":"\n<style>\n.og{\n  --navy:#1c267a; --navy-2:#2e3a9e; --navy-3:#141c5c;\n  --indigo:#4657e5; --peri:#97a2ff;\n  --ink:#060818; --ink-2:#373a51; --ink-3:#6b6d80;\n  --page:#f3f4fc; --bg-2:#e6e8f7; --paper:#ffffff; --line:#d9dcf1;\n  --t1:#eaecfd; --t2:#e6e8f7; --t3:#f3f4fc; --t4:#dddff4; --t5:#f0f1fb;\n  font-family:'Inter',-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;\n  font-size:17px; line-height:1.75; color:var(--ink); max-width:820px; margin:0 auto;\n}\n.og p{margin:0 0 20px}\n.og a{color:var(--navy-2); text-decoration:underline; text-underline-offset:2px}\n.og .dek{font-size:19px; line-height:1.6; margin:0 0 18px}\n.og .pills{display:flex; flex-wrap:wrap; gap:8px; margin:0 0 28px; padding:0; list-style:none}\n.og .pills li{font-size:12.5px; font-weight:600; letter-spacing:.02em; padding:5px 13px;\n  border-radius:999px; background:var(--t1); color:var(--navy)}\n.og .shortans{border-radius:14px; padding:26px 30px; margin:0 0 26px;\n  background:linear-gradient(135deg,#eaecfd 0%,#e6e8f7 100%)}\n.og .shortans h4{margin:0 0 10px; font-size:12.5px; letter-spacing:.11em; text-transform:uppercase;\n  font-weight:700; color:var(--navy)}\n.og .shortans p{margin:0; font-size:18px; line-height:1.65; font-weight:500}\n.og h2{font-size:27px; line-height:1.3; font-weight:700; color:var(--navy);\n  margin:54px 0 14px; padding-bottom:10px; letter-spacing:-.015em; position:relative}\n.og h2::after{content:\"\"; position:absolute; left:0; bottom:0; width:56px; height:3px; border-radius:2px}\n.og h2.s1::after{background:var(--navy)}\n.og h2.s2::after{background:var(--navy-2)}\n.og h2.s3::after{background:var(--indigo)}\n.og h2.s4::after{background:var(--peri)}\n.og h2.s5::after{background:var(--navy-3)}\n.og h2 + .sub{color:var(--ink-2); font-size:16px; margin:0 0 22px}\n.og h3{font-size:19px; font-weight:650; color:var(--navy-2); margin:32px 0 10px}\n.og .toc{border:1px solid var(--line); border-radius:14px; padding:22px 26px; margin:0 0 44px; background:var(--page)}\n.og .toc h4{margin:0 0 12px; font-size:12.5px; letter-spacing:.11em; text-transform:uppercase; font-weight:700; color:var(--navy)}\n.og .toc ol{margin:0; padding:0; list-style:none; counter-reset:t}\n.og .toc li{counter-increment:t; padding:9px 0 9px 34px; border-bottom:1px solid var(--line);\n  font-size:16px; line-height:1.5; position:relative}\n.og .toc li:last-child{border-bottom:none; padding-bottom:0}\n.og .toc li::before{content:counter(t,decimal-leading-zero); position:absolute; left:0; top:11px;\n  font-size:12px; font-weight:700; color:var(--indigo)}\n.og .toc a{color:var(--navy); font-weight:600; text-decoration:none}\n.og .toc a:hover{text-decoration:underline}\n.og .scroll{overflow-x:auto; -webkit-overflow-scrolling:touch; margin:26px 0 30px;\n  border:1px solid var(--line); border-radius:14px; background:var(--paper)}\n.og .scroll svg{display:block; min-width:660px; width:100%; height:auto}\n.og .cap{font-size:13.5px; color:var(--ink-2); text-align:center; margin:-18px 0 30px}\n.og .trio{display:grid; grid-template-columns:repeat(3,1fr); gap:12px; margin:26px 0 30px}\n.og .duo{display:grid; grid-template-columns:repeat(2,1fr); gap:12px; margin:26px 0 30px}\n.og .cd{border-radius:12px; padding:20px 22px}\n.og .cd.a{background:var(--t1)} .og .cd.b{background:var(--t2)} .og .cd.c{background:var(--t3)}\n.og .cd.d{background:var(--t4)} .og .cd.e{background:var(--t5)}\n.og .cd .code{display:block; font-size:11.5px; font-weight:700; letter-spacing:.07em;\n  text-transform:uppercase; color:var(--indigo); margin-bottom:7px}\n.og .cd h5{margin:0 0 7px; font-size:16.5px; font-weight:650; color:var(--navy); line-height:1.35}\n.og .cd p{margin:0; font-size:15px; line-height:1.6}\n.og .note{border:1px solid var(--navy); border-radius:12px; padding:20px 24px; margin:28px 0; background:var(--paper)}\n.og .note p{margin:0; font-size:16.5px; line-height:1.65}\n.og .note strong{color:var(--navy)}\n.og table{width:100%; border-collapse:separate; border-spacing:0; margin:26px 0 32px; font-size:15.5px;\n  border:1px solid var(--line); border-radius:12px; overflow:hidden}\n.og th{background:var(--navy); color:#fff; text-align:left; padding:14px 16px; font-weight:700;\n  font-size:13px; line-height:1.4; letter-spacing:.055em; text-transform:uppercase}\n.og td{border:0; border-top:1px solid var(--line); padding:13px 16px; vertical-align:top; line-height:1.6}\n.og tbody tr:first-child td{border-top:0}\n.og tbody tr:nth-child(even){background:var(--t3)}\n.og tbody td:first-child{font-weight:600; color:var(--navy)}\n.og tbody tr:nth-child(even){background:var(--page)}\n.og .steps{margin:26px 0 30px; padding:0; list-style:none; counter-reset:s}\n.og .steps li{counter-increment:s; position:relative; padding:14px 18px 14px 56px; margin-bottom:8px;\n  border-radius:11px; background:var(--page); font-size:16px; line-height:1.55}\n.og .steps li::before{content:counter(s); position:absolute; left:16px; top:14px; width:26px; height:26px;\n  border-radius:50%; background:var(--navy); color:#fff; font-size:13px; font-weight:700;\n  display:flex; align-items:center; justify-content:center}\n.og .steps span{display:block; font-size:14px; color:var(--ink-2); margin-top:3px}\n.og details{border:1px solid var(--line); border-radius:11px; padding:15px 20px; margin-bottom:9px; background:var(--paper)}\n.og details[open]{border-color:var(--peri)}\n.og summary{font-weight:650; color:var(--navy); cursor:pointer; font-size:16.5px; line-height:1.5}\n.og details p{margin:12px 0 0; font-size:16px; line-height:1.7}\n.og .cta{border-radius:16px; padding:38px 34px; margin:52px 0 30px; text-align:center;\n  background:linear-gradient(135deg,#141c5c 0%,#4657e5 100%)}\n.og .cta h3{color:#fff; margin:0 0 10px; font-size:25px; line-height:1.3}\n.og .cta p{color:#d5d8f5; margin:0 0 24px; font-size:16.5px; line-height:1.6}\n.og .cta .btns{display:flex; gap:12px; justify-content:center; flex-wrap:wrap}\n.og .cta a{display:inline-block; padding:14px 30px; border-radius:9px; font-weight:650; font-size:16px; text-decoration:none}\n.og .cta a.p{background:#ffffff}\n.og .cta a.p span{color:#1c267a !important}\n.og .cta a.s{border:1px solid rgba(255,255,255,.6)}\n.og .cta a.s span{color:#ffffff !important}\n.og .foot{border-top:1px solid var(--line); padding-top:20px; margin-top:42px; font-size:14.5px;\n  color:var(--ink-2); line-height:1.7}\n@media(max-width:680px){\n  .og{font-size:16px}\n  .og h2{font-size:22px} .og .dek{font-size:17px} .og .shortans p{font-size:16.5px}\n  .og .trio,.og .duo{grid-template-columns:1fr}\n  .og .shortans{padding:20px 22px} .og .toc{padding:18px 20px} .og .cta{padding:28px 20px}\n  .og table{font-size:14px} .og th,.og td{padding:11px 12px}\n}\n<\/style>\n\n<div class=\"og\">\n<p class=\"dek\">You already have one. The real question is whether it knows anything about your application, and whether it is still switched on.<\/p>\n\n<ul class=\"pills\"><li>WAF<\/li><li>Application security<\/li><li>API protection<\/li><\/ul>\n\n<div class=\"shortans\">\n  <h4>The short answer<\/h4>\n  <p>Cloudflare and AWS give you edge protection that handles volumetric attacks and known signatures well. Neither knows your endpoints, your parameters or what a normal request looks like for your application. Attacks that are well-formed and application-specific pass straight through, and a large share of deployed WAFs sit in monitoring mode after the first false positive.<\/p>\n<\/div>\n\n<div class=\"toc\">\n  <h4>On this page<\/h4>\n  <ol>\n    <li><a href=\"#have\">What you already have<\/a><\/li>\n    <li><a href=\"#through\">What gets through anyway<\/a><\/li>\n    <li><a href=\"#monitoring\">The monitoring mode problem<\/a><\/li>\n    <li><a href=\"#models\">Negative and positive security models<\/a><\/li>\n    <li><a href=\"#shadow\">Shadow APIs<\/a><\/li>\n    <li><a href=\"#decide\">How to decide<\/a><\/li>\n  <\/ol>\n<\/div>\n\n<h2 class=\"s1\" id=\"have\">What you already have<\/h2>\n\n<p>If you are behind Cloudflare or using AWS WAF with managed rules, you have real protection. Volumetric denial of service is absorbed. Known bad IP ranges are filtered. Generic injection patterns matching published signatures get caught. For a lot of automated background noise, this is sufficient.<\/p>\n\n<div class=\"scroll\">\n<svg viewBox=\"0 0 780 376\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" role=\"img\" aria-label=\"A request passing through internet, CDN, managed rules and the application, with four attack classes that arrive untouched\">\n<text x=\"16\" y=\"26\" font-family=\"Inter,-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif\" font-size=\"14.5\" font-weight=\"700\" fill=\"#1c267a\">One request, four places it could be stopped<\/text>\n<rect x=\"16\" y=\"44\" width=\"176\" height=\"96\" rx=\"12\" fill=\"#f0f1fb\"\/>\n<text x=\"104\" y=\"72\" text-anchor=\"middle\" font-family=\"Inter,-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif\" font-size=\"14\" font-weight=\"700\" fill=\"#1c267a\">Internet<\/text>\n<text x=\"104\" y=\"96\" text-anchor=\"middle\" font-family=\"Inter,-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif\" font-size=\"12\" fill=\"#373a51\">the request arrives<\/text>\n<path d=\"M194 92 L198 92\" stroke=\"#4657e5\" stroke-width=\"2\" fill=\"none\"\/>\n<path d=\"M196 87 L204 92 L196 97 Z\" fill=\"#4657e5\"\/>\n<rect x=\"206\" y=\"44\" width=\"176\" height=\"96\" rx=\"12\" fill=\"#e6e8f7\"\/>\n<text x=\"295\" y=\"72\" text-anchor=\"middle\" font-family=\"Inter,-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif\" font-size=\"14\" font-weight=\"700\" fill=\"#1c267a\">CDN \/ edge<\/text>\n<text x=\"295\" y=\"96\" text-anchor=\"middle\" font-family=\"Inter,-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif\" font-size=\"12\" fill=\"#373a51\">volumetric floods,<\/text>\n<text x=\"295\" y=\"114\" text-anchor=\"middle\" font-family=\"Inter,-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif\" font-size=\"12\" fill=\"#373a51\">known bad IPs<\/text>\n<path d=\"M385 92 L389 92\" stroke=\"#4657e5\" stroke-width=\"2\" fill=\"none\"\/>\n<path d=\"M387 87 L395 92 L387 97 Z\" fill=\"#4657e5\"\/>\n<rect x=\"397\" y=\"44\" width=\"176\" height=\"96\" rx=\"12\" fill=\"#e6e8f7\"\/>\n<text x=\"485\" y=\"72\" text-anchor=\"middle\" font-family=\"Inter,-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif\" font-size=\"14\" font-weight=\"700\" fill=\"#1c267a\">Managed rules<\/text>\n<text x=\"485\" y=\"96\" text-anchor=\"middle\" font-family=\"Inter,-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif\" font-size=\"12\" fill=\"#373a51\">known signatures,<\/text>\n<text x=\"485\" y=\"114\" text-anchor=\"middle\" font-family=\"Inter,-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif\" font-size=\"12\" fill=\"#373a51\">generic patterns<\/text>\n<path d=\"M576 92 L580 92\" stroke=\"#4657e5\" stroke-width=\"2\" fill=\"none\"\/>\n<path d=\"M578 87 L586 92 L578 97 Z\" fill=\"#4657e5\"\/>\n<rect x=\"588\" y=\"44\" width=\"176\" height=\"96\" rx=\"12\" fill=\"#dddff4\"\/>\n<text x=\"676\" y=\"72\" text-anchor=\"middle\" font-family=\"Inter,-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif\" font-size=\"14\" font-weight=\"700\" fill=\"#1c267a\">Your app<\/text>\n<text x=\"676\" y=\"96\" text-anchor=\"middle\" font-family=\"Inter,-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif\" font-size=\"12\" fill=\"#373a51\">business logic,<\/text>\n<text x=\"676\" y=\"114\" text-anchor=\"middle\" font-family=\"Inter,-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif\" font-size=\"12\" fill=\"#373a51\">auth, data access<\/text>\n<rect x=\"16\" y=\"166\" width=\"748\" height=\"178\" rx=\"12\" fill=\"#f3f4fc\"\/>\n<path d=\"M16 178 a12 12 0 0 1 12 -12 h724 a12 12 0 0 1 12 12 v26 h-748 Z\" fill=\"#2e3a9e\"\/>\n<text x=\"390\" y=\"191\" text-anchor=\"middle\" font-family=\"Inter,-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif\" font-size=\"14.5\" font-weight=\"700\" fill=\"#ffffff\">What reaches your application untouched<\/text>\n<rect x=\"40\" y=\"224\" width=\"17\" height=\"17\" rx=\"5\" fill=\"#ffffff\" stroke=\"#97a2ff\" stroke-width=\"1.5\"\/>\n<path d=\"M45.6 229.6 l5.8 5.8 M51.4 229.6 l-5.8 5.8\" stroke=\"#4657e5\" stroke-width=\"2\" fill=\"none\" stroke-linecap=\"round\"\/>\n<text x=\"68\" y=\"236\" font-family=\"Inter,-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif\" font-size=\"13.5\" fill=\"#060818\">Requests to API endpoints nobody documented<\/text>\n<rect x=\"40\" y=\"253\" width=\"17\" height=\"17\" rx=\"5\" fill=\"#ffffff\" stroke=\"#97a2ff\" stroke-width=\"1.5\"\/>\n<path d=\"M45.6 258.6 l5.8 5.8 M51.4 258.6 l-5.8 5.8\" stroke=\"#4657e5\" stroke-width=\"2\" fill=\"none\" stroke-linecap=\"round\"\/>\n<text x=\"68\" y=\"265\" font-family=\"Inter,-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif\" font-size=\"13.5\" fill=\"#060818\">Valid-looking calls carrying manipulated parameters<\/text>\n<rect x=\"40\" y=\"282\" width=\"17\" height=\"17\" rx=\"5\" fill=\"#ffffff\" stroke=\"#97a2ff\" stroke-width=\"1.5\"\/>\n<path d=\"M45.6 287.6 l5.8 5.8 M51.4 287.6 l-5.8 5.8\" stroke=\"#4657e5\" stroke-width=\"2\" fill=\"none\" stroke-linecap=\"round\"\/>\n<text x=\"68\" y=\"294\" font-family=\"Inter,-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif\" font-size=\"13.5\" fill=\"#060818\">Credential stuffing paced to resemble real logins<\/text>\n<rect x=\"40\" y=\"311\" width=\"17\" height=\"17\" rx=\"5\" fill=\"#ffffff\" stroke=\"#97a2ff\" stroke-width=\"1.5\"\/>\n<path d=\"M45.6 316.6 l5.8 5.8 M51.4 316.6 l-5.8 5.8\" stroke=\"#4657e5\" stroke-width=\"2\" fill=\"none\" stroke-linecap=\"round\"\/>\n<text x=\"68\" y=\"323\" font-family=\"Inter,-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif\" font-size=\"13.5\" fill=\"#060818\">Logic abuse where every single request is well-formed<\/text>\n<text x=\"390\" y=\"368\" text-anchor=\"middle\" font-family=\"Inter,-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif\" font-size=\"12.5\" fill=\"#373a51\">Every layer above is useful. None of them knows what your application expects.<\/text>\n<\/svg>\n<\/div>\n\n<h2 class=\"s2\" id=\"through\">What gets through anyway<\/h2>\n\n<p>Managed rulesets are built to be safe across every customer using them, which means they are necessarily generic. They cannot be tuned to an application they know nothing about.<\/p>\n\n<p>So the traffic that passes is the traffic that looks legitimate. A request to an endpoint your inventory does not list. A valid API call with a manipulated identifier that returns another tenant&#8217;s data. Credential stuffing paced to resemble ordinary logins. Business logic abuse where every individual request is perfectly well-formed and the sequence is the attack.<\/p>\n\n<h2 class=\"s3\" id=\"monitoring\">The monitoring mode problem<\/h2>\n\n<p>This is the most common failure in practice, and it has nothing to do with product quality.<\/p>\n\n<ol class=\"steps\">\n  <li>The WAF is deployed in blocking mode<span>Reasonable defaults, managed rules enabled<\/span><\/li>\n  <li>A rule blocks something legitimate<span>Usually a large customer, usually at an awkward moment<\/span><\/li>\n  <li>Somebody switches to monitoring to restore service<span>Correct call under pressure<\/span><\/li>\n  <li>Tuning gets scheduled<span>And then deprioritised behind shipping<\/span><\/li>\n  <li>It logs attacks indefinitely and blocks none<span>The dashboard looks busy and healthy<\/span><\/li>\n<\/ol>\n\n<div class=\"note\">\n  <p><strong>Worth checking today.<\/strong> Open your WAF console and confirm whether rules are set to block or to count. Plenty of teams discover the answer changed during an incident eighteen months ago and never changed back.<\/p>\n<\/div>\n\n<p>Treating this as a discipline failure misses the point. False positives are a design consequence of blocking by generic signature. Fix the model and the pressure to disable it largely goes away.<\/p>\n\n<h2 class=\"s4\" id=\"models\">Negative and positive security models<\/h2>\n\n<div class=\"scroll\">\n<svg viewBox=\"0 0 780 262\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" role=\"img\" aria-label=\"Negative security model blocking known bad patterns compared with a positive model allowing only learned good traffic\">\n<rect x=\"16\" y=\"14\" width=\"364\" height=\"210\" rx=\"12\" fill=\"#f3f4fc\"\/>\n<path d=\"M16.0 26 a12 12 0 0 1 12 -12 h340 a12 12 0 0 1 12 12 v40 h-364.0 Z\" fill=\"#2e3a9e\"\/>\n<text x=\"198\" y=\"40\" text-anchor=\"middle\" font-family=\"Inter,-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif\" font-size=\"14.5\" font-weight=\"700\" fill=\"#ffffff\">Negative model<\/text>\n<text x=\"198\" y=\"58\" text-anchor=\"middle\" font-family=\"Inter,-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif\" font-size=\"12\" fill=\"#c9cdf2\">block what looks bad<\/text>\n<rect x=\"400\" y=\"14\" width=\"364\" height=\"210\" rx=\"12\" fill=\"#f3f4fc\"\/>\n<path d=\"M400.0 26 a12 12 0 0 1 12 -12 h340 a12 12 0 0 1 12 12 v40 h-364.0 Z\" fill=\"#1c267a\"\/>\n<text x=\"582\" y=\"40\" text-anchor=\"middle\" font-family=\"Inter,-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif\" font-size=\"14.5\" font-weight=\"700\" fill=\"#ffffff\">Positive model<\/text>\n<text x=\"582\" y=\"58\" text-anchor=\"middle\" font-family=\"Inter,-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif\" font-size=\"12\" fill=\"#c9cdf2\">allow what is known good<\/text>\n<rect x=\"34\" y=\"86\" width=\"17\" height=\"17\" rx=\"5\" fill=\"#ffffff\" stroke=\"#97a2ff\" stroke-width=\"1.5\"\/>\n<path d=\"M39.6 91.6 l5.8 5.8 M45.4 91.6 l-5.8 5.8\" stroke=\"#4657e5\" stroke-width=\"2\" fill=\"none\" stroke-linecap=\"round\"\/>\n<text x=\"62\" y=\"98\" font-family=\"Inter,-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif\" font-size=\"12.5\" fill=\"#060818\">Needs a rule per attack<\/text>\n<rect x=\"34\" y=\"112\" width=\"17\" height=\"17\" rx=\"5\" fill=\"#ffffff\" stroke=\"#97a2ff\" stroke-width=\"1.5\"\/>\n<path d=\"M39.6 117.6 l5.8 5.8 M45.4 117.6 l-5.8 5.8\" stroke=\"#4657e5\" stroke-width=\"2\" fill=\"none\" stroke-linecap=\"round\"\/>\n<text x=\"62\" y=\"124\" font-family=\"Inter,-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif\" font-size=\"12.5\" fill=\"#060818\">Novel attacks pass by default<\/text>\n<rect x=\"34\" y=\"138\" width=\"17\" height=\"17\" rx=\"5\" fill=\"#ffffff\" stroke=\"#97a2ff\" stroke-width=\"1.5\"\/>\n<path d=\"M39.6 143.6 l5.8 5.8 M45.4 143.6 l-5.8 5.8\" stroke=\"#4657e5\" stroke-width=\"2\" fill=\"none\" stroke-linecap=\"round\"\/>\n<text x=\"62\" y=\"150\" font-family=\"Inter,-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif\" font-size=\"12.5\" fill=\"#060818\">Rule list grows forever<\/text>\n<rect x=\"34\" y=\"164\" width=\"17\" height=\"17\" rx=\"5\" fill=\"#ffffff\" stroke=\"#97a2ff\" stroke-width=\"1.5\"\/>\n<path d=\"M39.6 169.6 l5.8 5.8 M45.4 169.6 l-5.8 5.8\" stroke=\"#4657e5\" stroke-width=\"2\" fill=\"none\" stroke-linecap=\"round\"\/>\n<text x=\"62\" y=\"176\" font-family=\"Inter,-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif\" font-size=\"12.5\" fill=\"#060818\">Tuning never finishes<\/text>\n<rect x=\"418\" y=\"86\" width=\"17\" height=\"17\" rx=\"5\" fill=\"#2e3a9e\"\/>\n<path d=\"M422.5 94.8 l2.7 2.8 l5.3 -5.6\" stroke=\"#ffffff\" stroke-width=\"2\" fill=\"none\" stroke-linecap=\"round\" stroke-linejoin=\"round\"\/>\n<text x=\"446\" y=\"98\" font-family=\"Inter,-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif\" font-size=\"12.5\" fill=\"#060818\">Learns your real traffic<\/text>\n<rect x=\"418\" y=\"112\" width=\"17\" height=\"17\" rx=\"5\" fill=\"#2e3a9e\"\/>\n<path d=\"M422.5 120.8 l2.7 2.8 l5.3 -5.6\" stroke=\"#ffffff\" stroke-width=\"2\" fill=\"none\" stroke-linecap=\"round\" stroke-linejoin=\"round\"\/>\n<text x=\"446\" y=\"124\" font-family=\"Inter,-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif\" font-size=\"12.5\" fill=\"#060818\">Unknown patterns refused<\/text>\n<rect x=\"418\" y=\"138\" width=\"17\" height=\"17\" rx=\"5\" fill=\"#2e3a9e\"\/>\n<path d=\"M422.5 146.8 l2.7 2.8 l5.3 -5.6\" stroke=\"#ffffff\" stroke-width=\"2\" fill=\"none\" stroke-linecap=\"round\" stroke-linejoin=\"round\"\/>\n<text x=\"446\" y=\"150\" font-family=\"Inter,-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif\" font-size=\"12.5\" fill=\"#060818\">Adapts as the app changes<\/text>\n<rect x=\"418\" y=\"164\" width=\"17\" height=\"17\" rx=\"5\" fill=\"#2e3a9e\"\/>\n<path d=\"M422.5 172.8 l2.7 2.8 l5.3 -5.6\" stroke=\"#ffffff\" stroke-width=\"2\" fill=\"none\" stroke-linecap=\"round\" stroke-linejoin=\"round\"\/>\n<text x=\"446\" y=\"176\" font-family=\"Inter,-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif\" font-size=\"12.5\" fill=\"#060818\">Fewer false positives<\/text>\n<text x=\"390\" y=\"250\" text-anchor=\"middle\" font-family=\"Inter,-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif\" font-size=\"12.5\" fill=\"#373a51\">A negative model is permanently one rule behind. A positive model inverts the default.<\/text>\n<\/svg>\n<\/div>\n\n<p>A negative model needs a rule for every attack, which means it is permanently behind. A positive model learns what your traffic actually looks like and treats deviation as suspicious, which inverts the default and closes the window on novel attacks.<\/p>\n\n<h2 class=\"s5\" id=\"shadow\">Shadow APIs<\/h2>\n\n<p>You cannot protect endpoints you do not know exist. Undocumented endpoints accumulate through ordinary work: a service ships faster than the inventory updates, a deprecated version stays reachable, an internal endpoint becomes externally routable during a migration.<\/p>\n\n<p>Any protection scoped from documentation inherits the gaps in that documentation. Discovery has to come from observed traffic rather than from a spreadsheet.<\/p>\n\n<h2 class=\"s1\" id=\"decide\">How to decide<\/h2>\n\n<table>\n  <thead><tr><th>Your situation<\/th><th>Reasonable position<\/th><\/tr><\/thead>\n  <tbody>\n    <tr><td>Static marketing site, no user data<\/td><td>Edge protection is fine<\/td><\/tr>\n    <tr><td>SaaS application handling customer data<\/td><td>Application-aware protection is warranted<\/td><\/tr>\n    <tr><td>Public APIs, or partner integrations<\/td><td>Discovery and per-endpoint policy matter<\/td><\/tr>\n    <tr><td>Multi-tenant architecture<\/td><td>Object-level authorisation abuse is your main risk<\/td><\/tr>\n    <tr><td>Pursuing SOC 2 or ISO 27001<\/td><td>You need a demonstrable protection control, in blocking mode<\/td><\/tr>\n  <\/tbody>\n<\/table>\n\n<h2 class=\"s2\">How Osto does it<\/h2>\n\n<p>Osto&#8217;s WAAP runs as a reverse proxy in front of your application. It discovers applications and API endpoints automatically from real traffic rather than from a list you maintain, then builds a positive security policy from observed behaviour. It covers the OWASP Top 10, DDoS and bot traffic, and the self-configuring policy is what keeps false positives low enough that blocking mode survives contact with production.<\/p>\n\n<p>It reports into the same platform as cloud posture, endpoint control and code security, so a web-layer signal can be correlated with what is happening elsewhere instead of sitting in an isolated console.<\/p>\n\n<div class=\"cta\">\n  <h3>Find out what is reaching your application<\/h3>\n  <p>A free assessment maps your internet-facing endpoints, including the ones missing from your inventory, and shows what current protection is actually blocking.<\/p>\n  <div class=\"btns\">\n    <a class=\"p\" href=\"https:\/\/www.osto.one\/contact\"><span>Get a free security assessment<\/span><\/a>\n    <a class=\"s\" href=\"https:\/\/www.osto.one\/book-demo\"><span>Book a platform walkthrough<\/span><\/a>\n  <\/div>\n<\/div>\n\n<h2 class=\"s3\">Frequently asked questions<\/h2>\n\n<details>\n  <summary>Do I need a WAF if I use Cloudflare or AWS?<\/summary>\n  <p>You already have edge protection, which handles volumetric attacks and known-signature traffic well. What those default layers do not have is knowledge of your application: which endpoints exist, what parameters they accept, and what a legitimate request looks like. That gap is what a dedicated application-aware WAF addresses.<\/p>\n<\/details>\n<details>\n  <summary>What is the difference between a CDN and a WAF?<\/summary>\n  <p>A CDN caches and distributes content and absorbs volumetric traffic. A WAF inspects request content against rules to decide whether a request should reach your application. Many CDNs offer WAF functionality as an add-on, usually with managed generic rulesets rather than policies derived from your traffic.<\/p>\n<\/details>\n<details>\n  <summary>Why do WAFs get put into monitoring mode and left there?<\/summary>\n  <p>False positives. A rule blocks legitimate traffic, a customer complains, and the fastest fix is switching to monitoring. The intent is always to tune and re-enable, and it frequently does not happen. A WAF in monitoring mode logs attacks and stops none of them.<\/p>\n<\/details>\n<details>\n  <summary>What is a positive security model?<\/summary>\n  <p>Instead of blocking traffic matching known-bad patterns, a positive model learns the shape of your legitimate traffic and permits only what matches. Novel attacks are refused because they do not match known-good behaviour, rather than being allowed because no signature existed for them yet.<\/p>\n<\/details>\n<details>\n  <summary>What are shadow APIs and why do they matter?<\/summary>\n  <p>Endpoints running in production that are missing from your inventory and documentation. They appear through fast shipping, deprecated versions left running, and internal endpoints that became reachable. Protection scoped to documented endpoints will not cover them, which is why automatic discovery matters.<\/p>\n<\/details>\n<details>\n  <summary>Does SOC 2 require a WAF?<\/summary>\n  <p>Not by name. SOC 2 requires controls addressing system protection and vulnerability management, and a WAF is one common way to demonstrate protection for internet-facing applications. Auditors look at whether the control objective is met rather than at a named product category.<\/p>\n<\/details>\n\n<div class=\"foot\">\n  <p><strong>Related reading:<\/strong> <a href=\"https:\/\/www.osto.one\/blog\/soc-2-controls-cc1-cc9\/\">SOC 2 controls CC1 to CC9<\/a> &middot; <a href=\"https:\/\/www.osto.one\/resources\/glossary\/vapt\/\">VAPT explained<\/a><\/p>\n  <p><strong>Accuracy note:<\/strong> Capabilities of third-party edge and CDN products change frequently. Verify current feature sets and rule behaviour with your provider. Current to August 2026.<\/p>\n<\/div>\n<\/div>\n\n<script type=\"application\/ld+json\">\n{\n \"@context\": \"https:\/\/schema.org\",\n \"@type\": \"FAQPage\",\n \"mainEntity\": [\n  {\n   \"@type\": \"Question\",\n   \"name\": \"Do I need a WAF if I use Cloudflare or AWS?\",\n   \"acceptedAnswer\": {\n    \"@type\": \"Answer\",\n    \"text\": \"You already have edge protection, which handles volumetric attacks and known-signature traffic well. What those default layers do not have is knowledge of your application: which endpoints exist, what parameters they accept, and what a legitimate request looks like. That gap is what a dedicated application-aware WAF addresses.\"\n   }\n  },\n  {\n   \"@type\": \"Question\",\n   \"name\": \"What is the difference between a CDN and a WAF?\",\n   \"acceptedAnswer\": {\n    \"@type\": \"Answer\",\n    \"text\": \"A CDN caches and distributes content and absorbs volumetric traffic. A WAF inspects request content against rules to decide whether a request should reach your application. Many CDNs offer WAF functionality as an add-on, usually with managed generic rulesets rather than policies derived from your traffic.\"\n   }\n  },\n  {\n   \"@type\": \"Question\",\n   \"name\": \"Why do WAFs get put into monitoring mode and left there?\",\n   \"acceptedAnswer\": {\n    \"@type\": \"Answer\",\n    \"text\": \"False positives. A rule blocks legitimate traffic, a customer complains, and the fastest fix is switching to monitoring. The intent is always to tune and re-enable, and it frequently does not happen. A WAF in monitoring mode logs attacks and stops none of them.\"\n   }\n  },\n  {\n   \"@type\": \"Question\",\n   \"name\": \"What is a positive security model?\",\n   \"acceptedAnswer\": {\n    \"@type\": \"Answer\",\n    \"text\": \"Instead of blocking traffic matching known-bad patterns, a positive model learns the shape of your legitimate traffic and permits only what matches. Novel attacks are refused because they do not match known-good behaviour, rather than being allowed because no signature existed for them yet.\"\n   }\n  },\n  {\n   \"@type\": \"Question\",\n   \"name\": \"What are shadow APIs and why do they matter?\",\n   \"acceptedAnswer\": {\n    \"@type\": \"Answer\",\n    \"text\": \"Endpoints running in production that are missing from your inventory and documentation. They appear through fast shipping, deprecated versions left running, and internal endpoints that became reachable. Protection scoped to documented endpoints will not cover them, which is why automatic discovery matters.\"\n   }\n  },\n  {\n   \"@type\": \"Question\",\n   \"name\": \"Does SOC 2 require a WAF?\",\n   \"acceptedAnswer\": {\n    \"@type\": \"Answer\",\n    \"text\": \"Not by name. SOC 2 requires controls addressing system protection and vulnerability management, and a WAF is one common way to demonstrate protection for internet-facing applications. Auditors look at whether the control objective is met rather than at a named product category.\"\n   }\n  }\n ]\n}\n<\/script>\n","protected":false},"excerpt":{"rendered":"<p>You already have one. The real question is whether it knows anything about your application, and whether it is still\u2026<\/p>\n","protected":false},"author":8,"featured_media":994,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[211],"tags":[445,133],"class_list":["post-993","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-guides","tag-do-you-need-a-waf","tag-waf"],"_links":{"self":[{"href":"https:\/\/www.osto.one\/resources\/wp-json\/wp\/v2\/posts\/993","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.osto.one\/resources\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.osto.one\/resources\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.osto.one\/resources\/wp-json\/wp\/v2\/users\/8"}],"replies":[{"embeddable":true,"href":"https:\/\/www.osto.one\/resources\/wp-json\/wp\/v2\/comments?post=993"}],"version-history":[{"count":1,"href":"https:\/\/www.osto.one\/resources\/wp-json\/wp\/v2\/posts\/993\/revisions"}],"predecessor-version":[{"id":995,"href":"https:\/\/www.osto.one\/resources\/wp-json\/wp\/v2\/posts\/993\/revisions\/995"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.osto.one\/resources\/wp-json\/wp\/v2\/media\/994"}],"wp:attachment":[{"href":"https:\/\/www.osto.one\/resources\/wp-json\/wp\/v2\/media?parent=993"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.osto.one\/resources\/wp-json\/wp\/v2\/categories?post=993"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.osto.one\/resources\/wp-json\/wp\/v2\/tags?post=993"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}