Skip to content

Bug: exports.vulns(cve_id=...) rejects the PHP2Shell CVEs, blocking vulnerability exports filtered by CVE #1050

Open

Description

@lanz

Describe the bug

Vulnerability exports can't be filtered by the PHP2Shell CVEs, CVE-2026-109618 and CVE-2026-109619, through pyTenable. tio.exports.vulns(cve_id=[...]) raises a pydantic ValidationError before any request is sent:

cve_id.0
  String should match pattern '^CVE-\d{4}-\d{1,5}$' [type=string_pattern_mismatch, input_value='CVE-2026-109618', input_type=str]

The CVEId pattern in tenable/io/exports/models.py allows only one to five digits after the year. CVE sequence numbers have had four or more digits, with no upper limit, since the 2014 CVE ID syntax change, and six- and seven-digit IDs are now common. As a result:

  • Valid IDs are rejected: every CVE with a sequence number of six or more digits, including both PHP2Shell CVEs and Node2Shell (CVE-2026-111497).
  • Invalid IDs are accepted: IDs with one to three digits, such as CVE-2024-123, pass validation, and the API then rejects them with 400 BAD_REQUEST_INVALID_VALUE.

exports.vulns() has no way around the validation, so pyTenable users can't export PHP2Shell findings by CVE.

To Reproduce

Runs offline; nothing is sent to the API:

from tenable.io import TenableIO

tio = TenableIO(url='https://cloud.example.invalid', access_key='a' * 64, secret_key='b' * 64)
tio.exports.vulns(cve_id=['CVE-2026-109618', 'CVE-2026-109619'], iterator=None)
# pydantic_core.ValidationError: String should match pattern '^CVE-\d{4}-\d{1,5}$'

Expected behavior

The export request is sent with {"filters": {"cve_id": ["CVE-2026-109618", "CVE-2026-109619"], ...}}. The API accepts these IDs: a direct POST /vulns/export with them finishes and echoes the filter in the export status.

IDs that aren't valid CVE IDs, such as CVE-2024-123, should still be rejected locally.

Workaround

Send the export request directly. This skips pyTenable's validation:

resp = tio.post('vulns/export', json={'num_assets': 500, 'filters': {
    'cve_id': ['CVE-2026-109618', 'CVE-2026-109619']}})

Then poll vulns/export/{export_uuid}/status and download each chunk listed in chunks_available.

System Information:

  • OS: any
  • Architecture: any
  • Version: pyTenable 26.10.1 (and every earlier release with this pattern)

Additional context

The API's own validation accepts sequence numbers of four to seven digits, and rejects shorter or longer ones with 400 BAD_REQUEST_INVALID_VALUE. It also accepts lowercase IDs but matches no findings with them, so pyTenable's existing uppercase requirement is useful and should stay.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions