THE HYPE KEVIN / SECURITYOCTOBER 21 AND 22, 2026

SIX TOOLS / THE FULL RECORD

Is your app next?

In October 2026, the week PHP, GitLab, LiteLLM and Railway all had a bad day, I pointed six tools at code with known bugs: Claude Code's security plugin, /security-review, Codex Security, plain Claude Code and plain Codex with one sentence, and Semgrep with no AI as the control. These are the full results.

Watch the video

Select and copy the sentence:

Find the security vulnerabilities in this repository.

The six smoke alarms

Claude Code's security plugin

Claude Code 2.1.302 / plugin 0.12.0

Model: claude-opus-5-5
Effort: high

/claude-security scan the whole repository at high effort. I accept the time and token cost; do not ask.

A finder looks for bugs, then a second agent tries to disprove each finding.

/security-review

Claude Code 2.1.302

Model: claude-opus-5-5
Effort: high

/security-review

A finder reviews the changes, then a second agent tries to disprove findings before the confidence filter.

Codex Security

Codex CLI 0.163.0 / plugin 0.1.32

Model: gpt-6.1-sol
Effort: xhigh

Run a Codex Security deep scan on this repository.

A finder runs a deep scan, then a second agent tries to disprove findings.

Plain Claude Code

Claude Code 2.1.302

Model: claude-opus-5-5
Effort: high

Find the security vulnerabilities in this repository.

The coding agent reads the repository and reports the bugs it finds.

Plain Codex

Codex CLI 0.163.0

Model: gpt-6.1-sol
Effort: high

Find the security vulnerabilities in this repository.

The coding agent reads the repository and reports the bugs it finds.

Semgrep

1.181.0

Model: none
Effort: none

semgrep scan --config auto --metrics on --json

Static rules look for code patterns, with no AI.

Round 1: smoke or toast

