<?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: omarmohelal</title>
    <description>The latest articles on DEV Community by omarmohelal (@omarmohelal).</description>
    <link>https://dev.to/omarmohelal</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%2F4106203%2F4903a2ff-1b06-432e-a23f-24523ac761f1.png</url>
      <title>DEV Community: omarmohelal</title>
      <link>https://dev.to/omarmohelal</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/omarmohelal"/>
    <language>en</language>
    <item>
      <title>Why my security scanner refuses to tell you your code is clean</title>
      <dc:creator>omarmohelal</dc:creator>
      <pubDate>Sat, 05 Sep 2026 10:18:40 +0000</pubDate>
      <link>https://dev.to/omarmohelal/why-my-security-scanner-refuses-to-tell-you-your-code-is-clean-5aj8</link>
      <guid>https://dev.to/omarmohelal/why-my-security-scanner-refuses-to-tell-you-your-code-is-clean-5aj8</guid>
      <description>&lt;p&gt;There is a failure mode in security tooling that almost nobody instruments for,&lt;br&gt;
and once you see it you cannot unsee it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;An empty findings list looks identical to a clean result.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A scanner that crashed halfway, a scanner whose API key expired, a scanner that&lt;br&gt;
ran out of budget, and a scanner that genuinely examined everything and found&lt;br&gt;
nothing — all four produce the same artifact: &lt;code&gt;findings: []&lt;/code&gt;. The CI job goes&lt;br&gt;
green. The PR merges. Nobody involved can tell which of the four happened.&lt;/p&gt;

&lt;p&gt;I built an application-security agent, and this is the problem I ended up&lt;br&gt;
designing the whole thing around.&lt;/p&gt;
&lt;h2&gt;
  
  
  What it does instead
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;sechelix
sechelix audit examples/demo-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  BLOCKED    authorization   no reasoning executor configured; this node
                             analyses code and cannot be answered by the
                             runner alone
  SUCCEEDED  map
  BLOCKED    verify          dependency not satisfied: authorization
  BLOCKED    gate            dependency not satisfied: verify

RESULT  INCOMPLETE - unsatisfied mandatory nodes: gate, verify
        No security claim can be made from this run.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Exit code 1. Not because your code is bad — because &lt;strong&gt;nothing was examined&lt;/strong&gt;,&lt;br&gt;
and the tool will not pretend otherwise.&lt;/p&gt;

&lt;p&gt;The states are deliberately distinct:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;State&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;SUCCEEDED&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;the lane ran and delivered&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;SKIPPED&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;the lane does not apply to this target — it owes no evidence&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;BLOCKED&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;the lane could not run. A real question is open&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;FAILED&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;the lane ran and errored&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;SKIPPED&lt;/code&gt; and &lt;code&gt;BLOCKED&lt;/code&gt; are the pair that matters. An inapplicable lane is a&lt;br&gt;
real answer. An unaffordable verifier is not.&lt;/p&gt;
&lt;h2&gt;
  
  
  The budget case is the one that convinced me
&lt;/h2&gt;

&lt;p&gt;Give a run a cost ceiling and let it run out just before the verifier:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;map     SUCCEEDED
authz   SUCCEEDED
verify  BLOCKED    max_cost_usd budget exhausted: requested 0.5, 0.1 remaining
gate    BLOCKED    dependency not satisfied: verify

unsatisfied mandatory: ['gate', 'verify']
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A budget limit that silently skips verification and then returns PASS has&lt;br&gt;
converted a cost control into a correctness bug. That is strictly worse than&lt;br&gt;
having no budget at all, because now the failure is invisible. There is a test&lt;br&gt;
that starves the budget mid-verification and asserts the gate never passes.&lt;/p&gt;
&lt;h2&gt;
  
  
  Blinding the verifier
&lt;/h2&gt;

&lt;p&gt;The second design decision: a hunter proposes findings, and an independent&lt;br&gt;
verifier tries to refute them. The verifier is &lt;strong&gt;not told&lt;/strong&gt; the hunter's&lt;br&gt;
confidence, severity, verdict, or exploitability — those fields are stripped&lt;br&gt;
before the candidate is handed over.&lt;/p&gt;

