UsersAPI.edit() does not send payload, resulting in HTTP 415.

Open Beginner friendly
#1,058 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
1/5
Estimated time
Under an hour
Newbie friendliness
90/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
python
Domain
api

Research direction

Read tenable/io/users.py and inspect UsersAPI.edit(), where the issue identifies the payload construction and the PUT call that omits it. Check nearby tests for user editing and run the relevant test; done means the PUT receives the constructed payload and the edit operation no longer fails with HTTP 415.

Written by the indexing model from the issue text.

Description

Describe the bug
UsersAPI.edit() in pyTenable 26.10.1 builds the user update payload but does not pass the payload to the underlying PUT request.

As a result, attempting to edit a user in Tenable Vulnerability Management results in:

UnsupportedMediaTypeError: [415: PUT] https://cloud.tenable.com/users/<user_id>
body=b'{"error":"Unsupported Media Type"}'

The implementation is constructed immediately beforehand

return self._api.put(f'users/{scrub(user_id)}').json()

To Reproduce
Steps to reproduce the behavior:

  1. Initialize a TenableIO client:
from tenable.io import TenableIO

tio = TenableIO(
    access_key="...",
    secret_key="..."
)
  1. Attempt to update the name of an existing Tenable Vulnerability Management user:

user_id = 1234567

tio.users.edit(
user_id,
name="Firstname Lastname"
)

  1. The request fails with
UnsupportedMediaTypeError: [415: PUT] https://cloud.tenable.com/users/1234567
body=b'{"error":"Unsupported Media Type"}'
  1. Reviewing tenable/io/users.py shows that edit() constructs a payload:
user = self.details(self._check('user_id', user_id, int))
payload = dict_merge(
    {
        'permissions': user['permissions'],
        'enabled': user['enabled'],
        'email': user['email'],
        'name': user.get('name', None),
    },
    payload,
)

but does not pass it to the PUT request:

return self._api.put(f'users/{scrub(user_id)}').json()

The same operation succeeds when the payload is explicitly supplied to the underlying API client:

user = tio.users.details(user_id)

payload = {
    "permissions": user["permissions"],
    "enabled": user["enabled"],
    "email": user["email"],
    "name": "Firstname Lastname",
}

resp = tio.users._api.put(
    f"users/{user_id}",
    json=payload
)

resp.json()

Expected behavior
UsersAPI.edit() should pass the constructed payload to the PUT request and successfully update the specified user fields.

For example, the final request appears that it should be:

return self._api.put(
    f'users/{scrub(user_id)}',
    json=payload
).json()

Screenshots
N/A. Full exception and reproduction code provided above.

System Information (please complete the following information):

  • OS: Windows
  • Architecture: 64-bit
  • pyTenable Version: 26.10.1
  • Product: Tenable Vulnerability Management
  • Python Version: 3.14.6
  • Memory: N/A

Additional context
pyTenable 26.10.1 is the installed version:

import tenable
print(tenable.__version__)

Output

26.10.1

The issue can be worked around by calling:

tio.users._api.put(
    f"users/{user_id}",
    json=payload
)

with the same payload constructed by UsersAPI.edit(). This succeeds, which indicates the issue is specifically that UsersAPI.edit() constructs payload but does not provide it to _api.put().

Dominant language
Python
Stars
417
Forks
190
Avg merge
3d 22h
Merged PRs (30d)
7

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from tenable/pyTenable

All issues in tenable/pyTenable

Similar issues

More Python issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.