VYPR
Moderate severityNVD Advisory· Published Jan 7, 2014· Updated Apr 29, 2026

CVE-2013-6419

CVE-2013-6419

Description

Interaction error in OpenStack Nova and Neutron before Havana 2013.2.1 and icehouse-1 does not validate the instance ID of the tenant making a request, which allows remote tenants to obtain sensitive metadata by spoofing the device ID that is bound to a port, which is not properly handled by (1) api/metadata/handler.py in Nova and (2) the neutron-metadata-agent (agent/metadata/agent.py) in Neutron.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
novaPyPI
< 12.0.0a012.0.0a0

Affected products

1
  • cpe:2.3:a:openstack:havana:*:*:*:*:*:*:*:*
    Range: <=havana-1

Patches

3
af2f82310701

Prevent spoofing instance_id from neutron to nova

https://github.com/openstack/novaAaron RosenOct 7, 2013via ghsa
2 files changed · +43 0
  • nova/api/metadata/handler.py+13 0 modified
    @@ -147,15 +147,20 @@ def _handle_remote_ip_request(self, req):
     
         def _handle_instance_id_request(self, req):
             instance_id = req.headers.get('X-Instance-ID')
    +        tenant_id = req.headers.get('X-Tenant-ID')
             signature = req.headers.get('X-Instance-ID-Signature')
             remote_address = req.headers.get('X-Forwarded-For')
     
             # Ensure that only one header was passed
     
             if instance_id is None:
                 msg = _('X-Instance-ID header is missing from request.')
    +        elif tenant_id is None:
    +            msg = _('X-Tenant-ID header is missing from request.')
             elif not isinstance(instance_id, basestring):
                 msg = _('Multiple X-Instance-ID headers found within request.')
    +        elif not isinstance(tenant_id, basestring):
    +            msg = _('Multiple X-Tenant-ID headers found within request.')
             else:
                 msg = None
     
    @@ -195,4 +200,12 @@ def _handle_instance_id_request(self, req):
                 LOG.error(_('Failed to get metadata for instance id: %s'),
                           instance_id)
     
    +        if meta_data.instance['project_id'] != tenant_id:
    +            LOG.warning(_("Tenant_id %(tenant_id)s does not match tenant_id "
    +                          "of instance %(instance_id)s."),
    +                        {'tenant_id': tenant_id,
    +                         'instance_id': instance_id})
    +            # causes a 404 to be raised
    +            meta_data = None
    +
             return meta_data
    
  • nova/tests/test_metadata.py+30 0 modified
    @@ -601,6 +601,7 @@ def fake_get_metadata(instance_id, remote_address):
                 relpath="/2009-04-04/user-data",
                 address="192.192.192.2",
                 headers={'X-Instance-ID': 'a-b-c-d',
    +                     'X-Tenant-ID': 'test',
                          'X-Instance-ID-Signature': signed})
             self.assertEqual(response.status_int, 200)
     
    @@ -613,6 +614,7 @@ def fake_get_metadata(instance_id, remote_address):
                 fake_get_metadata_by_instance_id=fake_get_metadata,
                 headers={'X-Forwarded-For': '192.192.192.2',
                          'X-Instance-ID': 'a-b-c-d',
    +                     'X-Tenant-ID': 'test',
                          'X-Instance-ID-Signature': signed})
     
             self.assertEqual(response.status_int, 200)
    @@ -627,17 +629,44 @@ def fake_get_metadata(instance_id, remote_address):
                 fake_get_metadata_by_instance_id=fake_get_metadata,
                 headers={'X-Forwarded-For': '192.192.192.2',
                          'X-Instance-ID': 'a-b-c-d',
    +                     'X-Tenant-ID': 'test',
                          'X-Instance-ID-Signature': ''})
     
             self.assertEqual(response.status_int, 403)
     
    +        # missing X-Tenant-ID from request
    +        response = fake_request(
    +            self.stubs, self.mdinst,
    +            relpath="/2009-04-04/user-data",
    +            address="192.192.192.2",
    +            fake_get_metadata_by_instance_id=fake_get_metadata,
    +            headers={'X-Forwarded-For': '192.192.192.2',
    +                     'X-Instance-ID': 'a-b-c-d',
    +                     'X-Instance-ID-Signature': signed})
    +
    +        self.assertEqual(response.status_int, 400)
    +
    +        # mismatched X-Tenant-ID
    +        response = fake_request(
    +            self.stubs, self.mdinst,
    +            relpath="/2009-04-04/user-data",
    +            address="192.192.192.2",
    +            fake_get_metadata_by_instance_id=fake_get_metadata,
    +            headers={'X-Forwarded-For': '192.192.192.2',
    +                     'X-Instance-ID': 'a-b-c-d',
    +                     'X-Tenant-ID': 'FAKE',
    +                     'X-Instance-ID-Signature': signed})
    +
    +        self.assertEqual(response.status_int, 404)
    +
             # without X-Forwarded-For
             response = fake_request(
                 self.stubs, self.mdinst,
                 relpath="/2009-04-04/user-data",
                 address="192.192.192.2",
                 fake_get_metadata_by_instance_id=fake_get_metadata,
                 headers={'X-Instance-ID': 'a-b-c-d',
    +                     'X-Tenant-ID': 'test',
                          'X-Instance-ID-Signature': signed})
     
             self.assertEqual(response.status_int, 500)
    @@ -655,6 +684,7 @@ def fake_get_metadata(instance_id, remote_address):
                 fake_get_metadata_by_instance_id=fake_get_metadata,
                 headers={'X-Forwarded-For': '192.192.192.2',
                          'X-Instance-ID': 'z-z-z-z',
    +                     'X-Tenant-ID': 'test',
                          'X-Instance-ID-Signature': signed})
             self.assertEqual(response.status_int, 500)
     
    