&lt;p&gt;The reason is mundane. A verifier that reads &lt;em&gt;"HIGH confidence SQL injection,&lt;br&gt;
definitely exploitable"&lt;/em&gt; before it looks at the code is not verifying. It is&lt;br&gt;
agreeing.&lt;/p&gt;

&lt;p&gt;I tested this by planting a fake finding. Two candidates went in: one real&lt;br&gt;
(against a file with a genuine missing ownership check), one fabricated against&lt;br&gt;
that file's &lt;strong&gt;clean twin&lt;/strong&gt;, tagged as loudly as I could make it —&lt;br&gt;
&lt;code&gt;confidence: HIGH&lt;/code&gt;, &lt;code&gt;severity: CRITICAL&lt;/code&gt;, &lt;code&gt;verdict: exploitable&lt;/code&gt;,&lt;br&gt;
&lt;code&gt;hunter_notes: certain this is a real IDOR&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The verifier kept the real one and refuted the plant:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;refuted: the candidate locating the missing-ownership claim at&lt;br&gt;
&lt;code&gt;clean/orders.py:get_order&lt;/code&gt; is false. The clean variant explicitly compares&lt;br&gt;
&lt;code&gt;order['user_id']&lt;/code&gt; to &lt;code&gt;session['user_id']&lt;/code&gt; and returns &lt;code&gt;(None, 404)&lt;/code&gt; on&lt;br&gt;
mismatch before the success return.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It named the exact line. And a capture of the prompt actually sent confirms&lt;br&gt;
&lt;code&gt;HIGH&lt;/code&gt;, &lt;code&gt;CRITICAL&lt;/code&gt;, &lt;code&gt;exploitable&lt;/code&gt; and the hunter's note never reached it.&lt;/p&gt;
&lt;h2&gt;
  
  
  Paired fixtures, because precision is the hard part
&lt;/h2&gt;

&lt;p&gt;The demo corpus has five vulnerable files and five clean counterparts, each pair&lt;br&gt;
differing in exactly one security-relevant way.&lt;/p&gt;

&lt;p&gt;This is not decoration. &lt;strong&gt;A corpus that only contains bugs cannot measure&lt;br&gt;
whether a tool stops.&lt;/strong&gt; An agent that flags every line scores perfectly on a&lt;br&gt;
vulnerable-only benchmark and is useless in a real repository. If the clean twin&lt;br&gt;
is not in the corpus, a false positive is invisible.&lt;/p&gt;
&lt;h2&gt;
  
  
  It found a bug I wrote
&lt;/h2&gt;

&lt;p&gt;I pointed the tool at its own runner. It found a path traversal:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;run_id&lt;/code&gt; arrives from the command line — &lt;code&gt;sechelix report &amp;lt;id&amp;gt;&lt;/code&gt; — and was joined&lt;br&gt;
straight onto the runs directory. So:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;run_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'../../outside.json'&lt;/span&gt;  -&amp;gt;  resolves outside the workspace
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;report&lt;/code&gt; would then read that file and print it. Fixed with a shape check plus a&lt;br&gt;
resolved-path confinement check, and ten regression tests. It is in the history&lt;br&gt;
at commit &lt;code&gt;0e50b56&lt;/code&gt; rather than quietly patched.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I have not measured
&lt;/h2&gt;

&lt;p&gt;There is a blind evaluation: 76 cases judged by 76 independent processes, each&lt;br&gt;
launched from an empty directory containing only the case file — precision&lt;br&gt;
0.950, false-positive rejection 0.947. That is a &lt;strong&gt;label-only&lt;/strong&gt; result on 38&lt;br&gt;
authored pairs. It is not a measurement of the full workflow, which is still&lt;br&gt;
marked &lt;code&gt;NOT_MEASURED&lt;/code&gt; in the repository.&lt;/p&gt;

&lt;p&gt;I also have not benchmarked against SEC-AF, Cloudflare's security-audit skill,&lt;br&gt;
or Strix. So I am not claiming to beat them. The comparison does not exist yet,&lt;br&gt;
and saying so is cheaper than being caught.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Agent Skill — Claude Code, Codex, Copilot. No Python.&lt;/span&gt;
npx skills@latest add omarmohelal/SecHelix &lt;span class="nt"&gt;--skill&lt;/span&gt; sechelix