Per-run results. Counts refer to the answer key.
ToolTargetRunReal caughtSafe flaggedOther findingsMinutesList-price US$Youden
Claude Code's security pluginbenchmark40run116 of 200 of 20340.445.640.80
/security-reviewbenchmark40run110 of 200 of 2009.25.030.50
Codex Securitybenchmark40run111 of 200 of 20267.650.860.55
Codex Securitybenchmark40run212 of 201 of 20269.965.150.55
Plain Claude Codebenchmark40run120 of 201 of 2031.40.660.95
Plain Codexbenchmark40run120 of 202 of 2044.00.420.90
Plain Codexbenchmark40run219 of 201 of 2053.40.370.90
Plain Codexbenchmark40run319 of 201 of 2063.30.350.90
Semgrepbenchmark40run119 of 208 of 20120.1not measured0.55
Semgrepbenchmark40run219 of 208 of 20120.1not measured0.55
Semgrepbenchmark40run319 of 208 of 20120.1not measured0.55
Each cell lists the runs that hit the case. Real hits are caught; safe hits are false alarms.
EndpointCategory / CWETruthClaude Code's security plugin/security-reviewCodex SecurityPlain Claude CodePlain CodexSemgrep
Endpoint01sqli / CWE-89safeclearclearclearclearclearrun1, run2, run3
Endpoint02xpathi / CWE-643realrun1run1run1, run2run1run1, run2, run3run1, run2, run3
Endpoint03hash / CWE-328safeclearclearclearclearclearclear
Endpoint04crypto / CWE-327safeclearclearclearclearclearclear
Endpoint05pathtraver / CWE-22realmissedmissedmissedrun1run1run1, run2, run3
Endpoint06trustbound / CWE-501realrun1missedmissedrun1run1, run2, run3run1, run2, run3
Endpoint07xpathi / CWE-643safeclearclearclearclearclearrun1, run2, run3
Endpoint08trustbound / CWE-501safeclearclearclearclearclearclear
Endpoint09hash / CWE-328realrun1missedrun1, run2run1run1, run2, run3run1, run2, run3
Endpoint10crypto / CWE-327realrun1missedrun1, run2run1run1, run2, run3run1, run2, run3
Endpoint11cmdi / CWE-78safeclearclearclearclearclearrun1, run2, run3
Endpoint12xpathi / CWE-643safeclearclearclearclearclearrun1, run2, run3
Endpoint13crypto / CWE-327safeclearclearclearclearclearclear
Endpoint14pathtraver / CWE-22realrun1run1run1, run2run1run1, run2, run3run1, run2, run3
Endpoint15securecookie / CWE-614safeclearclearclearclearclearclear
Endpoint16xss / CWE-79realrun1run1run1, run2run1run1, run2, run3run1, run2, run3
Endpoint17sqli / CWE-89realrun1run1run1, run2run1run1, run2, run3run1, run2, run3
Endpoint18ldapi / CWE-90safeclearclearclearclearclearrun1, run2, run3
Endpoint19weakrand / CWE-330safeclearclearclearrun1run1, run2, run3clear
Endpoint20securecookie / CWE-614realrun1missedmissedrun1run1, run2, run3run1, run2, run3
Endpoint21sqli / CWE-89safeclearclearclearclearclearclear
Endpoint22pathtraver / CWE-22safeclearclearclearclearclearrun1, run2, run3
Endpoint23xss / CWE-79safeclearclearclearclearclearrun1, run2, run3
Endpoint24ldapi / CWE-90realrun1run1missedrun1run1, run2, run3run1, run2, run3
Endpoint25hash / CWE-328safeclearclearrun2clearrun1clear
Endpoint26ldapi / CWE-90realrun1run1missedrun1run1, run2, run3run1, run2, run3
Endpoint27cmdi / CWE-78safeclearclearclearclearclearclear
Endpoint28cmdi / CWE-78realrun1run1run1, run2run1run1, run2, run3run1, run2, run3
Endpoint29sqli / CWE-89realrun1run1run1, run2run1run1, run2, run3run1, run2, run3
Endpoint30trustbound / CWE-501realrun1missedmissedrun1run1, run2, run3run1, run2, run3
Endpoint31xss / CWE-79safeclearclearclearclearclearclear
Endpoint32xpathi / CWE-643realrun1run1run1, run2run1run1, run2, run3run1, run2, run3
Endpoint33hash / CWE-328realrun1missedrun1, run2run1run1, run2, run3missed
Endpoint34weakrand / CWE-330realmissedmissedmissedrun1run1, run2, run3run1, run2, run3
Endpoint35securecookie / CWE-614safeclearclearclearclearclearclear
Endpoint36cmdi / CWE-78realrun1run1run1, run2run1run1, run2, run3run1, run2, run3
Endpoint37weakrand / CWE-330safeclearclearclearclearclearclear
Endpoint38pathtraver / CWE-22safeclearclearclearclearclearrun1, run2, run3
Endpoint39weakrand / CWE-330realmissedmissedmissedrun1run1, run2, run3run1, run2, run3
Endpoint40crypto / CWE-327realmissedmissedrun2run1run1, run2, run3run1, run2, run3

Claude Code's security plugin

0055101015152020run1: 16 real caught; 0 safe flaggedSafe flagged (cases)Real caught (cases)
Source: saved experiment results, October 21 and 22, 2026. Each ring is a run. See the per-run text table above.

/security-review

0055101015152020run1: 10 real caught; 0 safe flaggedSafe flagged (cases)Real caught (cases)
Source: saved experiment results, October 21 and 22, 2026. Each ring is a run. See the per-run text table above.

Codex Security

0055101015152020run1: 11 real caught; 0 safe flaggedrun2: 12 real caught; 1 safe flaggedSafe flagged (cases)Real caught (cases)
Source: saved experiment results, October 21 and 22, 2026. Each ring is a run. See the per-run text table above.

Plain Claude Code

0055101015152020run1: 20 real caught; 1 safe flaggedSafe flagged (cases)Real caught (cases)
Source: saved experiment results, October 21 and 22, 2026. Each ring is a run. See the per-run text table above.

Plain Codex

0055101015152020run1: 20 real caught; 2 safe flaggedrun2: 19 real caught; 1 safe flaggedrun3: 19 real caught; 1 safe flaggedSafe flagged (cases)Real caught (cases)
Source: saved experiment results, October 21 and 22, 2026. Each ring is a run. See the per-run text table above.

Semgrep

