Microsoft has added CVE-2026-41256 to its Security Update Guide, bringing attention to a subtle but significant vulnerability in the popular JSON processing tool jq. The issue, published in May 2026 with a moderate severity rating, lies in how jq handles filter programs loaded with the -f flag. When a filter file contains an embedded NUL byte (\0), jq silently truncates the content at that point, potentially leading to incomplete filter execution. For Windows developers and DevOps engineers who rely on jq for automating JSON manipulation in CI/CD pipelines, this bug can open the door to supply chain attacks, logic bypasses, and unexpected automation outcomes.

Understanding jq and the -f flag

jq is a lightweight, cross-platform command-line processor that slices, filters, and transforms JSON data. It has become an indispensable tool in scripting, configuration management, and continuous integration workflows. The -f option tells jq to read a filter expression from a file rather than inline from the command line. This feature is especially handy when filters grow complex or need to be shared across multiple scripts and pipeline stages. For example, a typical Azure DevOps or GitHub Actions workflow might call jq -f filter.jq data.json to extract deployment versions or transform webhook payloads.

The convenience of -f comes with an implicit trust model: the filter file content is assumed to be safe and complete. In many CI/CD setups, those filter files live in version-controlled repositories, often alongside application code. An attacker who can manipulate that repository—via a malicious pull request, for instance—could tamper with the filter file without raising immediate red flags, especially if the change is hidden by a NUL byte.

The NUL byte truncation vulnerability

At the heart of CVE-2026-41256 is a classic C-style string handling issue. Many programs, including jq, are written in C or a similar language where a NUL byte (character code 0) traditionally marks the end of a string. When jq reads the contents of a filter file for the -f option, it treats the file as a null-terminated string, stopping as soon as it encounters the first NUL byte. Consequently, any filter logic beyond that byte is silently ignored. The program does not issue a warning or error; it simply executes a truncated filter, often leading the user to believe the entire file was processed.

This behaviour becomes dangerous when the invisible truncation changes the intended logic. Consider a filter designed to extract only safe production configurations while excluding sensitive staging parameters:

# filter.jq
select(.env == "production") | .service

If an attacker embeds a NUL byte just before the final line, the effective filter becomes merely select(.env == "production"), omitting the projection that restricts output to .service. The pipeline would then emit the entire production entry, perhaps exposing internal secrets that the .service selector was meant to hide. Alternatively, if the NUL byte is placed at the very beginning, the filter becomes empty, causing jq to output the entire raw JSON input—a disastrous information leak if that input contains credentials or private IP addresses.

CI/CD pipelines at risk

Modern CI/CD systems rely heavily on jq for tasks like parsing API responses, modifying Docker Compose files, and validating deployment manifests. A compromised filter file can undermine the integrity of an entire release pipeline. An attacker who manages to insert a NUL byte into a filter.jq inside a shared repository could achieve several malicious outcomes:

  • Logic bypass: A security validation filter (select(.allow_deploy == true)) can be truncated to a no-op, letting unapproved code sail through.
  • Information disclosure: Truncated projections can spill entire JSON structures instead of intended fields, dumping secrets into build logs.
  • Denial of service: An empty filter may produce enormous output, filling log storage or breaking downstream steps that expect a specific structure.
  • Supply chain poisoning: If the filter is used to extract artifact URLs, a truncated expression might pick up attacker-controlled metadata, redirecting downloads to malicious packages.

The vulnerability is particularly acute in Windows environments where jq is often deployed alongside PowerShell automation. Tools like GitHub Actions, Azure Pipelines, and local development scripts all execute jq under the hood, and developers rarely inspect binary file content for NUL bytes. Because the truncation is silent, a compromised filter file can persist for weeks without detection.

Why Microsoft’s Security Update Guide includes this CVE

jq is not a Microsoft product, but the software giant frequently highlights vulnerabilities in widely used open-source tools that impact its ecosystem. Windows users can install jq via winget, Chocolatey, or as part of the Windows Subsystem for Linux (WSL). Furthermore, Microsoft’s own cloud services and documentation often feature jq in sample pipelines and automation guides. By listing CVE-2026-41256, Microsoft aims to alert administrators and developers who might be running vulnerable versions on Windows Server, Azure DevOps agents, or developer workstations. The inclusion underscores the cross-platform nature of this risk and encourages prompt remediation.

Users should immediately upgrade to a version of jq that addresses CVE-2026-41256. The jq maintainers have released a patch that either rejects filter files with embedded NUL bytes or provides a clear warning while still safely processing the content after the NUL. Exactly which mitigation strategy was adopted can be found in the release notes for the fixed version. Windows users can update via their package manager of choice:

# Using winget
winget upgrade jqlang.jq

Using Chocolatey

choco upgrade jq

If an immediate upgrade isn’t possible, several workarounds can reduce risk:

  • Avoid the -f flag where practical: Inline filters using -jq 'expression' are not subject to this bug.
  • Validate filter files before use: Scan files for NUL bytes with a simple command like findstr /v /r "^$" filter.jq or a dedicated binary checker.
  • Lock down repository access: Use branch protection rules and mandatory code reviews to prevent unauthorized changes to filter files.
  • Log filter contents in debug mode: Enable pipeline debug output to capture the exact filter string being executed, making truncation visible.

Community response and broader implications

The disclosure has sparked discussions in DevOps circles about the general dangers of using file-based input for security-sensitive tools. Many argue that jq’s behaviour is a design flaw stemming from its C heritage, and that similar vulnerabilities may lurk in other command-line utilities that handle binary data. The incident serves as a reminder that supply chain security extends beyond package dependencies to the very scripts and filters that orchestrate builds. In Windows shops, where jq often runs alongside PowerShell and .NET tools, defenders should audit all automation scripts for potential NUL byte injection points.

Looking ahead

CVE-2026-41256 is a moderate-severity bug on its own, but in the interconnected web of CI/CD automation, moderate issues can quickly escalate to high-impact breaches. The fix is straightforward, but the real challenge lies in ensuring all pipeline components are patched and that development practices are adjusted to treat filter files as untrusted input. For Windows users, staying current with Microsoft’s Security Update Guide—even for non-Microsoft products—is a necessary layer of defence in an increasingly automated world.

As the DevOps mantra goes, trust but verify. Now, that verification must include checking for NUL bytes hidden in plain sight.