How Debian OVAL content is structured

Hello everyone! As we saw in the last episode, the results of vulnerability detection for one host produced by two different APIs can vary greatly. Therefore, in order to find out the truth, it is necessary to understand what vulnerability data is provided by the Linux distribution vendor and how this data is structured.

Alternative video link (for Russia):

Why is it important to do this? Because using data from a Linux distribution vendor, we can ask vulnerability detection API vendors questions: why are you detecting in a different way than described in this data? And then we will understand what caused the difference. And we will either adjust the API for vulnerability detection, or we will adjust the content of the Linux distribution vendor. Either way, it will be a success! In any case, the transparency of the vulnerability detection process will increase.

Last time we looked at vulnerabilities for Debian host and Debian Docker base image. So let’s continue with Debian. In particular, with the official Debian OVAL (Open Vulnerability and Assessment Language) content.

Debian OVAL content can be downloaded from the website. For Debian 11.6 it will be (~48M).


I took the very first definition as an example:

    <definition id="oval:org.debian:def:302398480618719661759273474285073383836" version="1" class="vulnerability">
        <title>CVE-1999-0199 glibc</title>
        <affected family="unix">
          <platform>Debian GNU/Linux 11</platform>
        <reference source="CVE" ref_id="CVE-1999-0199" ref_url=""/>
        <description>manual/search.texi in the GNU C Library (aka glibc) before 2.2 lacks a statement about the unspecified tdelete return value upon deletion of a tree's root, which might allow attackers to access a dangling pointer in an application whose developer was unaware of a documentation update from 1999.</description>
      <criteria comment="Release section" operator="AND">
        <criterion test_ref="oval:org.debian.oval:tst:1" comment="Debian 11 is installed"/>
        <criteria comment="Architecture section" operator="OR">
          <criteria comment="Architecture independent section" operator="AND">
            <criterion test_ref="oval:org.debian.oval:tst:2" comment="all architecture"/>
            <criterion test_ref="oval:org.debian.oval:tst:3" comment="glibc DPKG is earlier than 2.2-1"/>

As we can see here, Debian OVAL content is organized by CVE IDs and software packages. This is not typical. Typically, OVAL providers organize it by Bulletin IDs. Here we don’t see any Bulletin IDs (DSA or DLA) at all (Upd. Nope, my fault, there are DSAs for some definitions!). The DSA Security Bulletin can be found in crossreferences page. The DLA Security Bulletin can be found in debian-lts-announce (but it’s much more complicated). However, it would be much better if Bulletin IDs were just in the OVAL content in reference tags. It seems right to ask the Debian security team about this.

Upd. 11.01.2023 Actually I was wrong, there are DSAs for some definitions (1935 DSA IDs) !

<definition id="oval:org.debian:def:218814361374511235945907500140142528432" version="1" class="vulnerability">
        <title>CVE-2016-2124 samba</title>
        <affected family="unix">
          <platform>Debian GNU/Linux 11</platform>
        <reference source="CVE" ref_id="CVE-2016-2124" ref_url="">
        <description>security update</description>
          <moreinfo>Several vulnerabilities have been discovered in Samba, a SMB/CIFS file, print, and login server for Unix.</moreinfo>
      <criteria comment="Release section" operator="AND">
        <criterion test_ref="oval:org.debian.oval:tst:1" comment="Debian 11 is installed">
        <criteria comment="Architecture section" operator="OR">
          <criteria comment="Architecture independent section" operator="AND">
            <criterion test_ref="oval:org.debian.oval:tst:2" comment="all architecture">
            <criterion test_ref="oval:org.debian.oval:tst:9090" comment="samba DPKG is earlier than 2:4.13.13+dfsg-1~deb11u2">

The detection logic is quite simple. In fact, in each defenition, there is a:

  • Debian release test
  • Architecture test
  • Package version test (for one package only)

Let’s take a closer look at these tests.

oval:org.debian.oval:tst:1 Debian 11 is installed

This test checks that the major version in /etc/debian_version is 11:

vmuser@debian1:~$ cat /etc/debian_version 

