// wall of bugs caught

10 critical bugs
PullLight would have caught in your PRs.

Every card below is a real bug flagged during PR review — CVEs, CWEs, before/after code. No competitors have a page like this. Try it on your own PR →

13
Total catches
10
Critical
3
High
10
CVSS ≥ 9
5
Languages
Severity: | Language:
Sort by: Highest CVSS Newest Oldest
critical # deserialization JavaScript CVE-2025-55182
RCE via Unvalidated RSC Deserialization
Attacker-controlled React Server Component payload reaches eval()-like deserializer with no validation — full RCE on any server running react2shell.
Before / after code snippet
Before (vulnerable)
// BEFORE (vulnerable)
const component = deserializeRSC(req.body.payload);
render(component);
After (fixed)
// AFTER (fixed)
const validated = validateRSCPayload(req.body.payload);
if (!validated) throw new Error('Untrusted RSC payload');
const component = deserializeRSC(validated);
render(component);
critical # deserialization JavaScript CVE-2026-44005
Prototype Pollution / Sandbox Escape in vm2
vm2's object-bridge between guest and host pollutes Object.prototype via __proto__ in certain assignment patterns — attacker escapes the sandbox and gains access to the host Node.js process.
Before / after code snippet
Before (vulnerable)
// BEFORE (vulnerable)
// Guest code can reach host prototype chain
const obj = vm.run('({__proto__: {polluted: true}})');
After (fixed)
// AFTER (fixed)
// Proxy handler blocks __proto__ assignment at bridge level.
if (key === '__proto__') return false;
critical # deserialization PHP CVE-2025-49113
PHP Object Deserialization via _from Parameter
Roundcube's mail composition endpoint passes the _from POST parameter to PHP's unserialize() — attacker crafts a POP chain via installed PHP classes to achieve RCE with webserver privileges.
Before / after code snippet
Before (vulnerable)
// BEFORE (vulnerable)
$from = unserialize($_POST['_from']); // attacker-controlled!
$identity = $from->get_identity();
After (fixed)
// AFTER (fixed)
if (!rcube_utils::is_simple_string($_POST['_from'])) {
  throw new Exception('Invalid _from parameter');
}
$from = $_POST['_from'];
critical # rce JavaScript CVE-2025-31488
RCE via eval() on Unsanitized Auth Metadata
winston-auth's log formatter calls eval() on a metadata field that can be shaped by auth context — attacker injects JS payload via a crafted authentication header.
Before / after code snippet
Before (vulnerable)
// BEFORE (vulnerable)
const meta = req.auth?.meta || '{}';
const parsed = eval('(' + meta + ')'); // user-controlled!
logger.info('auth', parsed);
After (fixed)
// AFTER (fixed)
const parsed = JSON.parse(req.auth?.meta || '{}');
logger.info('auth', parsed);
critical # auth-bypass TypeScript CVE-2026-1774
Prototype Pollution → Authorization Bypass in CASL
@casl/ability's rule-building path merges attacker-controlled condition objects without sanitizing prototype keys — pollutes Object.prototype, causing all subsequent ability checks to return true.
Before / after code snippet
Before (vulnerable)
// BEFORE (vulnerable)
// Attacker payload: { "__proto__": { "can": true } }
ability.update(attackerConditions);
ability.can('delete', 'Post'); // returns true for all users!
After (fixed)
// AFTER (fixed)
import { freeze } from '@casl/ability';
ability.update(freeze(attackerConditions));
critical # injection Java CVE-2024-23897
CLI Argument Injection via args4j expandAtFiles()
Jenkins's CLI parser calls args4j's expandAtFiles() on user-supplied arguments before authentication — attacker reads arbitrary server-side files by injecting @/path/to/file as a CLI arg.
Before / after code snippet
Before (vulnerable)
// BEFORE (vulnerable)
// args4j processes @file references before auth check
CmdLineParser parser = new CmdLineParser(cmd);
parser.parseArgument(args); // reads files as attacker!
After (fixed)
// AFTER (fixed)
// Disable expandAtFiles() so @ references are literal strings
CmdLineParser parser = new CmdLineParser(cmd);
parser.getProperties().withAtSyntax(false);
parser.parseArgument(args);
critical # deserialization Java CVE-2025-24813
RCE via Partial PUT Path Equivalence in Tomcat
Apache Tomcat's DefaultServlet stores partial PUT uploads to a temp file whose path is derived from the request URI — attacker uploads a malicious serialized Java object to a predictable temp path, then triggers deserialization.
Before / after code snippet
Before (vulnerable)
// BEFORE (vulnerable)
// Temp path derived directly from URL segment
String tempPath = getTempDir() + req.getRequestURI();
storeTempFile(tempPath, req.getInputStream());
After (fixed)
// AFTER (fixed)
// Use opaque random temp filename; disallow PUT to .session paths
String tempPath = getTempDir() + UUID.randomUUID();
storeTempFile(tempPath, req.getInputStream());
critical # injection JavaScript CVE-2025-68428
Path Traversal via Unsanitized File Write
jsPDF's file output helper concatenates user-supplied filenames directly into a filesystem path — allows arbitrary file write outside the intended directory.
Before / after code snippet
Before (vulnerable)
// BEFORE (vulnerable)
const outputPath = path.join(outputDir, userFilename);
fs.writeFileSync(outputPath, pdfBuffer);
After (fixed)
// AFTER (fixed)
const safe = path.basename(userFilename);
const outputPath = path.join(outputDir, safe);
fs.writeFileSync(outputPath, pdfBuffer);
critical # race-condition Python CVE-2024-49768
TOCTOU Race in HTTP Pipelining
Waitress's pipelined request handler checks connection state before processing but re-reads it after — a race window lets an attacker smuggle a second request as the authenticated identity of the first.
Before / after code snippet
Before (vulnerable)
# BEFORE (vulnerable)
if self.request_count > 0:
    # ... time passes, state may change ...
    self.handle_request(request)  # uses stale identity
After (fixed)
# AFTER (fixed)
with self._lock:
    if self.request_count > 0:
        self.handle_request(request)
critical # rce JavaScript CVE-2024-21534
Sandbox Escape via unsafe vm.compile
jsonpath-plus passes attacker-controlled expressions to Node.js's vm module via a code path that bypasses the safe-eval flag — full sandbox escape to host process.
Before / after code snippet
Before (vulnerable)
// BEFORE (vulnerable)
const result = vm.runInNewContext(expr, sandbox);
After (fixed)
// AFTER (fixed)
// Validate expr against safe-path allowlist before eval.
if (!isSafeExpression(expr)) throw new Error('Unsafe expression');
const result = vm.runInNewContext(expr, sandbox);
Browse full case studies with diffs & analysis →
Install in 60 seconds — free for OSS. Watch PullLight flag bugs like these in your PRs.
Install on GitHub →