Skip to content

VNX-1322: Use of Blocking Code in Single-threaded, Non-blocking Context

Reports synchronous Node.js APIs (fs.*Sync, execSync/spawnSync, pbkdf2Sync/scryptSync, zlib *Sync, bcrypt hashSync/compareSync) called inside an HTTP request handler, where they stall the event loop for every client. Startup code, helpers outside handlers, async APIs, scripts and tests are not reported.

Updated 02 Nov 2026Checked against cli@de9b52a
Field Value
Rule ID VNX-1322
Severity Medium
SARIF level warning
Kind sast
Languages JavaScript / TypeScript
CWE CWE-1322
CAPEC CAPEC-66
ATT&CK T1190
CWSS vector CWSS:1.0/TI:M/AP:RU/AL:S/IC:N/FC:LT/RP:RU/RL:S/AV:L/AS:N/IN:A/SC:A/BI:M/DI:H/EX:M/EC:N/P:C
Tags blocking-in-non-blocking event-loop dos cwe-1322
Source internal/sast/rules/vnx-1322.rego

Overview

VNX-1322 maps to CWE-1322: Use of Blocking Code in Single-threaded, Non-blocking Context. A Node.js server runs every request on one thread. A synchronous file, process, key-derivation or compression call inside a request handler stops that thread until it returns, so every other client waits.

Why This Matters

A single slow disk read or child process inside a handler turns into server-wide latency, and an attacker who can trigger the call repeatedly (a large file, an expensive pbkdf2Sync) can deny service to everyone with a handful of requests.

What Gets Flagged

The rule looks for a sync API inside a function whose parameters are (req, res), (request, reply), (request, response), (request, h) or a Koa ctx, including http.createServer callbacks and TypeScript-typed parameters.

router.get('/docs/:name', (req, res) => {
  const body = fs.readFileSync(file, 'utf8')            // FLAGGED
  res.send(body)
})

this.handleLogin = function(req, res, next) {
  var key = crypto.pbkdf2Sync(req.body.password, salt, 210000, 64, "sha512")  // FLAGGED
}

convert.post('/convert', async (req: Request, res: Response) => {
  const out = execSync(`soffice --convert-to pdf ${input}`)  // FLAGGED
})

What Is Not Flagged

  • Sync calls at module level or in a helper outside any handler (loading certificates or config at startup, warming a cache).
  • fs.promises.*, callback-style fs.readFile, execFile with a callback.
  • Build scripts and CLIs, test files, comments and string literals.
  • A sync call reached from a handler through a helper function defined elsewhere is not followed.

Remediation

  1. Use the asynchronous form: await fs.promises.readFile(...), execFile(..., cb) or util.promisify(exec), crypto.pbkdf2(..., cb), zlib.gzip(..., cb), bcrypt.compare(...).
  2. Move unavoidable synchronous work to startup, or to a worker thread.

References

Suppressing this rule

Put a nosec comment on the line, or on line 1 to cover the whole file. Use the comment marker of the file’s language (#, //, -- or ;):

# nosec vnx-1322
// nosec vnx-1322

Or record an ignore rule: vulnetix ignore add --rule vnx-1322 --reason "...". See Suppressing findings.

Edit this pageSources: cli/internal/sast/rules/vnx-1322.rego, cli/internal/sast/docs/vnx-1322.md
esc
↑ ↓ move↵ openSearches in your browser. A key like autonomy.max or a code like threshold_required jumps straight to it.