<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Bruce Hernandez</title>
    <description>The latest articles on DEV Community by Bruce Hernandez (@bruce_hernandez_e4218d514).</description>
    <link>https://dev.to/bruce_hernandez_e4218d514</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4198805%2Ffea80ad8-634b-4e4f-81d2-9f6b428ed105.jpg</url>
      <title>DEV Community: Bruce Hernandez</title>
      <link>https://dev.to/bruce_hernandez_e4218d514</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/bruce_hernandez_e4218d514"/>
    <language>en</language>
    <item>
      <title>A Failed Request Is Not Proof of Blocking: Test the Decision, Not Just the Error</title>
      <dc:creator>Bruce Hernandez</dc:creator>
      <pubDate>Wed, 21 Oct 2026 16:28:12 +0000</pubDate>
      <link>https://dev.to/bruce_hernandez_e4218d514/a-failed-request-is-not-proof-of-blocking-test-the-decision-not-just-the-error-1i2</link>
      <guid>https://dev.to/bruce_hernandez_e4218d514/a-failed-request-is-not-proof-of-blocking-test-the-decision-not-just-the-error-1i2</guid>
      <description>&lt;p&gt;Your negative test returns an error. The dashboard turns green. Everyone moves on.&lt;/p&gt;

&lt;p&gt;But did the security control deny the request—or did the service simply break?&lt;/p&gt;

&lt;p&gt;Here is a three-case exercise for separating a policy decision from an application failure. You can follow the short demonstration, then adapt the evidence pattern to a test environment you control.&lt;/p&gt;

&lt;h2&gt;
  
  
  The setup: three places to observe one request
&lt;/h2&gt;

&lt;p&gt;The demonstration uses three local HTTP services:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Test harness → application policy gateway → synthetic destination
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The dashboard is on loopback port 8765, the gateway on 8766, and the destination on 8767. Each test has a new correlation ID, carried across the instrumented services.&lt;/p&gt;

&lt;p&gt;This is an application-level policy lab. The destination remains directly reachable locally by design. It demonstrates how to collect evidence; it does not establish host isolation, packet filtering, or production protection.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=6jTM3egg_vA" rel="noopener noreferrer"&gt;Watch the 2-minute walkthrough&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Establish a working allowed case
&lt;/h2&gt;

&lt;p&gt;Send the allowed request through the gateway to &lt;code&gt;/public&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Look for all three observations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The client receives HTTP 200.&lt;/li&gt;
&lt;li&gt;The gateway records ALLOW and rule &lt;code&gt;LAB-ALLOW-READ&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The destination records that same correlation ID and path.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The matching destination event matters. A successful response from a different route, a cache, or a different request would not establish the path you intended to test.&lt;/p&gt;

&lt;p&gt;Record the route and relevant identity/context alongside the result. This small lab has no authentication model; an identity-based system needs that additional context.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Test the intended denial
&lt;/h2&gt;

&lt;p&gt;Send the request to &lt;code&gt;/admin&lt;/code&gt; through the same gateway.&lt;/p&gt;

&lt;p&gt;In this lab, expect HTTP 403, gateway decision DENY, and rule &lt;code&gt;LAB-DEFAULT-DENY&lt;/code&gt;. There should be no destination event for that correlation ID.&lt;/p&gt;

&lt;p&gt;Do not stop at “403 means secure.” HTTP 403 communicates a refusal to fulfill the request; it does not identify which component made the decision or prove your intended policy caused it. See &lt;a href="https://www.rfc-editor.org/rfc/rfc9110.html#section-15.5.4" rel="noopener noreferrer"&gt;HTTP Semantics, RFC 9110 §15.5.4&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The gateway's decision and named rule connect the observation to the control being tested. The destination observation provides corroboration within this instrumented lab.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Add the failure that should NOT count as a denial
&lt;/h2&gt;

&lt;p&gt;Send &lt;code&gt;/maintenance&lt;/code&gt; through the gateway.&lt;/p&gt;

