Action buttons show up for users that have restricted permissions but no permissions for that specific object #24

Closed
opened 2026-04-05 16:21:14 +02:00 by MrUnknownDE · 0 comments
Owner

Originally created by @fabi125 on 4/1/2026

NetBox Edition

NetBox Community

NetBox Version

v4.5.6

Python Version

3.12

Steps to Reproduce

On https://demo.netbox.dev/:

  1. Create a new user partial_device_edit.
  2. Create a new permission device_view that grants "Can view" on Device to partial_device_edit.
  3. Create a new permission device_edit that grants "Can add", "Can change" and "Can delete" on Device with the constraints {"site__name": "DM-Akron"} to partial_device_edit.
  4. Open up a device that is NOT in DM-Akron, e.g. https://demo.netbox.dev/dcim/devices/15/

Expected Behavior

No edit or delete button is displayed on the object view page.

Observed Behavior

Both Edit and Delete buttons are displayed, but clicking them results in a 404.

The bug seems to live in get_permitted_actions:

b73f7f7d00/netbox/netbox/views/generic/mixins.py (L53-L72)

After get_permission_for_model is used to get the required permission (e.g. dcim.change_device) it is passed without the object to user.has_perms, which seems to return True if the user has that permission regardless of additional constraints. Updating it to pass the object if available seems to fix the issue:

diff --git a/netbox/netbox/views/generic/mixins.py b/netbox/netbox/views/generic/mixins.py
index 6e40e4175..544c70e2a 100644
--- a/netbox/netbox/views/generic/mixins.py
+++ b/netbox/netbox/views/generic/mixins.py
@@ -1,3 +1,5 @@
+import inspect
+
 from django.shortcuts import get_object_or_404
 
 from extras.models import TableConfig
@@ -66,8 +68,16 @@ class ActionsMixin:
             required_permissions = [
                 get_permission_for_model(model, perm) for perm in action.permissions_required
             ]
-            if not required_permissions or user.has_perms(required_permissions):
-                permitted_actions.append(action)
+            # If we have a specific object, check permissions against the object.
+            if (
+                not required_permissions
+                or (inspect.isclass(model) and user.has_perms(required_permissions))
+                or (
+                    not inspect.isclass(model)
+                    and user.has_perms(required_permissions, model)
+                )
+            ):
+                 permitted_actions.append(action)
 
         return permitted_actions

If the maintainers agree that this is the right fix or have other ideas on how to fix it, I'd be happy to put up a PR for this.

*Originally created by @fabi125 on 4/1/2026* ### NetBox Edition NetBox Community ### NetBox Version v4.5.6 ### Python Version 3.12 ### Steps to Reproduce On https://demo.netbox.dev/: 1. Create a new user `partial_device_edit`. 2. Create a new permission `device_view` that grants "Can view" on Device to `partial_device_edit`. 3. Create a new permission `device_edit` that grants "Can add", "Can change" and "Can delete" on Device with the constraints `{"site__name": "DM-Akron"}` to `partial_device_edit`. 4. Open up a device that is NOT in DM-Akron, e.g. https://demo.netbox.dev/dcim/devices/15/ ### Expected Behavior No edit or delete button is displayed on the object view page. ### Observed Behavior Both Edit and Delete buttons are displayed, but clicking them results in a 404. The bug seems to live in `get_permitted_actions`: https://github.com/netbox-community/netbox/blob/b73f7f7d00dcb75c33161d659c30f53f7101fe49/netbox/netbox/views/generic/mixins.py#L53-L72 After `get_permission_for_model` is used to get the required permission (e.g. `dcim.change_device`) it is passed without the object to `user.has_perms`, which seems to return `True` if the user has that permission regardless of additional constraints. Updating it to pass the object if available seems to fix the issue: ```diff diff --git a/netbox/netbox/views/generic/mixins.py b/netbox/netbox/views/generic/mixins.py index 6e40e4175..544c70e2a 100644 --- a/netbox/netbox/views/generic/mixins.py +++ b/netbox/netbox/views/generic/mixins.py @@ -1,3 +1,5 @@ +import inspect + from django.shortcuts import get_object_or_404 from extras.models import TableConfig @@ -66,8 +68,16 @@ class ActionsMixin: required_permissions = [ get_permission_for_model(model, perm) for perm in action.permissions_required ] - if not required_permissions or user.has_perms(required_permissions): - permitted_actions.append(action) + # If we have a specific object, check permissions against the object. + if ( + not required_permissions + or (inspect.isclass(model) and user.has_perms(required_permissions)) + or ( + not inspect.isclass(model) + and user.has_perms(required_permissions, model) + ) + ): + permitted_actions.append(action) return permitted_actions ``` If the maintainers agree that this is the right fix or have other ideas on how to fix it, I'd be happy to put up a PR for this.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github/netbox#24