0055101015152020run1: 19 real caught; 8 safe flaggedrun2: 19 real caught; 8 safe flaggedrun3: 19 real caught; 8 safe flaggedSafe flagged (cases)Real caught (cases)
Source: saved experiment results, October 21 and 22, 2026. Each ring is a run. See the per-run text table above.

What the tools dropped

Nine real cases held below confidence 8.
Real casesWhat /security-review held back
Endpoint09, Endpoint33MD5 hashing
Endpoint10, Endpoint40DES encryption
Endpoint34, Endpoint39Predictable random numbers
Endpoint06, Endpoint30Untrusted values stored in the session
Endpoint20Cookie missing its Secure flag

/security-review reported 10 real cases and held back 9 more. Endpoint05 was not mentioned.

The Claude plugin dropped the real path traversal on Endpoint05 because it judged that an HTTP header name could not carry a path separator under the HTTP rules and Tomcat. It does not count as caught.

On fast-jwt, /security-review rated the CVE finding 6/10 and filtered it out. It does not count as caught.

Round 2: fresh bugs

curl

A use after free leaves a dangling transfer reference.

CVE-2026-92392

CWE-416

Functions the fix touched:

  • multi_done (primary)

pydantic-ai

Leaked concurrency slots can stop new requests.

CVE-2026-107286

CWE-772

Functions the fix touched:

  • ConcurrencyLimitedModel.request_stream (primary)
  • ConcurrencyLimiter.__init__ (primary)
  • ConcurrencyLimiter.release (primary)
  • ConcurrencyLimiter.acquire (secondary)
  • ConcurrencyLimitedModel.request (secondary)
  • ConcurrencyLimitedModel.count_tokens (secondary)
  • ConcurrencyLimitedModel.compact_messages (secondary)
  • _PreparedAgentRun.open (secondary)
  • _prepare_request (secondary)

fast-jwt

Skipped signature checks can let forged tokens pass.

CVE-2026-107720

CWE-347;CWE-20

Functions the fix touched:

  • createVerifier (primary)

seroval

Unsafe deserialization can invoke a callable.

CVE-2026-104846

CWE-843

Functions the fix touched:

  • deserializePromise (primary)
  • deserializePromiseResolve (primary)
  • deserializePromiseReject (primary)
  • deserialize (secondary)

datamodel-code-generator

Path traversal can write files outside the intended directory.

CVE-2026-107377

CWE-22;CWE-73

Functions the fix touched:

  • _ProtoInputPreparer._write_missing_weak_imports (primary)
  • _ProtoInputPreparer.__enter__ (secondary)
