VYPR
High severityNVD Advisory· Published Aug 7, 2014· Updated May 6, 2026

CVE-2014-3429

CVE-2014-3429

Description

IPython Notebook 0.12 through 1.x before 1.2 does not validate the origin of websocket requests, which allows remote attackers to execute arbitrary code by leveraging knowledge of the kernel id and a crafted page.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
ipythonPyPI
>= 0.12, < 1.2.01.2.0

Affected products

11
  • cpe:2.3:a:ipython:ipython_notebook:0.12:*:*:*:*:*:*:*+ 6 more
    • cpe:2.3:a:ipython:ipython_notebook:0.12:*:*:*:*:*:*:*
    • cpe:2.3:a:ipython:ipython_notebook:0.12.1:*:*:*:*:*:*:*
    • cpe:2.3:a:ipython:ipython_notebook:0.13:*:*:*:*:*:*:*
    • cpe:2.3:a:ipython:ipython_notebook:0.13.1:*:*:*:*:*:*:*
    • cpe:2.3:a:ipython:ipython_notebook:0.13.2:*:*:*:*:*:*:*
    • cpe:2.3:a:ipython:ipython_notebook:1.0.0:*:*:*:*:*:*:*
    • cpe:2.3:a:ipython:ipython_notebook:1.1.0:*:*:*:*:*:*:*
  • Mageia/Mageia2 versions
    cpe:2.3:o:mageia:mageia:3.0:*:*:*:*:*:*:*+ 1 more
    • cpe:2.3:o:mageia:mageia:3.0:*:*:*:*:*:*:*
    • cpe:2.3:o:mageia:mageia:4.0:*:*:*:*:*:*:*
  • OpenSUSE/openSUSE2 versions
    cpe:2.3:o:opensuse:opensuse:13.1:*:*:*:*:*:*:*+ 1 more
    • cpe:2.3:o:opensuse:opensuse:13.1:*:*:*:*:*:*:*
    • cpe:2.3:o:opensuse:opensuse:13.2:*:*:*:*:*:*:*

Patches

2
e5b669ce4750

Merge pull request #4845 from rgbkrk/origin_host

https://github.com/ipython/ipythonMin RKJan 31, 2014via ghsa
1 file changed · +35 2
  • IPython/html/base/zmqhandlers.py+35 2 modified
    @@ -16,6 +16,11 @@
     # Imports
     #-----------------------------------------------------------------------------
     
    +try:
    +    from urllib.parse import urlparse # Py 3
    +except ImportError:
    +    from urlparse import urlparse # Py 2
    +
     try:
         from http.cookies import SimpleCookie  # Py 3
     except ImportError:
    @@ -37,7 +42,30 @@
     #-----------------------------------------------------------------------------
     
     class ZMQStreamHandler(websocket.WebSocketHandler):
    -    
    +
    +    def same_origin(self):
    +        """Check to see that origin and host match in the headers."""
    +
    +        # The difference between version 8 and 13 is that in 8 the
    +        # client sends a "Sec-Websocket-Origin" header and in 13 it's
    +        # simply "Origin".
    +        if self.request.headers.get("Sec-WebSocket-Version") in ("7", "8"):
    +            origin_header = self.request.headers.get("Sec-Websocket-Origin")
    +        else:
    +            origin_header = self.request.headers.get("Origin")
    +
    +        host = self.request.headers.get("Host")
    +
    +        # If no header is provided, assume we can't verify origin
    +        if(origin_header is None or host is None):
    +            return False
    +
    +        parsed_origin = urlparse(origin_header)
    +        origin = parsed_origin.netloc
    +
    +        # Check to see that origin matches host directly, including ports
    +        return origin == host
    +
         def clear_cookie(self, *args, **kwargs):
             """meaningless for websockets"""
             pass
    @@ -86,6 +114,11 @@ def allow_draft76(self):
     class AuthenticatedZMQStreamHandler(ZMQStreamHandler, IPythonHandler):
     
         def open(self, kernel_id):
    +        # Check to see that origin matches host directly, including ports
    +        if not self.same_origin():
    +            self.log.warn("Cross Origin WebSocket Attempt.")
    +            raise web.HTTPError(404)
    +
             self.kernel_id = cast_unicode(kernel_id, 'ascii')
             self.session = Session(config=self.config)
             self.save_on_message = self.on_message
    @@ -114,4 +147,4 @@ def on_first_message(self, msg):
             if self.get_current_user() is None:
                 self.log.warn("Couldn't authenticate WebSocket connection")
                 raise web.HTTPError(403)
    -        self.on_message = self.save_on_message
    \ No newline at end of file
    +        self.on_message = self.save_on_message
    
dd4135db9f42

Merge pull request #4845 from rgbkrk/origin_host

1 file changed · +35 2
  • IPython/html/base/zmqhandlers.py+35 2 modified
    @@ -16,6 +16,11 @@
     # Imports
     #-----------------------------------------------------------------------------
     
    +try:
    +    from urllib.parse import urlparse # Py 3
    +except ImportError:
    +    from urlparse import urlparse # Py 2
    +
     try:
         from http.cookies import SimpleCookie  # Py 3
     except ImportError:
    @@ -37,7 +42,30 @@
     #-----------------------------------------------------------------------------
     
     class ZMQStreamHandler(websocket.WebSocketHandler):
    -    
    +
    +    def same_origin(self):
    +        """Check to see that origin and host match in the headers."""
    +
    +        # The difference between version 8 and 13 is that in 8 the
    +        # client sends a "Sec-Websocket-Origin" header and in 13 it's
    +        # simply "Origin".
    +        if self.request.headers.get("Sec-WebSocket-Version") in ("7", "8"):
    +            origin_header = self.request.headers.get("Sec-Websocket-Origin")
    +        else:
    +            origin_header = self.request.headers.get("Origin")
    +
    +        host = self.request.headers.get("Host")
    +
    +        # If no header is provided, assume we can't verify origin
    +        if(origin_header is None or host is None):
    +            return False
    +
    +        parsed_origin = urlparse(origin_header)
    +        origin = parsed_origin.netloc
    +
    +        # Check to see that origin matches host directly, including ports
    +        return origin == host
    +
         def clear_cookie(self, *args, **kwargs):
             """meaningless for websockets"""
             pass
    @@ -86,6 +114,11 @@ def allow_draft76(self):
     class AuthenticatedZMQStreamHandler(ZMQStreamHandler, IPythonHandler):
     
         def open(self, kernel_id):
    +        # Check to see that origin matches host directly, including ports
    +        if not self.same_origin():
    +            self.log.warn("Cross Origin WebSocket Attempt.")
    +            raise web.HTTPError(404)
    +
             self.kernel_id = cast_unicode(kernel_id, 'ascii')
             self.session = Session(config=self.config)
             self.save_on_message = self.on_message
    @@ -114,4 +147,4 @@ def on_first_message(self, msg):
             if self.get_current_user() is None:
                 self.log.warn("Couldn't authenticate WebSocket connection")
                 raise web.HTTPError(403)
    -        self.on_message = self.save_on_message
    \ No newline at end of file
    +        self.on_message = self.save_on_message
    

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

14

News mentions

0

No linked articles in our index yet.