textfilecontent54_test is a test for a text file:

    <textfilecontent54_test id="oval:org.debian.oval:tst:1" version="1" check="all" check_existence="at_least_one_exists" comment="Debian GNU/Linux 11 is installed" xmlns="">
      <object object_ref="oval:org.debian.oval:obj:1"/>
      <state state_ref="oval:org.debian.oval:ste:1"/>

textfilecontent54_object contains the path to the file and a regular expression to search for:

<textfilecontent54_object id="oval:org.debian.oval:obj:1" version="1" xmlns="">
  <pattern operation="pattern match">(\d+)\.\d</pattern>
  <instance datatype="int">1</instance>

textfilecontent54_state contains the number 11:

    <textfilecontent54_state id="oval:org.debian.oval:ste:1" version="1" xmlns="">
      <subexpression operation="equals">11</subexpression>

In fact, this is an unnecessary check, since oval-definitions-bullseye.xml only contains checks for Debian 11. All definitions in this file use the same distribution version test, checking the same state.

$ cat oval-definitions-bullseye.xml | grep "textfilecontent54_state"
    <textfilecontent54_state id="oval:org.debian.oval:ste:1" version="1" xmlns="">

oval:org.debian.oval:tst:2 all architecture

uname_test should check the architecture of the processor using the uname data.
But in this particular test, there is uname_object but no uname_state.

<uname_test id="oval:org.debian.oval:tst:2" version="1" check="all" check_existence="at_least_one_exists" comment="Installed architecture is all" xmlns="">
      <object object_ref="oval:org.debian.oval:obj:2"/>

So, in fact, the architecture is not checked:

<uname_object id="oval:org.debian.oval:obj:2" version="1" xmlns=""/>

This is true for all definitions:

cat oval-definitions-bullseye.xml | grep "uname_test"
    <uname_test id="oval:org.debian.oval:tst:2" version="1" check="all" check_existence="at_least_one_exists" comment="Installed architecture is all" xmlns="">

It is important. According to the official Debian OVAL content, architecture DOES NOT affect vulnerability detection. Whether this is a bug in the OVAL content or is this the correct logic we will need to understand further. But it makes sense to address the question to the Debian Security Team.

oval:org.debian.oval:tst:3 glibc DPKG is earlier than 2.2-1

Finally, let’s look at dpkginfo_test for detecting a vulnerable version:

    <dpkginfo_test id="oval:org.debian.oval:tst:3" version="1" check="all" check_existence="at_least_one_exists" comment="glibc is earlier than 2.2-1" xmlns="">
      <object object_ref="oval:org.debian.oval:obj:3"/>
      <state state_ref="oval:org.debian.oval:ste:2"/>

dpkginfo_object contains the package name:

<dpkginfo_object id="oval:org.debian.oval:obj:3" version="1" xmlns="">

dpkginfo_state contains the patched version:

    <dpkginfo_state id="oval:org.debian.oval:ste:2" version="1" xmlns="">
      <evr datatype="debian_evr_string" operation="less than">0:2.2-1</evr>

The version is the same as in the output of dpkg –list (well, you need to add the zero epoch as well):

$ dpkg --list 
ii  base-files                    11.1+deb11u4                   amd64        Debian base system miscellaneous files
ii  base-passwd                   3.5.51                         amd64        Debian base system master password and group files
ii  bash                          5.1-2+deb11u1                  amd64        GNU Bourne Again SHell
ii  bash-completion               1:2.11-2                       all          programmable completion for the bash shell
ii  bind9-dnsutils                1:9.16.27-1~deb11u1            amd64        Clients provided with BIND 9

In conclusion

As you can see, the information related to vulnerability detection (in this OVAL content) can be simplified to a combination of CVE_Number (CVE ID), Distribution_Version, Package_Name and Package_Version:

CVE-1999-0199|Debian 11|glibc|0:2.2-1

Upd. 11.01.2023 There are DSAs for some definitions, so it’s better to use combination of Bulletin, CVE_Number (CVE ID), Distribution_Version, Package_Name and Package_Version

And in the future it is possible to try to write a converter from OVAL to this simplified format and try to detect vulnerabilities with it.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.