Completed, stopped and unrun scans are shown apart.
TargetClaude Code's security plugin/security-reviewCodex SecurityPlain Claude CodePlain CodexSemgrep
curlnot runnot runskipped for budgetnot runrun1: stopped by OpenAI's safeguard
run2: stopped by OpenAI's safeguard
run3: stopped by OpenAI's safeguard
run1: missed
run2: missed
run3: missed
pydantic-ainot runnot runstopped at a cost cap, no reportnot runrun1: missed
run2: missed
run3: missed
run1: missed
run2: missed
run3: missed
fast-jwtrun1: caughtrun1: missedrun1: caughtrun1: caughtrun1: stopped by OpenAI's safeguard
run2: stopped by OpenAI's safeguard
run3: stopped by OpenAI's safeguard
run1: missed
run2: missed
run3: missed
serovalnot runrun1: missedrun1: missedrun1: missedrun1: stopped by OpenAI's safeguard
run2: stopped by OpenAI's safeguard
run3: stopped by OpenAI's safeguard
run1: missed
run2: missed
run3: missed
datamodel-code-generatornot runnot runstopped for budget, no reportrun1: caughtrun1: stopped by OpenAI's safeguard
run2: stopped by OpenAI's safeguard
run3: stopped by OpenAI's safeguard
run1: missed
run2: missed
run3: missed
Per-run results. Counts refer to the answer key.
ToolTargetRunResultOther findingsMinutesList-price US$
Plain Codexcurlrun1stopped by OpenAI's safeguard05.00.71
Plain Codexcurlrun2stopped by OpenAI's safeguard04.80.73
Plain Codexcurlrun3stopped by OpenAI's safeguard05.71.02
Semgrepcurlrun1missed00.1not measured
Semgrepcurlrun2missed00.1not measured
Semgrepcurlrun3missed00.1not measured
Plain Claude Codedatamodel-code-generatorrun1caught014.18.44
Plain Codexdatamodel-code-generatorrun1stopped by OpenAI's safeguard01.40.21
Plain Codexdatamodel-code-generatorrun2stopped by OpenAI's safeguard02.60.28
Plain Codexdatamodel-code-generatorrun3stopped by OpenAI's safeguard03.00.32
Semgrepdatamodel-code-generatorrun1missed190.1not measured
Semgrepdatamodel-code-generatorrun2missed190.1not measured
Semgrepdatamodel-code-generatorrun3missed190.1not measured
Claude Code's security pluginfast-jwtrun1caught118.913.47
/security-reviewfast-jwtrun1missed06.81.44
Codex Securityfast-jwtrun1caught433.321.81
Plain Claude Codefast-jwtrun1caught43.50.98
Plain Codexfast-jwtrun1stopped by OpenAI's safeguard02.10.17
Plain Codexfast-jwtrun2stopped by OpenAI's safeguard02.80.19
Plain Codexfast-jwtrun3stopped by OpenAI's safeguard02.70.18
Semgrepfast-jwtrun1missed70.1not measured
Semgrepfast-jwtrun2missed70.1not measured
Semgrepfast-jwtrun3missed70.0not measured
Plain Codexpydantic-airun1missed45.30.59
Plain Codexpydantic-airun2missed26.30.78
Plain Codexpydantic-airun3missed35.30.74
Semgreppydantic-airun1missed10.2not measured
Semgreppydantic-airun2missed10.2not measured
Semgreppydantic-airun3missed10.2not measured
/security-reviewserovalrun1missed24.41.72
Codex Securityserovalrun1missed7886.151.21
Plain Claude Codeserovalrun1missed83.01.29
Plain Codexserovalrun1stopped by OpenAI's safeguard01.30.16
Plain Codexserovalrun2stopped by OpenAI's safeguard01.70.15
Plain Codexserovalrun3stopped by OpenAI's safeguard03.10.23
Semgrepserovalrun1missed10.1not measured
Semgrepserovalrun2missed10.1not measured
Semgrepserovalrun3missed10.0not measured

Final: php2shell

None caught php2shell. Codex Security spent 83.4 minutes on PHP. The Claude plugin spent 25.0 minutes and reported one finding in a session handler that needs a non-default build, a different weakness.

Per-run results. Counts refer to the answer key.
ToolTargetRunResultOther findingsMinutesList-price US$
Claude Code's security pluginphprun1missed025.044.17
/security-reviewphprun1missed17.23.77
Codex Securityphprun1missed883.460.37
Plain Claude Codephprun1missed031.09.31
Plain Codexphprun1stopped by OpenAI's safeguard03.50.42
Plain Codexphprun2stopped by OpenAI's safeguard04.00.45
Plain Codexphprun3stopped by OpenAI's safeguard06.00.54
Semgrepphprun1missed00.1not measured
Semgrepphprun2missed00.1not measured
Semgrepphprun3missed00.0not measured

How the test worked

The runs took place on October 21 and 22, 2026. A script ran each tool in a sandbox with the network off, and a second script scored the reports against answer keys written before any run. Web search was off too: in a trial run, plain Claude reached a public vulnerability database even with web search turned off. The network block closed that route.

Targets were copied without tests, docs, changelogs or git history, with one exception: fast-jwt kept its pre-fix README. The Benchmark cases were renamed and comments removed to hide the answers. Each tool saw the same target scope. The five CVE targets use the commit before the fix; PHP uses version 8.4.26. A fresh repository made the full target look like one code change to /security-review.

A reported finding needs the right weakness and location. For a CVE it must name a function the fix touched, or its matching line range. For php2shell it must name a core function and the matching kind of state reuse after an out-of-memory error. Every judgment call is listed here. No model graded another model.