&lt;span class="c"&gt;# Optional runner&lt;/span&gt;
pip &lt;span class="nb"&gt;install &lt;/span&gt;sechelix
sechelix doctor
sechelix audit examples/demo-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;STATIC&lt;/code&gt; is the default and performs no network access at all. No account, no&lt;br&gt;
email, no cloud.&lt;/p&gt;

&lt;p&gt;Apache-2.0 · &lt;a href="https://github.com/omarmohelal/SecHelix" rel="noopener noreferrer"&gt;github.com/omarmohelal/SecHelix&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you disagree with the fail-closed design — and there is a real argument that&lt;br&gt;
a noisy &lt;code&gt;INCOMPLETE&lt;/code&gt; trains people to ignore it — I would genuinely like to hear&lt;br&gt;
it.&lt;/p&gt;

</description>
      <category>automation</category>
      <category>python</category>
      <category>security</category>
      <category>tooling</category>
    </item>
    <item>
      <title>Why an AppSec agent should try to disprove its own findings</title>
      <dc:creator>omarmohelal</dc:creator>
      <pubDate>Wed, 02 Sep 2026 12:49:43 +0000</pubDate>
      <link>https://dev.to/omarmohelal/why-an-appsec-agent-should-try-to-disprove-its-own-findings-23p6</link>
      <guid>https://dev.to/omarmohelal/why-an-appsec-agent-should-try-to-disprove-its-own-findings-23p6</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://sechelix.com/research/why-an-appsec-agent-should-try-to-disprove-its-own-findings" rel="noopener noreferrer"&gt;sechelix.com&lt;/a&gt;. This is a syndicated copy; the canonical version lives there.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The failure mode nobody optimises for
&lt;/h2&gt;

&lt;p&gt;Point a capable model at a codebase and ask it to find security problems, and it will find some. It will also produce findings that are confident, well-structured, and wrong — and those read exactly like the real ones, because nothing about a fluent explanation requires the underlying claim to be true.&lt;/p&gt;

&lt;p&gt;That asymmetry is the actual problem. A missed bug costs you the bug. A plausible false positive costs a reviewer an hour, and the third one costs you their attention for every finding after it.&lt;/p&gt;

&lt;p&gt;Teams do not abandon bad security tooling because it misses things. They abandon it because they stop believing it. Once a tool has been wrong three times in a way that felt authoritative, its next report gets skimmed — including the one that was right.&lt;/p&gt;

&lt;p&gt;Most effort in this space goes into detection. I think the more useful lever is refusal.&lt;/p&gt;

&lt;h2&gt;
  
  
  A finding is a claim
&lt;/h2&gt;

&lt;p&gt;The design premise of SecHelix is one sentence: &lt;strong&gt;a security finding is a claim, and a claim gets an independent refutation attempt before anyone is told about it.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Three mechanisms carry most of that.&lt;/p&gt;

&lt;h3&gt;
  
  
  Applicability has four outcomes, and one of them cannot be laundered
&lt;/h3&gt;

&lt;p&gt;Every check resolves to &lt;code&gt;APPLICABLE&lt;/code&gt;, &lt;code&gt;NOT_APPLICABLE&lt;/code&gt;, &lt;code&gt;UNKNOWN&lt;/code&gt;, or &lt;code&gt;BLOCKED&lt;/code&gt;. &lt;code&gt;UNKNOWN&lt;/code&gt; and &lt;code&gt;BLOCKED&lt;/code&gt; can never be converted into &lt;code&gt;NOT_APPLICABLE&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This sounds like bookkeeping. It is the single change with the largest effect on what a report &lt;em&gt;means&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Without it, "we could not evaluate this" and "this does not apply here" collapse into the same clean-looking output, and a reader cannot tell a check that passed from a check that never ran. With it, a clean report becomes a much stronger statement, because everything the tool could not establish is still visible on the page.&lt;/p&gt;

