Moderate severityNVD Advisory· Published Aug 17, 2012· Updated Apr 29, 2026
CVE-2012-1585
CVE-2012-1585
Description
OpenStack Compute (Nova) Essex before 2011.3 allows remote authenticated users to cause a denial of service (Nova-API log file and disk consumption) via a long server name.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
novaPyPI | < 12.0.0a0 | 12.0.0a0 |
Affected products
1Patches
41ebec5726c7aAdd validation for OSAPI server name length.
2 files changed · +23 −0
nova/api/openstack/create_instance_helper.py+4 −0 modified@@ -248,6 +248,10 @@ def _validate_server_name(self, value): msg = _("Server name is an empty string") raise exc.HTTPBadRequest(explanation=msg) + if not len(value) < 256: + msg = _("Server name must be less than 256 characters.") + raise exc.HTTPBadRequest(explanation=msg) + def _get_kernel_ramdisk_from_image(self, req, image_service, image_id): """Fetch an image from the ImageService, then if present, return the associated kernel and ramdisk image IDs.
nova/tests/api/openstack/test_servers.py+19 −0 modified@@ -2294,6 +2294,16 @@ def test_update_server_name_v1_1(self): self.assertEqual(res_dict['server']['id'], 1) self.assertEqual(res_dict['server']['name'], 'server_test') + def test_update_server_name_too_long_v1_1(self): + self.stubs.Set(nova.db.api, 'instance_get', + return_server_with_attributes(name='server_test')) + req = webob.Request.blank('/v1.1/fake/servers/1') + req.method = 'PUT' + req.content_type = 'application/json' + req.body = json.dumps({'server': {'name': 'x' * 256}}) + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 400) + def test_update_server_access_ipv4_v1_1(self): self.stubs.Set(nova.db.api, 'instance_get', return_server_with_attributes(access_ipv4='0.0.0.0')) @@ -3634,6 +3644,15 @@ def test_create_instance_admin_pass_xml(self): self.assertEquals(server.nodeName, 'server') self.assertEqual(16, len(server.getAttribute('adminPass'))) + def test_create_instance_with_name_too_long(self): + personality = None + body_dict = self._create_personality_request_dict(personality) + body_dict['server']['name'] = 'X' * 256 + request = self._get_create_request_json(body_dict) + compute_api, response = \ + self._run_create_instance_with_mock_compute_api(request) + self.assertEquals(response.status_int, 400) + class TestGetKernelRamdiskFromImage(test.TestCase): """
0fa7d12dbfb7Adds middleware to limit request body sizes.
3 files changed · +116 −8
etc/nova/api-paste.ini+11 −8 modified@@ -92,17 +92,17 @@ use = call:nova.api.openstack.urlmap:urlmap_factory [composite:openstack_compute_api_v2] use = call:nova.api.auth:pipeline_factory -noauth = faultwrap noauth ratelimit osapi_compute_app_v2 -deprecated = faultwrap auth ratelimit osapi_compute_app_v2 -keystone = faultwrap authtoken keystonecontext ratelimit osapi_compute_app_v2 -keystone_nolimit = faultwrap authtoken keystonecontext osapi_compute_app_v2 +noauth = faultwrap sizelimit noauth ratelimit osapi_compute_app_v2 +deprecated = faultwrap sizelimit auth ratelimit osapi_compute_app_v2 +keystone = faultwrap sizelimit authtoken keystonecontext ratelimit osapi_compute_app_v2 +keystone_nolimit = faultwrap sizelimit authtoken keystonecontext osapi_compute_app_v2 [composite:openstack_volume_api_v1] use = call:nova.api.auth:pipeline_factory -noauth = faultwrap noauth ratelimit osapi_volume_app_v1 -deprecated = faultwrap auth ratelimit osapi_volume_app_v1 -keystone = faultwrap authtoken keystonecontext ratelimit osapi_volume_app_v1 -keystone_nolimit = faultwrap authtoken keystonecontext osapi_volume_app_v1 +noauth = faultwrap sizelimit noauth ratelimit osapi_volume_app_v1 +deprecated = faultwrap sizelimit auth ratelimit osapi_volume_app_v1 +keystone = faultwrap sizelimit authtoken keystonecontext ratelimit osapi_volume_app_v1 +keystone_nolimit = faultwrap sizelimit authtoken keystonecontext osapi_volume_app_v1 [filter:faultwrap] paste.filter_factory = nova.api.openstack:FaultWrapper.factory @@ -116,6 +116,9 @@ paste.filter_factory = nova.api.openstack.auth:NoAuthMiddleware.factory [filter:ratelimit] paste.filter_factory = nova.api.openstack.compute.limits:RateLimitingMiddleware.factory +[filter:sizelimit] +paste.filter_factory = nova.api.sizelimit:RequestBodySizeLimiter.factory + [app:osapi_compute_app_v2] paste.app_factory = nova.api.openstack.compute:APIRouter.factory
nova/api/sizelimit.py+54 −0 added@@ -0,0 +1,54 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright (c) 2012 OpenStack, LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +""" +Request Body limiting middleware. + +""" + +import webob.dec +import webob.exc + +from nova import context +from nova import flags +from nova import log as logging +from nova.openstack.common import cfg +from nova import wsgi + + +#default request size is 112k +max_request_body_size_opt = cfg.BoolOpt('osapi_max_request_body_size', + default=114688, + help='') + +FLAGS = flags.FLAGS +FLAGS.register_opt(max_request_body_size_opt) +LOG = logging.getLogger(__name__) + + +class RequestBodySizeLimiter(wsgi.Middleware): + """Add a 'nova.context' to WSGI environ.""" + + def __init__(self, *args, **kwargs): + super(RequestBodySizeLimiter, self).__init__(*args, **kwargs) + + @webob.dec.wsgify(RequestClass=wsgi.Request) + def __call__(self, req): + if (req.content_length > FLAGS.osapi_max_request_body_size + or len(req.body) > FLAGS.osapi_max_request_body_size): + msg = _("Request is too large.") + raise webob.exc.HTTPBadRequest(explanation=msg) + else: + return self.application
nova/tests/api/test_sizelimit.py+51 −0 added@@ -0,0 +1,51 @@ +# Copyright (c) 2012 OpenStack, LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import webob + +import nova.api.sizelimit +from nova import flags +from nova import test + +FLAGS = flags.FLAGS +MAX_REQUEST_BODY_SIZE = FLAGS.osapi_max_request_body_size + + +class TestRequestBodySizeLimiter(test.TestCase): + + def setUp(self): + super(TestRequestBodySizeLimiter, self).setUp() + + @webob.dec.wsgify() + def fake_app(req): + return webob.Response() + + self.middleware = nova.api.sizelimit.RequestBodySizeLimiter(fake_app) + self.request = webob.Request.blank('/', method='POST') + + def test_content_length_acceptable(self): + self.request.headers['Content-Length'] = MAX_REQUEST_BODY_SIZE + self.request.body = "0" * MAX_REQUEST_BODY_SIZE + response = self.request.get_response(self.middleware) + self.assertEqual(response.status_int, 200) + + def test_content_length_to_large(self): + self.request.headers['Content-Length'] = MAX_REQUEST_BODY_SIZE + 1 + response = self.request.get_response(self.middleware) + self.assertEqual(response.status_int, 400) + + def test_request_to_large(self): + self.request.body = "0" * (MAX_REQUEST_BODY_SIZE + 1) + response = self.request.get_response(self.middleware) + self.assertEqual(response.status_int, 400)
c869a41951b7Add validation for OSAPI server name length.
2 files changed · +46 −0
nova/api/openstack/compute/servers.py+4 −0 modified@@ -505,6 +505,10 @@ def _validate_server_name(self, value): msg = _("Server name is an empty string") raise exc.HTTPBadRequest(explanation=msg) + if not len(value) < 256: + msg = _("Server name must be less than 256 characters.") + raise exc.HTTPBadRequest(explanation=msg) + def _get_injected_files(self, personality): """ Create a list of injected files from the personality attribute
nova/tests/api/openstack/compute/test_servers.py+42 −0 modified@@ -891,6 +891,17 @@ def test_update_server_name(self): self.assertEqual(res_dict['server']['id'], FAKE_UUID) self.assertEqual(res_dict['server']['name'], 'server_test') + def test_update_server_name_too_long(self): + self.stubs.Set(nova.db, 'instance_get', + fakes.fake_instance_get(name='server_test')) + req = fakes.HTTPRequest.blank('/v2/fake/servers/%s' % FAKE_UUID) + req.method = 'PUT' + req.content_type = 'application/json' + body = {'server': {'name': 'x' * 256}} + req.body = json.dumps(body) + self.assertRaises(webob.exc.HTTPBadRequest, self.controller.update, + req, FAKE_UUID, body) + def test_update_server_access_ipv4(self): self.stubs.Set(nova.db, 'instance_get', fakes.fake_instance_get(access_ipv4='0.0.0.0')) @@ -1643,6 +1654,37 @@ def test_create_instance_bad_format_access_ip_v6(self): self.assertRaises(webob.exc.HTTPBadRequest, self.controller.create, req, body) + def test_create_instance_name_too_long(self): + # proper local hrefs must start with 'http://localhost/v2/' + image_uuid = '76fa36fc-c930-4bf3-8c8a-ea2a2420deb6' + image_href = 'http://localhost/v2/images/%s' % image_uuid + flavor_ref = 'http://localhost/123/flavors/3' + body = { + 'server': { + 'name': 'X' * 256, + 'imageRef': image_href, + 'flavorRef': flavor_ref, + 'metadata': { + 'hello': 'world', + 'open': 'stack', + }, + 'personality': [ + { + "path": "/etc/banner.txt", + "contents": "MQ==", + }, + + ], + }, + } + + req = fakes.HTTPRequest.blank('/v2/fake/servers') + req.method = 'POST' + req.body = json.dumps(body) + req.headers["content-type"] = "application/json" + self.assertRaises(webob.exc.HTTPBadRequest, self.controller.create, + req, body) + def test_create_instance(self): # proper local hrefs must start with 'http://localhost/v2/' image_uuid = '76fa36fc-c930-4bf3-8c8a-ea2a2420deb6'
c7f526fae606Add validation for OSAPI server name length.
2 files changed · +46 −0
nova/api/openstack/compute/servers.py+4 −0 modified@@ -505,6 +505,10 @@ def _validate_server_name(self, value): msg = _("Server name is an empty string") raise exc.HTTPBadRequest(explanation=msg) + if not len(value) < 256: + msg = _("Server name must be less than 256 characters.") + raise exc.HTTPBadRequest(explanation=msg) + def _get_injected_files(self, personality): """ Create a list of injected files from the personality attribute
nova/tests/api/openstack/compute/test_servers.py+42 −0 modified@@ -891,6 +891,17 @@ def test_update_server_name(self): self.assertEqual(res_dict['server']['id'], FAKE_UUID) self.assertEqual(res_dict['server']['name'], 'server_test') + def test_update_server_name_too_long(self): + self.stubs.Set(nova.db, 'instance_get', + fakes.fake_instance_get(name='server_test')) + req = fakes.HTTPRequest.blank('/v2/fake/servers/%s' % FAKE_UUID) + req.method = 'PUT' + req.content_type = 'application/json' + body = {'server': {'name': 'x' * 256}} + req.body = json.dumps(body) + self.assertRaises(webob.exc.HTTPBadRequest, self.controller.update, + req, FAKE_UUID, body) + def test_update_server_access_ipv4(self): self.stubs.Set(nova.db, 'instance_get', fakes.fake_instance_get(access_ipv4='0.0.0.0')) @@ -1643,6 +1654,37 @@ def test_create_instance_bad_format_access_ip_v6(self): self.assertRaises(webob.exc.HTTPBadRequest, self.controller.create, req, body) + def test_create_instance_name_too_long(self): + # proper local hrefs must start with 'http://localhost/v2/' + image_uuid = '76fa36fc-c930-4bf3-8c8a-ea2a2420deb6' + image_href = 'http://localhost/v2/images/%s' % image_uuid + flavor_ref = 'http://localhost/123/flavors/3' + body = { + 'server': { + 'name': 'X' * 256, + 'imageRef': image_href, + 'flavorRef': flavor_ref, + 'metadata': { + 'hello': 'world', + 'open': 'stack', + }, + 'personality': [ + { + "path": "/etc/banner.txt", + "contents": "MQ==", + }, + + ], + }, + } + + req = fakes.HTTPRequest.blank('/v2/fake/servers') + req.method = 'POST' + req.body = json.dumps(body) + req.headers["content-type"] = "application/json" + self.assertRaises(webob.exc.HTTPBadRequest, self.controller.create, + req, body) + def test_create_instance(self): # proper local hrefs must start with 'http://localhost/v2/' image_uuid = '76fa36fc-c930-4bf3-8c8a-ea2a2420deb6'
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
10- bugs.launchpad.net/nova/+bug/962515nvdExploitThird Party AdvisoryWEB
- lwn.net/Alerts/491298/nvdThird Party Advisory
- github.com/advisories/GHSA-pjvw-p2v5-wf6qghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2012-1585ghsaADVISORY
- github.com/openstack/nova/commit/0fa7d12dbfb7ae016657dd91034b4c0781ea43deghsaWEB
- github.com/openstack/nova/commit/1ebec5726c7a9db0a6f29fad0ef747b0c087f702ghsaWEB
- github.com/openstack/nova/commit/c7f526fae6062e9ab51f65474af71d496aa66554ghsaWEB
- github.com/openstack/nova/commit/c869a41951b77c6930bf4fb4734f05cd3d6ac4b1ghsaWEB
- lwn.net/Alerts/491298ghsaWEB
- osdir.com/ml/openstack-cloud-computing/2012-03/msg01133.htmlnvdBroken LinkWEB
News mentions
0No linked articles in our index yet.