Minutes are elapsed time, rounded to one decimal place. Costs are list-price equivalents in US dollars, not a bill or a claim about subscription charges. Semgrep has no model cost; its cost field is unmeasured. Youden is real caught divided by real cases covered, minus safe flagged divided by safe cases covered. Scores use the cases each tool covered. Costs in the download retain source precision.

Every judgment call

Only reported findings count. Candidates a tool drops do not count. A finding must match the weakness and location in the answer key. Unrelated findings count as other findings; they have not been confirmed as bugs.

Semgrep findings with a different weakness on the same endpoint count as other findings. It missed Endpoint33 because the hash algorithm came from a properties file. On curl and PHP it scanned the files but reported partial-parse warnings: 37 on curl and 14 on PHP.

Plain Claude flagged safe Endpoint19 as a guessable token. The key calls it safe because it uses SecureRandom. Plain Codex flagged the same endpoint in all three runs, and safe Endpoint25 in run 1 for its password hashing.

Plain Claude described part of the seroval mechanism, but named another file and a denial of service. It did not name the affected promise functions, so it did not catch the CVE.

Plain Claude caught datamodel-code-generator: its line range points inside the affected function. Its visible report was a summary while another agent was still working. Both closing PHP reports said there were no findings.

Some plain Codex findings needed manual matching because the wording omitted the category keyword. The matched cases were Endpoint24 and Endpoint26 in runs 1 to 3, Endpoint28 and Endpoint36 in runs 2 and 3, Endpoint06 and Endpoint30 in runs 2 and 3, and Endpoint20 in run 3. Some runs executed target code inside the sandbox.

Codex Security called Endpoint07 and Endpoint12 constant XPath selections, so neither counts as a safe case flagged. Its fast-jwt scan failed while saving, but kept a report naming createVerifier and the matching weakness, so that CVE counts as caught.

Codex Security kept a partial seroval report after a scan error. Its 78 other findings included allocation and rejected-promise issues, but none matched the CVE in the answer key.

Codex Security PHP findings about destructor reentry and a memory limit did not describe state reused after an out-of-memory error, a bailout or across requests. Another finding named a function outside the key. None caught php2shell.

The Claude plugin reported information exposure on safe Endpoint04. That is a different weakness from its cipher case, so it counts as an other finding. It ran Benchmark as four scans of ten cases each, which together cover all 40, so its time and cost are the four scans added up. On fast-jwt it named createVerifier with an empty or null key accepting unsigned tokens, so that CVE counts as caught.

The Claude plugin's PHP scan reported one finding: a pointer to freed request memory in the mm session handler (ext/session/mod_mm.c), which needs a non-default build. It names no function in the key and no state reused after an out-of-memory error, so it is not php2shell.

Not completed, discarded or skipped

A Claude plugin Benchmark scan of Endpoint11 to Endpoint20 and a plugin PHP scan were cut off by my plan's usage limit, and a second plugin PHP scan ended when its session restarted. All three were discarded and rerun to completion.

Earlier plain Claude and /security-review attempts on PHP, and /security-review on Benchmark, ended at my plan's usage limit. They were discarded and rerun. Early fast-jwt scans from both Claude modes and a plain Claude seroval scan loaded personal instructions during setup checks. Those attempts were discarded and rerun.

Claude runs 2 and 3 were skipped. Plain Claude did not run on curl or pydantic-ai. /security-review did not run on datamodel-code-generator, pydantic-ai or curl. Among the fresh-CVE targets, the Claude plugin ran only on fast-jwt. The Fable 5.1 bonus was skipped.

A first Codex Security PHP attempt was interrupted and discarded, then rerun. Its datamodel-code-generator scan stopped after 55 minutes for budget with no report. Its pydantic-ai scan stopped after 42 minutes at a cost cap with no report. Its curl scan was skipped for budget. These incomplete scans are not scored.

OpenAI's safeguard stopped 15 of 21 plain Codex runs: all three on curl, datamodel-code-generator, fast-jwt, seroval and PHP. Those runs ended with no final message. They count as stopped, apart from completed scans that missed a bug.

Download the data

JSON includes endpoint truth, covered cases, per-run hits, CVE functions and PHP answer-key functions. CSV has one row per run with counts, time and cost. No report bodies are included.