&lt;h3&gt;
  
  
  The verifier's job is to lose
&lt;/h3&gt;

&lt;p&gt;Every candidate goes to an independent verifier prompted to disprove it — not to double-check it, to attack it. Attacker control. Reachability. Missing guard assumptions. Role preconditions. Whether the vulnerable state is producible at all. Whether some compensating control already blocks the exploit.&lt;/p&gt;

&lt;p&gt;Findings that survive carry a seven-link evidence chain, and a finding that cannot name its links does not ship. High and Critical additionally require regression proof: the assertion has to fail against the vulnerable control and pass after the fix, or the claim that it was fixed is itself unverified.&lt;/p&gt;

&lt;h3&gt;
  
  
  The gate fails closed
&lt;/h3&gt;

&lt;p&gt;The release decision is &lt;code&gt;PASS&lt;/code&gt;, &lt;code&gt;PASS_WITH_KNOWN_RISK&lt;/code&gt;, &lt;code&gt;BLOCKED&lt;/code&gt;, or &lt;code&gt;INCOMPLETE&lt;/code&gt;. Missing required evidence returns &lt;code&gt;INCOMPLETE&lt;/code&gt; and a non-zero exit — never a silent pass.&lt;/p&gt;

&lt;p&gt;A gate that passes when it cannot see is worse than no gate, because it manufactures confidence.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this looks like on real code
&lt;/h2&gt;

&lt;p&gt;An authorized self-audit of a small Next.js storefront I own. &lt;code&gt;STATIC&lt;/code&gt; and &lt;code&gt;LOCAL&lt;/code&gt; mode, zero scanners enabled, nothing outside &lt;code&gt;127.0.0.1&lt;/code&gt; contacted. One external data source, forty-one of 546 hypotheses applicable, three candidates.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;One verified.&lt;/strong&gt; No &lt;code&gt;CSP&lt;/code&gt;, &lt;code&gt;X-Frame-Options&lt;/code&gt; or &lt;code&gt;HSTS&lt;/code&gt; on any route. A probe page served from a separate origin framed the entire interface, including the sign-in entry point. The fix was a catch-all headers rule; the proof was the browser's own refusal on retest:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Framing '&lt;a href="http://localhost:3009/" rel="noopener noreferrer"&gt;http://localhost:3009/&lt;/a&gt;' violates the following Content Security Policy directive: "frame-ancestors 'none'". The request has been blocked.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It was held at &lt;strong&gt;MEDIUM&lt;/strong&gt;, not High. The realistic outcome is phishing amplification, and the app performs no authenticated state-changing actions. Severity you can defend under questioning is worth more than severity that looks impressive in a summary.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;One refuted.&lt;/strong&gt; Remote configuration values reached &lt;code&gt;href&lt;/code&gt; and &lt;code&gt;src&lt;/code&gt; with only &lt;code&gt;.trim()&lt;/code&gt; applied. That is precisely the shape a scanner — or a confident reviewer — reports as high-severity XSS.&lt;/p&gt;

&lt;p&gt;Verification killed it. React 19 rewrote the payload to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;href="javascript:throw new Error('React has blocked a javascript: URL as a security precaution.')"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and attacker control over the configuration source was never established. Recorded &lt;code&gt;FALSE_POSITIVE&lt;/code&gt;, with the refutation reasoning kept rather than deleted.&lt;/p&gt;

&lt;p&gt;A scheme allowlist was added anyway — and labelled &lt;strong&gt;hardening, not a vulnerability fix&lt;/strong&gt;, because calling it a fix would imply there had been a vulnerability.&lt;/p&gt;

&lt;p&gt;That second result is the one I would point at. Any tool can produce findings. Discarding one is the part that costs something.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;And one process finding&lt;/strong&gt;, recorded because it is the interesting kind of near-miss. The first retest &lt;em&gt;appeared to fail&lt;/em&gt;. A stale prerender cache and a server still bound to the old port made a real fix look broken — which is exactly the mechanism by which a real fix silently becomes a false claim of remediation in the other direction. Only a clean rebuild settled it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The same discipline, turned inward
&lt;/h2&gt;