07006be9165d

Prevent spoofing instance_id from neutron to nova

https://github.com/openstack/novaAaron RosenOct 7, 2013via ghsa
2 files changed · +43 0
  • nova/api/metadata/handler.py+13 0 modified
    @@ -144,15 +144,20 @@ def _handle_remote_ip_request(self, req):
     
         def _handle_instance_id_request(self, req):
             instance_id = req.headers.get('X-Instance-ID')
    +        tenant_id = req.headers.get('X-Tenant-ID')
             signature = req.headers.get('X-Instance-ID-Signature')
             remote_address = req.headers.get('X-Forwarded-For')
     
             # Ensure that only one header was passed
     
             if instance_id is None:
                 msg = _('X-Instance-ID header is missing from request.')
    +        elif tenant_id is None:
    +            msg = _('X-Tenant-ID header is missing from request.')
             elif not isinstance(instance_id, basestring):
                 msg = _('Multiple X-Instance-ID headers found within request.')
    +        elif not isinstance(tenant_id, basestring):
    +            msg = _('Multiple X-Tenant-ID headers found within request.')
             else:
                 msg = None
     
    @@ -188,4 +193,12 @@ def _handle_instance_id_request(self, req):
                 LOG.error(_('Failed to get metadata for instance id: %s'),
                           instance_id)
     
    +        if meta_data.instance['project_id'] != tenant_id:
    +            LOG.warning(_("Tenant_id %(tenant_id)s does not match tenant_id "
    +                          "of instance %(instance_id)s."),
    +                        {'tenant_id': tenant_id,
    +                         'instance_id': instance_id})
    +            # causes a 404 to be raised
    +            meta_data = None
    +
             return meta_data
    
  • nova/tests/test_metadata.py+30 0 modified
    @@ -510,6 +510,7 @@ def fake_get_metadata(instance_id, remote_address):
                 relpath="/2009-04-04/user-data",
                 address="192.192.192.2",
                 headers={'X-Instance-ID': 'a-b-c-d',
    +                     'X-Tenant-ID': 'test',
                          'X-Instance-ID-Signature': signed})
             self.assertEqual(response.status_int, 200)
     
    @@ -522,6 +523,7 @@ def fake_get_metadata(instance_id, remote_address):
                 fake_get_metadata_by_instance_id=fake_get_metadata,
                 headers={'X-Forwarded-For': '192.192.192.2',
                          'X-Instance-ID': 'a-b-c-d',
    +                     'X-Tenant-ID': 'test',
                          'X-Instance-ID-Signature': signed})
     
             self.assertEqual(response.status_int, 200)
    @@ -536,17 +538,44 @@ def fake_get_metadata(instance_id, remote_address):
                 fake_get_metadata_by_instance_id=fake_get_metadata,
                 headers={'X-Forwarded-For': '192.192.192.2',
                          'X-Instance-ID': 'a-b-c-d',
    +                     'X-Tenant-ID': 'test',
                          'X-Instance-ID-Signature': ''})
     
             self.assertEqual(response.status_int, 403)
     
    +        # missing X-Tenant-ID from request
    +        response = fake_request(
    +            self.stubs, self.mdinst,
    +            relpath="/2009-04-04/user-data",
    +            address="192.192.192.2",
    +            fake_get_metadata_by_instance_id=fake_get_metadata,
    +            headers={'X-Forwarded-For': '192.192.192.2',
    +                     'X-Instance-ID': 'a-b-c-d',
    +                     'X-Instance-ID-Signature': signed})
    +
    +        self.assertEqual(response.status_int, 400)
    +
    +        # mismatched X-Tenant-ID
    +        response = fake_request(
    +            self.stubs, self.mdinst,
    +            relpath="/2009-04-04/user-data",
    +            address="192.192.192.2",
    +            fake_get_metadata_by_instance_id=fake_get_metadata,
    +            headers={'X-Forwarded-For': '192.192.192.2',
    +                     'X-Instance-ID': 'a-b-c-d',
    +                     'X-Tenant-ID': 'FAKE',
    +                     'X-Instance-ID-Signature': signed})
    +
    +        self.assertEqual(response.status_int, 404)
    +
             # without X-Forwarded-For
             response = fake_request(
                 self.stubs, self.mdinst,
                 relpath="/2009-04-04/user-data",
                 address="192.192.192.2",
                 fake_get_metadata_by_instance_id=fake_get_metadata,
                 headers={'X-Instance-ID': 'a-b-c-d',
    +                     'X-Tenant-ID': 'test',
                          'X-Instance-ID-Signature': signed})
     
             self.assertEqual(response.status_int, 500)
    @@ -564,6 +593,7 @@ def fake_get_metadata(instance_id, remote_address):
                 fake_get_metadata_by_instance_id=fake_get_metadata,
                 headers={'X-Forwarded-For': '192.192.192.2',
                          'X-Instance-ID': 'z-z-z-z',
    +                     'X-Tenant-ID': 'test',
                          'X-Instance-ID-Signature': signed})
             self.assertEqual(response.status_int, 500)
     
    
