VYPR
Critical severityGHSA Advisory· Published Mar 21, 2019· Updated Aug 4, 2024

CVE-2019-7539

CVE-2019-7539

Description

A code injection vulnerability in ipycache <=2016-05-31 allows arbitrary code execution via malicious pickle deserialization.

AI Insight

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

A code injection vulnerability in ipycache <=2016-05-31 allows arbitrary code execution via malicious pickle deserialization.

Vulnerability

The load_vars function in ipycache (all versions up to and including 2016-05-31) uses Python's pickle.load without any restrictions. This allows an attacker to craft a malicious pickle file that, when loaded, can execute arbitrary code during deserialization [1][2].

Exploitation

An attacker must be able to provide a specially crafted pickle file to be loaded by load_vars. This could occur if the attacker can write to the cache file path used by ipycache, for example by controlling input to an IPython or Jupyter notebook session. No authentication is required beyond the ability to influence the file contents. The exploit involves creating a pickle containing an object with a __reduce__ method that executes arbitrary commands [3][4].

Impact

Successful exploitation leads to arbitrary code execution in the context of the user running the notebook (e.g., the IPython kernel). This can result in full compromise of the user's data and system, including privilege escalation if the user has elevated rights.

Mitigation

The vulnerability is fixed in ipycache by commits c73a726 [3] and 9cc7cb8 [4], which introduced RestrictedUnpickler to limit deserialization to only _io.StringIO. Users should update to a version including these fixes. No workaround is available; until patched, avoid loading untrusted pickle files.

AI Insight generated on May 22, 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
ipycachePyPI
<= 0.1.4

Affected products

2

Patches

2
c73a726744c9

Fix for arbitrary code execution while unpickling in ipycache.load_vars() method.

https://github.com/adi928/ipycacheAditya NathFeb 4, 2020via ghsa
2 files changed · +44 8
  • ipycache.py+29 8 modified
    @@ -7,18 +7,20 @@
     # Imports
     #------------------------------------------------------------------------------
     
    +import hashlib
     # Stdlib
    -import inspect, os, sys, textwrap, re
    +import io
    +import os
    +import re
    +import sys
     
     # Our own
     from IPython.config.configurable import Configurable
     from IPython.core import magic_arguments
    -from IPython.core.magic import Magics, magics_class, line_magic, cell_magic
    -from IPython.utils.traitlets import Unicode
    -from IPython.utils.io import CapturedIO, capture_output
    +from IPython.core.magic import Magics, magics_class, cell_magic
     from IPython.display import clear_output
    -import hashlib
    -
    +from IPython.utils.io import CapturedIO
    +from IPython.utils.traitlets import Unicode
     
     #------------------------------------------------------------------------------
     # Six utility functions for Python 2/3 compatibility
    @@ -115,6 +117,7 @@ def load_vars(path, vars):
         with open(path, 'rb') as f:
             # Load the variables from the cache.
             try:
    +            restricted_loads(f.read())
                 cache = pickle.load(f)
             except EOFError as e:
                 cache={}
    @@ -151,8 +154,26 @@ def save_vars(path, vars_d):
         """
         with open(path, 'wb') as f:
             dump(vars_d, f)
    -    
    -    
    +
    +
    +# ------------------------------------------------------------------------------
    +# RestrictedUnpickler - For mitigating arbitrary code execution while unpickling
    +# This function provides restriction of using only the io module
    +# ------------------------------------------------------------------------------
    +class RestrictedUnpickler(pickle.Unpickler):
    +
    +    def find_class(self, module, name):
    +        if module == '_io' and name == 'StringIO':
    +            return getattr(sys.modules[module], name)
    +        # Forbid everything else.
    +        raise pickle.UnpicklingError("global '%s.%s' is forbidden" %
    +                                     (module, name))
    +
    +
    +def restricted_loads(s):
    +    """Helper function analogous to pickle.loads()."""
    +    return RestrictedUnpickler(io.BytesIO(s)).load()
    +
     #------------------------------------------------------------------------------
     # CapturedIO
     #------------------------------------------------------------------------------
    
  • test_ipycache.py+15 0 modified
    @@ -206,3 +206,18 @@ def ip_push(vars):
               ip_user_ns=user_ns, ip_run_cell=ip_run_cell, ip_push=ip_push)
         
         os.remove(path)
    +
    +
    +def test_load_exploitPickle():
    +    class vulnLoad():
    +        def __init__(self):
    +            self.a = 1
    +
    +        def __reduce__(self):
    +            return (os.system, ('uname -a',))
    +
    +    payload = vulnLoad()
    +    path = "malicious.pkl"
    +    with open("malicious.pkl", "wb") as f:
    +        pickle.dump(payload, f)
    +    assert_raises(pickle.UnpicklingError, load_vars, path, ['a'])
    
9cc7cb891ff1

Fix for arbitrary code execution while unpickling in ipycache.load_vars() method.

https://github.com/adi928/ipycacheAditya NathFeb 4, 2020via ghsa
2 files changed · +36 3
  • ipycache.py+21 3 modified
    @@ -19,7 +19,6 @@
     from IPython.display import clear_output
     import hashlib
     
    -
     #------------------------------------------------------------------------------
     # Six utility functions for Python 2/3 compatibility
     #------------------------------------------------------------------------------
    @@ -115,6 +114,7 @@ def load_vars(path, vars):
         with open(path, 'rb') as f:
             # Load the variables from the cache.
             try:
    +            restricted_loads(f.read())
                 cache = pickle.load(f)
             except EOFError as e:
                 cache={}
    @@ -151,8 +151,26 @@ def save_vars(path, vars_d):
         """
         with open(path, 'wb') as f:
             dump(vars_d, f)
    -    
    -    
    +
    +
    +# ------------------------------------------------------------------------------
    +# RestrictedUnpickler - For mitigating arbitrary code execution while unpickling
    +# This function provides restriction of using only the io module
    +# ------------------------------------------------------------------------------
    +class RestrictedUnpickler(pickle.Unpickler):
    +
    +    def find_class(self, module, name):
    +        if module == '_io' and name == 'StringIO':
    +            return getattr(sys.modules[module], name)
    +        # Forbid everything else.
    +        raise pickle.UnpicklingError("global '%s.%s' is forbidden" %
    +                                     (module, name))
    +
    +
    +def restricted_loads(s):
    +    """Helper function analogous to pickle.loads()."""
    +    return RestrictedUnpickler(io.BytesIO(s)).load()
    +
     #------------------------------------------------------------------------------
     # CapturedIO
     #------------------------------------------------------------------------------
    
  • test_ipycache.py+15 0 modified
    @@ -206,3 +206,18 @@ def ip_push(vars):
               ip_user_ns=user_ns, ip_run_cell=ip_run_cell, ip_push=ip_push)
         
         os.remove(path)
    +
    +
    +def test_load_exploitPickle():
    +    class vulnLoad():
    +        def __init__(self):
    +            self.a = 1
    +
    +        def __reduce__(self):
    +            return (os.system, ('uname -a',))
    +
    +    payload = vulnLoad()
    +    path = "malicious.pkl"
    +    with open("malicious.pkl", "wb") as f:
    +        pickle.dump(payload, f)
    +    assert_raises(pickle.UnpicklingError, load_vars, path, ['a'])
    \ No newline at end of file
    

Vulnerability mechanics

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

References

6

News mentions

0

No linked articles in our index yet.