&lt;p&gt;The uncomfortable version of this argument is what happens when you point the tool at itself.&lt;/p&gt;

&lt;p&gt;Running the differential reviewer over its own changes produced findings for a docstring explaining that a digest "is not a signature" — classified as a webhook change — and a comment about a sample-size bucket, classified as storage access. Neither line does anything. The tool was flagging its own prose.&lt;/p&gt;

&lt;p&gt;Writing tests that tried to &lt;em&gt;break&lt;/em&gt; the fail-closed guarantees, rather than confirm them, found worse. An unresolved &lt;code&gt;CRITICAL&lt;/code&gt; candidate passed the release gate, because the status enum covering "unproven" listed several states and not the most common one. An empty commit string made every report read as current, because two revisions were compared on the shorter of their lengths and nothing enforced a floor — and an empty string is exactly what &lt;code&gt;git rev-parse&lt;/code&gt; returns when it produces no output rather than failing.&lt;/p&gt;

&lt;p&gt;Both were fail-open paths in modules whose stated contract is fail-closed. Both are fixed. Both are in the changelog under their own heading, because a project arguing that findings need proof does not get to be quiet about its own.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I am not claiming
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The benchmark was unpublished for months, on purpose.&lt;/strong&gt; The repository contains 38 paired vulnerable/clean fixtures and a working scoring harness. It also contained a machine-readable blocker, &lt;code&gt;CONTAMINATED_EVALUATOR&lt;/code&gt;, recording why no number was published: the fixtures were authored by assistant sessions working in the repository, so scoring one of those sessions measures recall of answers it wrote rather than security-review capability.&lt;/p&gt;

&lt;p&gt;A sealed blind packet exists so an uncontaminated evaluator can produce a real measurement. On 2026-09-02 one finally ran: 76 cases, each judged by a separate process that had never seen the repository, the fixtures, the labels or the pairings. The committed result is &lt;code&gt;evals/results/claude-sonnet-5-blind-2026-09-02.json&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Read that result narrowly.&lt;/strong&gt; It measures a single-pass, label-only judgment — one question per file, one label back. There was no attack-surface pass, no independent refutation pass, no adapters, no evidence chain and no release gate. It is &lt;em&gt;not&lt;/em&gt; a measurement of the workflow this article describes, and &lt;code&gt;applicability_accuracy&lt;/code&gt;, &lt;code&gt;regression_proof_rate&lt;/code&gt; and &lt;code&gt;release_gate_accuracy&lt;/code&gt; are still the literal string &lt;code&gt;NOT_MEASURED&lt;/code&gt;. One model, one run, on an authored and balanced suite. No comparison to any other tool is offered or implied.&lt;/p&gt;

&lt;p&gt;Everything else on the list still stands:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The committed keyword baseline is not a score.&lt;/strong&gt; It is a regex matcher, flagged &lt;code&gt;is_sechelix_result: false&lt;/code&gt;, that lands at chance on the fixture suite. It exists to prove the scoring harness works and that the fixtures resist pattern matching.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One case study is not evidence of general performance.&lt;/strong&gt; One small app, self-audited by the author, one verified MEDIUM finding, one refutation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It is alpha.&lt;/strong&gt; Contracts and interfaces can still change.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It is built with substantial AI assistance&lt;/strong&gt;, directed by a human. Saying otherwise would be its own kind of unverified claim.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx skills@latest add omarmohelal/SecHelix &lt;span class="nt"&gt;--skill&lt;/span&gt; sechelix
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then ask your agent for an authorized audit of a repository you own.&lt;/p&gt;

&lt;p&gt;Apache-2.0, Python standard library only: &lt;a href="https://github.com/omarmohelal/SecHelix" rel="noopener noreferrer"&gt;github.com/omarmohelal/SecHelix&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The critique I actually want is whether a refutation step run by the same class of model that generated the candidate is meaningfully independent, or whether it only catches the shallowest errors. I have a design opinion about that — the quorum mechanism exists because I am not sure — and the label-only run above does not answer it. I would rather say so than imply otherwise.&lt;/p&gt;

</description>
      <category>appsec</category>
      <category>security</category>
      <category>ai</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
