Skip to content

TenableOne.inventory.findings.list() silently ignores filters when query_text/query_mode are not provided #1016

Description

@mdfranz

Description

TenableOne.inventory.findings.list() sends an empty {} request body to /api/v1/t1/inventory/findings/search when only filters is passed (without query_text and query_mode). The result is the API returns unfiltered findings rather than raising an error or applying the filters.

Root cause

In tenable/tenableone/inventory/findings/api.py, the payload is only constructed when all three of query_text, query_mode, and filters are non-None simultaneously:

payload = {}

# TODO: check what is the actual contract
if query_text is not None and query_mode is not None and filters is not None:
    payload = {
        "query": {"text": query_text, "mode": query_mode.value},
        "filters": [...],
    }

Passing only filters falls through to payload = {}.

Steps to reproduce

from tenable.tenableone import TenableOne
from tenable.tenableone.inventory.schema import PropertyFilter, Operator

t1 = TenableOne(access_key="...", secret_key="...")

# Expectation: returns only ACTIVE findings
# Actual: returns all findings (filters silently ignored)
findings = t1.inventory.findings.list(
    filters=[
        PropertyFilter(property="state", operator=Operator.EQUAL, value=["ACTIVE"]),
    ]
)

Expected behaviour

Filters should be applied independently of query_text/query_mode. The API accepts a body of {"filters": [...]} without a query key and applies them correctly — the bug is purely in the client-side payload construction.

Verified via direct HTTP call:

[requests.post](http://requests.post/)(
    "https://cloud.tenable.com/api/v1/t1/inventory/findings/search?limit=5",
    json={"filters": [{"property": "state", "operator": "=", "value": ["ACTIVE"]}]}
)
# Returns filtered results correctly

Suggested fix

Build query and filters keys independently:

payload = {}
if query_text is not None and query_mode is not None:
    payload["query"] = {"text": query_text, "mode": query_mode.value}
if filters is not None:
    payload["filters"] = [f.model_dump(mode="json") for f in filters]

Environment

  • Test date: 2026-08-04
  • OS: macOS 26.5.2 (arm64, build 25F84)
  • Python: CPython 3.14.5
  • pytenable: 26.6.1, installed from PyPI by uv
  • Dependency lock: uv.lock pins pytenable to 26.6.1
  • Project constraint: pytenable>=26.6,<27
  • API base URL: https://cloud.tenable.com/
  • Authentication: TenableOne(access_key=..., secret_key=...); credentials omitted

The reproduction was checked against the installed pytenable 26.6.1
implementation. The installed distribution does not retain an upstream Git
commit, so latest main (post 2105ee5) is not independently reproducible from
this environment.

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