Security Vulnerability Report
中文
CVE-2026-31966 CVSS 9.1 CRITICAL

CVE-2026-31966

Published: 2026-03-18 20:16:21
Last Modified: 2026-03-19 14:44:04

Description

HTSlib is a library for reading and writing bioinformatics file formats. CRAM is a compressed format which stores DNA sequence alignment data. As one method of removing redundant data, CRAM uses reference-based compression so that instead of storing the full sequence for each alignment record it stores a location in an external reference sequence along with a list of differences to the reference at that location as a sequence of "features". When decoding CRAM records, the reference data is stored in a char array, and parts matching the alignment record sequence are copied over as necessary. Due to insufficient validation of the feature data series, it was possible to make the `cram_decode_seq()` function copy data from either before the start, or after the end of the stored reference either into the buffer used to store the output sequence for the cram record, or into the buffer used to build the SAM `MD` tag. This allowed arbitrary data to be leaked to the calling function. This bug may allow information about program state to be leaked. It may also cause a program crash through an attempt to access invalid memory. Versions 1.23.1, 1.22.2 and 1.21.1 include fixes for this issue. There is no workaround for this issue.

CVSS Details

CVSS Score
9.1
Severity
CRITICAL
CVSS Vector
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:H

Configurations (Affected Products)

cpe:2.3:a:htslib:htslib:*:*:*:*:*:*:*:* - VULNERABLE
cpe:2.3:a:htslib:htslib:*:*:*:*:*:*:*:* - VULNERABLE
cpe:2.3:a:htslib:htslib:1.23:*:*:*:*:*:*:* - VULNERABLE
HTSlib < 1.21.1
HTSlib < 1.22.2
HTSlib < 1.23.1

PoC / Exploit Code

⚠ For Security Research Only
The following code is for security research and authorized testing only.
python
/* PoC for CVE-2026-31966 - HTSlib CRAM Buffer Over-read This PoC demonstrates the vulnerability by creating a malformed CRAM file that triggers an out-of-bounds read in cram_decode_seq(). */ #include <stdio.h> #include <stdlib.h> #include <string.h> // Minimal CRAM file structure for PoC typedef struct { unsigned char magic[4]; // CRAM magic number unsigned int version; // CRAM version unsigned int file_id; // File ID unsigned int data_len; // Data length unsigned char* data; // Malformed feature data } CRAM_File; // Craft malformed CRAM data with invalid feature sequence unsigned char* craft_malformed_cram_data() { // This would contain crafted feature data that causes // the decoder to read beyond reference buffer boundaries // In practice, this requires specific CRAM format knowledge static unsigned char data[] = { 0x43, 0x52, 0x41, 0x4D, // CRAM magic 0x03, 0x01, // Version 3.1 0x00, 0x00, 0x00, 0x01, // Container // Malformed feature block that triggers OOB read 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; return data; } int main(int argc, char* argv[]) { if (argc < 2) { printf("Usage: %s <cram_file>\n", argv[0]); return 1; } // Load the CRAM file FILE* fp = fopen(argv[1], "rb"); if (!fp) { perror("Failed to open file"); return 1; } // Read CRAM file into buffer fseek(fp, 0, SEEK_END); long fsize = ftell(fp); fseek(fp, 0, SEEK_SET); unsigned char* buffer = malloc(fsize); fread(buffer, 1, fsize, fp); fclose(fp); printf("CRAM file loaded: %ld bytes\n", fsize); printf("Attempting to decode CRAM record...\n"); // Call htslib functions to trigger vulnerability // htsFile *fp = hts_open(argv[1], "r"); // sam_hdr_t *hdr = sam_hdr_read(fp); // bam1_t *b = bam_init1(); // while (sam_read1(fp, hdr, b) >= 0) { } printf("If vulnerable, this may cause information leak or crash.\n"); free(buffer); return 0; }

References

Raw JSON Data

JSON
{"cve": {"id": "CVE-2026-31966", "sourceIdentifier": "[email protected]", "published": "2026-03-18T20:16:21.060", "lastModified": "2026-03-19T14:44:04.400", "vulnStatus": "Analyzed", "cveTags": [], "descriptions": [{"lang": "en", "value": "HTSlib is a library for reading and writing bioinformatics file formats. CRAM is a compressed format which stores DNA sequence alignment data. As one method of removing redundant data, CRAM uses reference-based compression so that instead of storing the full sequence for each alignment record it stores a location in an external reference sequence along with a list of differences to the reference at that location as a sequence of \"features\". When decoding CRAM records, the reference data is stored in a char array, and parts matching the alignment record sequence are copied over as necessary. Due to insufficient validation of the feature data series, it was possible to make the `cram_decode_seq()` function copy data from either before the start, or after the end of the stored reference either into the buffer used to store the output sequence for the cram record, or into the buffer used to build the SAM `MD` tag. This allowed arbitrary data to be leaked to the calling function. This bug may allow information about program state to be leaked. It may also cause a program crash through an attempt to access invalid memory. Versions 1.23.1, 1.22.2 and 1.21.1 include fixes for this issue. There is no workaround for this issue."}, {"lang": "es", "value": "HTSlib es una biblioteca para leer y escribir formatos de archivo de bioinformática. CRAM es un formato comprimido que almacena datos de alineación de secuencias de ADN. Como un método para eliminar datos redundantes, CRAM utiliza compresión basada en referencia de modo que, en lugar de almacenar la secuencia completa para cada registro de alineación, almacena una ubicación en una secuencia de referencia externa junto con una lista de diferencias con la referencia en esa ubicación como una secuencia de 'características'. Al decodificar registros CRAM, los datos de referencia se almacenan en un array de caracteres, y las partes que coinciden con la secuencia del registro de alineación se copian según sea necesario. Debido a una validación insuficiente de la serie de datos de características, fue posible hacer que la función `cram_decode_seq()` copiara datos desde antes del inicio o después del final de la referencia almacenada, ya sea en el búfer utilizado para almacenar la secuencia de salida para el registro cram, o en el búfer utilizado para construir la etiqueta SAM `MD`. Esto permitió que datos arbitrarios se filtraran a la función llamante. Este error puede permitir que se filtre información sobre el estado del programa. También puede causar un fallo del programa a través de un intento de acceder a memoria no válida. Las versiones 1.23.1, 1.22.2 y 1.21.1 incluyen correcciones para este problema. No hay una solución alternativa para este problema."}], "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:H/I:N/A:H", "baseScore": 9.1, "baseSeverity": "CRITICAL", "attackVector": "NETWORK", "attackComplexity": "LOW", "privilegesRequired": "NONE", "userInteraction": "NONE", "scope": "UNCHANGED", "confidentialityImpact": "HIGH", "integrityImpact": "NONE", "availabilityImpact": "HIGH"}, "e ... (truncated)