Skip to content

PluginMenuItem and PluginMenuButton Share Mutable State Between Instances #20239

@jnovinger

Description

@jnovinger

Deployment Type

Self-hosted

NetBox Version

v4.4.0

Python Version

3.10

Steps to Reproduce

  1. Create two PluginMenuItem instances without explicit permissions parameter
  2. Modify the permissions of the first instance
  3. Check the permissions of the second instance
from unittest import TestCase
from netbox.plugins.navigation import PluginMenuItem

class TestPluginNavigationBug(TestCase):
    def test_shared_mutable_state_bug(self):
        """
        Test that PluginMenuItem instances share mutable class attributes,
        causing permission leakage between instances.
        """
        # Clean slate
        PluginMenuItem.permissions.clear()

        # Create instance without explicit permissions (uses class default)
        item1 = PluginMenuItem(link='test1', link_text='Test 1')

        # Modify permissions through this instance
        item1.permissions.append('leaked_permission')

        # Create second instance - should have clean permissions but doesn't
        item2 = PluginMenuItem(link='test2', link_text='Test 2')

        # SECURITY ASSERTIONS: These fail when vulnerability exists
        self.assertIsNot(item1.permissions, item2.permissions,
                        "VULNERABILITY: Instances share same permission object")

        # Clean up
        PluginMenuItem.permissions.clear()

Note: While not demonstrated, PluginMenuButton has the same behavior and also needs to be fixed.

Expected Behavior

Each PluginMenuItem instance should have its own independent permissions list. When item1.permissions is modified, item2.permissions should remain empty ([]).

Observed Behavior

Both PluginMenuItem instances share the same permissions list object. Modifying permissions on one instance affects all other instances that don't have explicit permissions parameters.

Metadata

Metadata

Assignees

Labels

netboxseverity: lowDoes not significantly disrupt application functionality, or a workaround is availablestatus: acceptedThis issue has been accepted for implementationtype: bugA confirmed report of unexpected behavior in the application

Type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions