VYPR
High severityNVD Advisory· Published Mar 12, 2020· Updated Aug 4, 2024

CVE-2020-9543

CVE-2020-9543

Description

OpenStack Manila <7.4.1, >=8.0.0 <8.1.1, and >=9.0.0 <9.1.1 allows attackers to view, update, delete, or share resources that do not belong to them, because of a context-free lookup of a UUID. Attackers may also create resources, such as shared file systems and groups of shares on such share networks.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

CVE-2020-9543 allows unprivileged OpenStack Manila users to view, modify, or delete share networks not owned by them through a missing project-scope access control check.

Vulnerability

Description

CVE-2020-9543 is an access-control vulnerability in OpenStack Manila, the shared filesystem management service. The vulnerability arises because the share network API performs a context-free lookup by UUID, failing to verify that the requesting user's project ID matches the resource's project ID [1]. This flaw affects Manila versions prior to 7.4.1, 8.0.0 to 8.1.1, and 9.0.0 to 9.1.1 [4].

Attack

Vector and Exploitation

An attacker with a valid Manila API credential but no administrative privileges can exploit this by simply supplying the UUID of a share network belonging to another project. The API does not enforce project isolation on the lookup, so the attacker can retrieve, update, delete, or reuse the share network for their own resources [4]. The attacker does not need to be in the same tenant or have prior special access beyond a normal user token.

Impact

Successful exploitation enables an attacker to view and manipulate share network subnets, create share filesystems or share groups on a compromised share network, and potentially expose or disrupt services that depend on the shared storage backend [1][4]. This violates multi-tenant isolation guarantees and can lead to data exposure or unauthorized resource consumption.

Mitigation

The fix, implemented in commit 947315f0903c [3], enforces project-scoped access control on share network APIs. Administrators must upgrade to Manila 7.4.1, 8.1.1, or 9.1.1 [4]. No workaround exists that preserves full functionality, as the defect is in the core API logic.

AI Insight generated on May 21, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
manilaPyPI
< 7.4.17.4.1
manilaPyPI
>= 8.0.0, < 8.1.18.1.1
manilaPyPI
>= 9.0.0, < 9.1.19.1.1

Affected products

202

Patches

1
947315f0903c

share_networks: enable project_only API only

