Medium severity5.9NVD Advisory· Published Nov 4, 2012· Updated Apr 29, 2026
CVE-2012-3446
CVE-2012-3446
Description
Apache Libcloud before 0.11.1 uses an incorrect regular expression during verification of whether the server hostname matches a domain name in the subject's Common Name (CN) or subjectAltName field of the X.509 certificate, which allows man-in-the-middle attackers to spoof SSL servers via a crafted certificate.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
apache-libcloudPyPI | < 0.11.1 | 0.11.1 |
Affected products
1Patches
1f2af5502dae3Fix hostname validation in the SSL verification code (CVE-2012-3446). Reported by researchers
4 files changed · +48 −11
CHANGES+12 −3 modified@@ -1,5 +1,14 @@ -*- coding: utf-8 -*- +Changes with Apache Libcloud 0.11.1: + + *) General + + - Fix hostname validation in the SSL verification code (CVE-2012-3446). + + Reported by researchers from the University of Texas at Austin (Martin + Georgiev, Suman Jana and Vitaly Shmatikov). + Changes with Apache Libcloud 0.11.0: *) Compute @@ -139,7 +148,7 @@ Changes with Apache Libcloud 0.11.0: CloudFiles driver. [Tomaz Muraus] - - Fix a bug with content_type and and encoding of object and path names in + - Fix a bug with content_type and and encoding of object and path names in the Atmos driver. [Russell Keith-Magee] @@ -234,7 +243,7 @@ Changes with Apache Libcloud 0.10.1: - Add ex_rescue and ex_unrescue method to OpenStack 1.1 driver. ; LIBCLOUD-193 - [Shawn Smith] + [Shawn Smith] - Include 'password' in the node extra dictionary when calling deploy_node if the password auth is used. @@ -419,7 +428,7 @@ Changes with Apache Libcloud 0.8.0: - Enable ex_delete_image method in the OpenStack 1.1 driver. [Shawn Smith] - - Return NodeImage instance in OpenStack 1.1 driver ex_save_image method + - Return NodeImage instance in OpenStack 1.1 driver ex_save_image method ; LIBCLOUD-138 [Shawn Smith]
libcloud/httplib_ssl.py+2 −7 modified@@ -122,13 +122,8 @@ def _verify_hostname(self, hostname, cert): # replace * with alphanumeric and dash # replace . with literal . valid_patterns = [ - re.compile( - pattern.replace( - r".", r"\." - ).replace( - r"*", r"[0-9A-Za-z]+" - ) - ) + re.compile('^' + pattern.replace(r".", r"\.") \ + .replace(r"*", r"[0-9A-Za-z]+") + '$') for pattern in (set(common_name) | set(alt_names))] return any(
libcloud/__init__.py+1 −1 modified@@ -20,7 +20,7 @@ """ __all__ = ['__version__', 'enable_debug'] -__version__ = '0.11.0' +__version__ = '0.11.1' try: import paramiko
libcloud/test/test_httplib_ssl.py+33 −0 modified@@ -45,16 +45,49 @@ def test_verify_hostname(self): 'subjectAltName': ((('DNS', 'foo.alt.name')), (('DNS', 'foo.alt.name.1')))} + cert3 = {'notAfter': 'Feb 16 16:54:50 2013 GMT', + 'subject': ((('countryName', 'US'),), + (('stateOrProvinceName', 'Delaware'),), + (('localityName', 'Wilmington'),), + (('organizationName', 'Python Software Foundation'),), + (('organizationalUnitName', 'SSL'),), + (('commonName', 'python.org'),))} + self.assertFalse(self.httplib_object._verify_hostname( hostname='invalid', cert=cert1)) + self.assertFalse(self.httplib_object._verify_hostname( + hostname='machine.python.org', cert=cert1)) + self.assertFalse(self.httplib_object._verify_hostname( + hostname='foomachine.python.org', cert=cert1)) + self.assertFalse(self.httplib_object._verify_hostname( + hostname='somesomemachine.python.org', cert=cert1)) + self.assertFalse(self.httplib_object._verify_hostname( + hostname='somemachine.python.orga', cert=cert1)) + self.assertFalse(self.httplib_object._verify_hostname( + hostname='somemachine.python.org.org', cert=cert1)) self.assertTrue(self.httplib_object._verify_hostname( hostname='somemachine.python.org', cert=cert1)) self.assertFalse(self.httplib_object._verify_hostname( hostname='invalid', cert=cert2)) + self.assertFalse(self.httplib_object._verify_hostname( + hostname='afoo.alt.name.1', cert=cert2)) + self.assertFalse(self.httplib_object._verify_hostname( + hostname='a.foo.alt.name.1', cert=cert2)) + self.assertFalse(self.httplib_object._verify_hostname( + hostname='foo.alt.name.1.2', cert=cert2)) + self.assertFalse(self.httplib_object._verify_hostname( + hostname='afoo.alt.name.1.2', cert=cert2)) self.assertTrue(self.httplib_object._verify_hostname( hostname='foo.alt.name.1', cert=cert2)) + self.assertTrue(self.httplib_object._verify_hostname( + hostname='python.org', cert=cert3)) + self.assertFalse(self.httplib_object._verify_hostname( + hostname='opython.org', cert=cert3)) + self.assertFalse(self.httplib_object._verify_hostname( + hostname='ython.org', cert=cert3)) + def test_get_subject_alt_names(self): cert1 = {'notAfter': 'Feb 16 16:54:50 2013 GMT', 'subject': ((('countryName', 'US'),),
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
6- www.cs.utexas.edu/~shmat/shmat_ccs12.pdfnvdExploitWEB
- github.com/advisories/GHSA-prcq-52f8-fp44ghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2012-3446ghsaADVISORY
- github.com/apache/libcloud/commit/f2af5502dae3ac63e656dd1b7d5f29cc82ded401ghsaWEB
- github.com/pypa/advisory-database/tree/main/vulns/apache-libcloud/PYSEC-2012-12.yamlghsaWEB
- svn.apache.org/repos/asf/libcloud/trunk/CHANGESnvdRelease NotesWEB
News mentions
0No linked articles in our index yet.