&lt;p&gt;The client receives HTTP 503. That looks like another failed request—but the gateway records ALLOW, and the destination records receiving it. The synthetic destination deliberately returns the error.&lt;/p&gt;

&lt;p&gt;If your test only checks “response is not 200,” both the denial and the service failure can look like a pass. You have tested availability, without establishing the authorization decision.&lt;/p&gt;

&lt;p&gt;Compare the complete evidence:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Case&lt;/th&gt;
&lt;th&gt;Client status&lt;/th&gt;
&lt;th&gt;Gateway decision&lt;/th&gt;
&lt;th&gt;Matching destination event&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Allowed &lt;code&gt;/public&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;200&lt;/td&gt;
&lt;td&gt;ALLOW&lt;/td&gt;
&lt;td&gt;Present&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Denied &lt;code&gt;/admin&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;403&lt;/td&gt;
&lt;td&gt;DENY&lt;/td&gt;
&lt;td&gt;Absent in this lab&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Service error &lt;code&gt;/maintenance&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;503&lt;/td&gt;
&lt;td&gt;ALLOW&lt;/td&gt;
&lt;td&gt;Present&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;These exact expectations belong to this lab. Your application might intentionally use different responses; write its expected behavior before running the test.&lt;/p&gt;

&lt;h2&gt;
  
  
  Turn the exercise into a useful test record
&lt;/h2&gt;

&lt;p&gt;For each case, preserve:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Expected outcome, route, and relevant identity or request context.&lt;/li&gt;
&lt;li&gt;Timestamp and correlation/request ID.&lt;/li&gt;
&lt;li&gt;Actual client response.&lt;/li&gt;
&lt;li&gt;Enforcement-point decision and the rule or policy version responsible.&lt;/li&gt;
&lt;li&gt;Matching destination observation, including the scope and time window searched.&lt;/li&gt;
&lt;li&gt;Verdict, evidence location, and any unresolved limitation.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Use synthetic identifiers. Redact credentials, tokens, and personal data before sharing evidence.&lt;/p&gt;

&lt;p&gt;Missing logs alone are weak evidence in a real environment: collection gaps, delay, retention, or a mismatched identifier can also explain absence. Check that instrumentation works using the allowed case, and investigate contradictions rather than marking the control passed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try this with your own negative tests
&lt;/h2&gt;

&lt;p&gt;Pick one existing “access denied” test. Add an allowed case on the intended route and a controlled application-error case. Then ask: would the test fail if the policy allowed the request but the backend returned an error?&lt;/p&gt;

&lt;p&gt;If the answer is no, improve the assertion and evidence before trusting the green result.&lt;/p&gt;

&lt;h2&gt;
  
  
  Free checklist and further reading
&lt;/h2&gt;

&lt;p&gt;Use my &lt;a href="https://sites.google.com/view/bruce-l-hernandez-books/free-security-checklist?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=failed_request_tutorial" rel="noopener noreferrer"&gt;free Security Control Verification Checklist&lt;/a&gt; to organize expected behavior, tests, and evidence. No signup is required.&lt;/p&gt;

&lt;p&gt;For more structured reading, I am the author of both books below. These links open my author site, where you can choose the book’s Amazon button:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://sites.google.com/view/bruce-l-hernandez-books/home?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=failed_request_tutorial&amp;amp;utm_content=engineering_book" rel="noopener noreferrer"&gt;Cybersecurity Engineering in Practice&lt;/a&gt; — foundations and the broader engineering workflow.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://sites.google.com/view/bruce-l-hernandez-books/home?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=failed_request_tutorial&amp;amp;utm_content=controls_book" rel="noopener noreferrer"&gt;Security Controls in Practice: From Requirements to Working Enterprise Protection&lt;/a&gt; — implementing, verifying, troubleshooting, and operating security controls.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The exercise above stands on its own; the books are optional further reading.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Prepared with AI assistance using the existing local lab source and walkthrough. The lab uses synthetic data.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>security</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
