<?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: Nexus Verify</title>
    <description>The latest articles on DEV Community by Nexus Verify (@nexusverify).</description>
    <link>https://dev.to/nexusverify</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%2F4239443%2F84bad731-7199-40a1-845d-86ea53ad352f.png</url>
      <title>DEV Community: Nexus Verify</title>
      <link>https://dev.to/nexusverify</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/nexusverify"/>
    <language>en</language>
    <item>
      <title>The deletion cookie that forgot Secure — a teardown of 230 Java files in 46 seconds</title>
      <dc:creator>Nexus Verify</dc:creator>
      <pubDate>Wed, 11 Nov 2026 16:03:56 +0000</pubDate>
      <link>https://dev.to/nexusverify/the-deletion-cookie-that-forgot-secure-a-teardown-of-230-java-files-in-46-seconds-o47</link>
      <guid>https://dev.to/nexusverify/the-deletion-cookie-that-forgot-secure-a-teardown-of-230-java-files-in-46-seconds-o47</guid>
      <description>&lt;p&gt;Most security scans end with a long list and no clear answer to "so what do I fix first?"&lt;/p&gt;

&lt;p&gt;This teardown is from a real run — the sample scan we publish so builders can see exactly what a check looks like before they buy one. No client code was involved. The targets were two public Java codebases, scanned as-is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;MyBatis JPetStore-6&lt;/strong&gt; — a real online-store web app: 46 Java files, 7,628 lines&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Spark (perwendel/spark)&lt;/strong&gt; — a Java web framework: 184 Java files, 21,272 lines&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Total: &lt;strong&gt;230 files, 28,900 lines, about 46 seconds of instrument time.&lt;/strong&gt; The instrument was Semgrep 1.140.0 with a frozen set of OWASP-category rules for Java — SQL injection, XSS, command injection, path traversal, weak crypto, weak randomness, insecure cookies, and others. It reads Java source only; anything living in XML mappers or config is outside its sight, and we say so in the report.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Findings issued: 16. Every one was read in context and dispositioned.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What actually broke
&lt;/h2&gt;

&lt;p&gt;One real fix, low severity — and it's the kind of bug almost nobody writes on purpose:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Spark, &lt;code&gt;Response.java:314&lt;/code&gt; — the cookie that deletes a cookie was built without the Secure flag.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Spark's normal cookie path does this right. Its deletion path didn't carry the same flag. A deletion cookie should carry the same protections as the cookie it replaces. Otherwise you have one code path that respects your cookie policy and a second, quieter path that doesn't.&lt;/p&gt;

&lt;p&gt;The fix is one line. The lesson is bigger:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Check every path that sets a cookie — create, update, &lt;em&gt;and&lt;/em&gt; delete. Frameworks and apps usually secure the happy path. The cleanup path is where the flag gets dropped.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you ship anything with session cookies, grep for every cookie construction in your codebase today — not just the login handler.&lt;/p&gt;

&lt;h2&gt;
  
  
  What held — and why we report it anyway
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;JPetStore-6: 1 finding, not a defect.&lt;/strong&gt; A &lt;code&gt;ThreadLocalRandom&lt;/code&gt; call in the Maven wrapper downloader names a temporary file during a build-tool download. It protects nothing, so weak randomness there is not a security problem. Counted, explained, no fix recommended.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Spark, &lt;code&gt;Response.java:292&lt;/code&gt;: not a defect.&lt;/strong&gt; This is the correct normal cookie method. It calls &lt;code&gt;setSecure(secured)&lt;/code&gt; from its own parameter. A pattern scanner can't see that the flag is parameterized, so it fired anyway. We note it so a reader can see &lt;em&gt;why&lt;/em&gt; a hit was dismissed, not just that it was.&lt;/p&gt;

&lt;h2&gt;
  
  
  The noise, counted in the open
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;4 × SQL injection (CWE-89) in Spark's route dispatcher — false positives.&lt;/strong&gt; The lines are route-dispatch calls like &lt;code&gt;Routes.execute(...)&lt;/code&gt;. The file contains no SQL at all. The rule's sink pattern binds on a generic &lt;code&gt;execute(...)&lt;/code&gt; shape. That's a known collision class.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;8 × insecure cookie in test code.&lt;/strong&gt; Mock verifications asserting that a cookie method was called. They set no cookies. Counted here, excluded from the fix list.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;1 × weak randomness in example code.&lt;/strong&gt; &lt;code&gt;new Random()&lt;/code&gt; minting an ID in a bundled example app. Fine in a demo. It would be a real problem if that pattern were copied into production — predictable IDs are guessable IDs.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Tally: &lt;strong&gt;1 real fix (low), 1 informational, 14 not-a-defect — each with the reason printed beside it.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;On the labeled benchmark corpus where this same rule set was calibrated, its measured precision was 0.7169. In plain terms: even a decent scanner will hand you hits that don't survive reading. The reading is the service.&lt;/p&gt;

&lt;h2&gt;
  
  
  What a builder can use from this
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Audit cookie deletion as well as cookie creation.&lt;/strong&gt; Same flags, every path.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Don't let example-code randomness reach production.&lt;/strong&gt; &lt;code&gt;new Random()&lt;/code&gt; for IDs, tokens, or filenames that matter is a defect; for a throwaway temp name, it isn't. Context decides.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Demand dispositions, not just counts.&lt;/strong&gt; "16 findings" means nothing until each one is marked real, informational, or not-a-defect with a reason. If a report won't show its dismissals, you can't trust its fixes.&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;If you want this kind of check on your own app before launch, the intake is at verify.novitasnexus.com — &lt;a href="mailto:verify@novitasnexus.com"&gt;verify@novitasnexus.com&lt;/a&gt; if you prefer email.&lt;/p&gt;

</description>
      <category>backend</category>
      <category>infosec</category>
      <category>java</category>
      <category>security</category>
    </item>
  </channel>
</rss>