bce36e9bdb1f

Prevent spoofing instance_id from neutron to nova

https://github.com/openstack/novaAaron RosenOct 7, 2013via ghsa
2 files changed · +43 0
  • nova/api/metadata/handler.py+13 0 modified
    @@ -148,15 +148,20 @@ def _handle_remote_ip_request(self, req):
     
         def _handle_instance_id_request(self, req):
             instance_id = req.headers.get('X-Instance-ID')
    +        tenant_id = req.headers.get('X-Tenant-ID')
             signature = req.headers.get('X-Instance-ID-Signature')
             remote_address = req.headers.get('X-Forwarded-For')
     
             # Ensure that only one header was passed
     
             if instance_id is None:
                 msg = _('X-Instance-ID header is missing from request.')
    +        elif tenant_id is None:
    +            msg = _('X-Tenant-ID header is missing from request.')
             elif not isinstance(instance_id, six.string_types):
                 msg = _('Multiple X-Instance-ID headers found within request.')
    +        elif not isinstance(tenant_id, six.string_types):
    +            msg = _('Multiple X-Tenant-ID headers found within request.')
             else:
                 msg = None
     
    @@ -196,4 +201,12 @@ def _handle_instance_id_request(self, req):
                 LOG.error(_('Failed to get metadata for instance id: %s'),
                           instance_id)
     
    +        if meta_data.instance['project_id'] != tenant_id:
    +            LOG.warning(_("Tenant_id %(tenant_id)s does not match tenant_id "
    +                          "of instance %(instance_id)s."),
    +                        {'tenant_id': tenant_id,
    +                         'instance_id': instance_id})
    +            # causes a 404 to be raised
    +            meta_data = None
    +
             return meta_data
    
  • nova/tests/test_metadata.py+30 0 modified
    @@ -643,6 +643,7 @@ def fake_get_metadata(instance_id, remote_address):
                 relpath="/2009-04-04/user-data",
                 address="192.192.192.2",
                 headers={'X-Instance-ID': 'a-b-c-d',
    +                     'X-Tenant-ID': 'test',
                          'X-Instance-ID-Signature': signed})
             self.assertEqual(response.status_int, 200)
     
    @@ -655,6 +656,7 @@ def fake_get_metadata(instance_id, remote_address):
                 fake_get_metadata_by_instance_id=fake_get_metadata,
                 headers={'X-Forwarded-For': '192.192.192.2',
                          'X-Instance-ID': 'a-b-c-d',
    +                     'X-Tenant-ID': 'test',
                          'X-Instance-ID-Signature': signed})
     
             self.assertEqual(response.status_int, 200)
    @@ -669,17 +671,44 @@ def fake_get_metadata(instance_id, remote_address):
                 fake_get_metadata_by_instance_id=fake_get_metadata,
                 headers={'X-Forwarded-For': '192.192.192.2',
                          'X-Instance-ID': 'a-b-c-d',
    +                     'X-Tenant-ID': 'test',
                          'X-Instance-ID-Signature': ''})
     
             self.assertEqual(response.status_int, 403)
     
    +        # missing X-Tenant-ID from request
    +        response = fake_request(
    +            self.stubs, self.mdinst,
    +            relpath="/2009-04-04/user-data",
    +            address="192.192.192.2",
    +            fake_get_metadata_by_instance_id=fake_get_metadata,
    +            headers={'X-Forwarded-For': '192.192.192.2',
    +                     'X-Instance-ID': 'a-b-c-d',
    +                     'X-Instance-ID-Signature': signed})
    +
    +        self.assertEqual(response.status_int, 400)
    +
    +        # mismatched X-Tenant-ID
    +        response = fake_request(
    +            self.stubs, self.mdinst,
    +            relpath="/2009-04-04/user-data",
    +            address="192.192.192.2",
    +            fake_get_metadata_by_instance_id=fake_get_metadata,
    +            headers={'X-Forwarded-For': '192.192.192.2',
    +                     'X-Instance-ID': 'a-b-c-d',
    +                     'X-Tenant-ID': 'FAKE',
    +                     'X-Instance-ID-Signature': signed})
    +
    +        self.assertEqual(response.status_int, 404)
    +
             # without X-Forwarded-For
             response = fake_request(
                 self.stubs, self.mdinst,
                 relpath="/2009-04-04/user-data",
                 address="192.192.192.2",
                 fake_get_metadata_by_instance_id=fake_get_metadata,
                 headers={'X-Instance-ID': 'a-b-c-d',
    +                     'X-Tenant-ID': 'test',
                          'X-Instance-ID-Signature': signed})
     
             self.assertEqual(response.status_int, 500)
    @@ -697,6 +726,7 @@ def fake_get_metadata(instance_id, remote_address):
                 fake_get_metadata_by_instance_id=fake_get_metadata,
                 headers={'X-Forwarded-For': '192.192.192.2',
                          'X-Instance-ID': 'z-z-z-z',
    +                     'X-Tenant-ID': 'test',
                          'X-Instance-ID-Signature': signed})
             self.assertEqual(response.status_int, 500)
     
    

Vulnerability mechanics

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

References

12

News mentions

0

No linked articles in our index yet.