https://github.com/openstack/manilaMohammed NaserJan 31, 2020via ghsa
3 files changed · +65 10
  • manila/db/sqlalchemy/api.py+2 1 modified
    @@ -3398,7 +3398,8 @@ def _security_service_get_query(context, session=None):
     def _network_get_query(context, session=None):
         if session is None:
             session = get_session()
    -    return (model_query(context, models.ShareNetwork, session=session).
    +    return (model_query(context, models.ShareNetwork, session=session,
    +                        project_only=True).
                 options(joinedload('share_instances'),
                         joinedload('security_services'),
                         subqueryload('share_network_subnets')))
    
  • manila/tests/db/sqlalchemy/test_api.py+56 9 modified
    @@ -1981,7 +1981,7 @@ def test_create_two_networks_in_different_tenants(self):
             share_nw_dict2['project_id'] = 'fake project 2'
             result1 = db_api.share_network_create(self.fake_context,
                                                   self.share_nw_dict)
    -        result2 = db_api.share_network_create(self.fake_context,
    +        result2 = db_api.share_network_create(self.fake_context.elevated(),
                                                   share_nw_dict2)
     
             self._check_fields(expected=self.share_nw_dict, actual=result1)
    @@ -2014,6 +2014,33 @@ def test_get(self):
             self.assertEqual(0, len(result['share_instances']))
             self.assertEqual(0, len(result['security_services']))
     
    +    def _create_share_network_for_project(self, project_id):
    +        ctx = context.RequestContext(user_id='fake user',
    +                                     project_id=project_id,
    +                                     is_admin=False)
    +
    +        share_data = self.share_nw_dict.copy()
    +        share_data['project_id'] = project_id
    +
    +        db_api.share_network_create(ctx, share_data)
    +        return share_data
    +
    +    def test_get_other_tenant_as_admin(self):
    +        expected = self._create_share_network_for_project('fake project 2')
    +        result = db_api.share_network_get(self.fake_context.elevated(),
    +                                          self.share_nw_dict['id'])
    +
    +        self._check_fields(expected=expected, actual=result)
    +        self.assertEqual(0, len(result['share_instances']))
    +        self.assertEqual(0, len(result['security_services']))
    +
    +    def test_get_other_tenant(self):
    +        self._create_share_network_for_project('fake project 2')
    +        self.assertRaises(exception.ShareNetworkNotFound,
    +                          db_api.share_network_get,
    +                          self.fake_context,
    +                          self.share_nw_dict['id'])
    +
         @ddt.data([{'id': 'fake share id1'}],
                   [{'id': 'fake share id1'}, {'id': 'fake share id2'}],)
         def test_get_with_shares(self, shares):
    @@ -2129,24 +2156,29 @@ def test_get_all_one_record(self, records_count):
                 share_network_dict.update({'id': fake_id,
                                            'project_id': fake_id})
                 share_networks.append(share_network_dict)
    -            db_api.share_network_create(self.fake_context, share_network_dict)
    +            db_api.share_network_create(self.fake_context.elevated(),
    +                                        share_network_dict)
                 index += 1
     
    -        result = db_api.share_network_get_all(self.fake_context)
    +        result = db_api.share_network_get_all(self.fake_context.elevated())
     
             self.assertEqual(len(share_networks), len(result))
             for index, net in enumerate(share_networks):
                 self._check_fields(expected=net, actual=result[index])
     
         def test_get_all_by_project(self):
    +        db_api.share_network_create(self.fake_context, self.share_nw_dict)
    +
             share_nw_dict2 = dict(self.share_nw_dict)
             share_nw_dict2['id'] = 'fake share nw id2'
             share_nw_dict2['project_id'] = 'fake project 2'
    -        db_api.share_network_create(self.fake_context, self.share_nw_dict)
    -        db_api.share_network_create(self.fake_context, share_nw_dict2)
    +        new_context = context.RequestContext(user_id='fake user 2',
    +                                             project_id='fake project 2',
    +                                             is_admin=False)
    +        db_api.share_network_create(new_context, share_nw_dict2)
     
             result = db_api.share_network_get_all_by_project(
    -            self.fake_context,
    +            self.fake_context.elevated(),
                 share_nw_dict2['project_id'])
     
             self.assertEqual(1, len(result))
    @@ -2415,9 +2447,24 @@ def test_update_not_found(self):
                               self.subnet_dict['id'],
                               {})
     
    -    @ddt.data([{'id': 'sn_id1', 'project_id': 'fake', 'user_id': 'fake'}],
    -              [{'id': 'fake_id', 'project_id': 'fake', 'user_id': 'fake'},
    -               {'id': 'sn_id2', 'project_id': 'fake', 'user_id': 'fake'}])
    +    @ddt.data([
    +        {
    +            'id': 'sn_id1',
    +            'project_id': 'fake project',
    +            'user_id': 'fake'
    +        }
    +    ], [
    +        {
    +            'id': 'fake_id',
    +            'project_id': 'fake project',
    +            'user_id': 'fake'
    +        },
    +        {
    +            'id': 'sn_id2',
    +            'project_id': 'fake project',
    +            'user_id': 'fake'
    +        }
    +    ])
         def test_get_all_by_share_network(self, share_networks):
     
             for idx, share_network in enumerate(share_networks):
    
  • releasenotes/notes/bug-1861485-fix-share-network-retrieval-31768dcda5aeeaaa.yaml+7 0 added
    @@ -0,0 +1,7 @@
    +---
    +security:
    +  - |
    +    CVE-2020-9543: An issue with share network retrieval has been addressed
    +    in the API by scoping unprivileged access to project only. Please see
    +    `launchpad bug #1861485 <https://bugs.launchpad
    +    .net/manila/+bug/1861485>`_ for more details.
    

Vulnerability mechanics

Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

8

News mentions

0

No linked articles in our index yet.