{"id":"CVE-2023-35932","aliases":["EUVD-2023-1913","GHSA-x49m-3cw7-gq5q","PYSEC-2026-1470"],"status":"published","title":"jcvi vulnerable to Configuration Injection due to unsanitized user input","description":"jcvi is a Python library to facilitate genome assembly, annotation, and comparative genomics. A configuration injection happens when user input is considered by the application in an unsanitized format and can reach the configuration file. A malicious user may craft a special payload that may lead to a command injection. The impact of a configuration injection may vary. Under some conditions, it may lead to command injection if there is for instance shell code execution from the configuration file values. This vulnerability does not currently have a fix.","severity":{"version":"3.1","score":7.1,"vector":"CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:L","level":"high","assessor":"cna","from":"cve"},"epss":{"day":"2026-11-10","score":0.01788,"percentile":0.78526,"model":"v2026.06.15"},"facts":{"in_kev":false,"known_exploited":false,"public_exploit":false,"fix_available":false},"cwes":["CWE-1284","CWE-77"],"published":"2023-06-23T21:05:32Z","modified":"2026-10-28T02:30:49Z","affected":[{"source":"ghsa","ecosystem":"PyPI","package":"jcvi","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"last_affected":"1.3.5"}]}]},{"source":"osv","ecosystem":"PyPI","package":"jcvi","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"last_affected":"1.3.5"}]}],"versions":["0.4.10","0.4.12","0.4.7","0.4.8","0.4.9","0.5.1","0.5.3","0.5.5","0.5.7","0.5.8","0.5.9","0.6.1","0.6.2","0.6.6","0.6.9","0.7.1","0.7.3","0.7.5","0.7.7","0.8.12","0.8.4","0.9.11","0.9.12","0.9.13","0.9.14","1.0.1","1.0.10","1.0.13","1.0.14","1.0.3","1.0.5","1.0.6","1.0.8","1.0.9","1.1.11","1.1.12","1.1.15","1.1.17","1.1.18","1.1.21","1.1.23","1.1.7","1.1.8","1.2.1","1.2.10","1.2.12","1.2.14","1.2.20","1.2.7","1.2.9","1.3.3","1.3.4","1.3.5"]},{"source":"osv","ecosystem":"PyPI","package":"jcvi","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"last_affected":"1.3.5"}]}],"versions":["0.4.10","0.4.12","0.4.7","0.4.8","0.4.9","0.5.1","0.5.3","0.5.5","0.5.7","0.5.8","0.5.9","0.6.1","0.6.2","0.6.6","0.6.9","0.7.1","0.7.3","0.7.5","0.7.7","0.8.12","0.8.4","0.9.11","0.9.12","0.9.13","0.9.14","1.0.1","1.0.10","1.0.13","1.0.14","1.0.3","1.0.5","1.0.6","1.0.8","1.0.9","1.1.11","1.1.12","1.1.15","1.1.17","1.1.18","1.1.21","1.1.23","1.1.7","1.1.8","1.2.1","1.2.10","1.2.12","1.2.14","1.2.20","1.2.7","1.2.9","1.3.3","1.3.4","1.3.5"]}],"products":[{"vendor":"jcvi_project","product":"jcvi"},{"vendor":"tanghaibao","product":"jcvi"}],"references":[{"url":"https://github.com/tanghaibao/jcvi/security/advisories/GHSA-x49m-3cw7-gq5q","tags":["x_refsource_CONFIRM","x_transferred","Vendor Advisory","advisory","web"]},{"url":"https://github.com/tanghaibao/jcvi/blob/cede6c65c8e7603cb266bc3395ac8f915ea9eac7/jcvi/apps/base.py#LL2227C1-L2228C41","tags":["x_refsource_MISC","x_transferred","Product","web"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2023-35932","tags":["advisory"]},{"url":"https://github.com/advisories/GHSA-x49m-3cw7-gq5q","tags":["advisory"]},{"url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2023/35xxx/CVE-2023-35932.json","tags":["advisory"]},{"url":"https://github.com/tanghaibao/jcvi","tags":["package"]},{"url":"https://pypi.org/project/jcvi","tags":["package"]}],"sources":{"cve":[{"id":"CVE-2023-35932","title":"jcvi vulnerable to Configuration Injection due to unsanitized user input ","description":"jcvi is a Python library to facilitate genome assembly, annotation, and comparative genomics. A configuration injection happens when user input is considered by the application in an unsanitized format and can reach the configuration file. A malicious user may craft a special payload that may lead to a command injection. The impact of a configuration injection may vary. Under some conditions, it may lead to command injection if there is for instance shell code execution from the configuration file values. This vulnerability does not currently have a fix.\n","status":"published","published":"2023-06-23T21:05:32.79Z","modified":"2024-11-27T20:01:06.11Z","cvss":[{"version":"3.1","score":7.1,"vector":"CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:L","level":"high","assessor":"cna"}],"cwes":["CWE-77"],"updated_at":"2026-11-02T14:35:33.794347Z"}],"euvd":[{"id":"EUVD-2023-1913","description":"jcvi is a Python library to facilitate genome assembly, annotation, and comparative genomics. A configuration injection happens when user input is considered by the application in an unsanitized format and can reach the configuration file. A malicious user may craft a special payload that may lead to a command injection. The impact of a configuration injection may vary. Under some conditions, it may lead to command injection if there is for instance shell code execution from the configuration file values. This vulnerability does not currently have a fix.\n","status":"published","published":"2023-06-23T21:05:32Z","modified":"2024-11-27T20:01:06Z","cvss":[{"version":"3.1","score":7.1,"vector":"CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:L","level":"high"}],"updated_at":"2026-11-03T00:04:45.257697Z"}],"ghsa":[{"id":"GHSA-x49m-3cw7-gq5q","title":"jcvi vulnerable to Configuration Injection due to unsanitized user input ","description":"### Summary\nA configuration injection happens when user input is considered by the application in an unsanitized format and can reach the configuration file. A malicious user may craft a special payload that may lead to a command injection.\n\n### PoC\n\nThe vulnerable code snippet is [/jcvi/apps/base.py#LL2227C1-L2228C41](https://github.com/tanghaibao/jcvi/blob/cede6c65c8e7603cb266bc3395ac8f915ea9eac7/jcvi/apps/base.py#LL2227C1-L2228C41). Under some circumstances a user input is retrieved and stored within the `fullpath` variable which reaches the configuration file `~/.jcvirc`.\n\n```python\n        fullpath = input(msg).strip()\n        config.set(PATH, name, fullpath)\n```\n\nI ripped a part of the codebase into a runnable PoC as follows. All the PoC does is call the `getpath()` function under some circumstances.\n\n```python\nfrom configparser import (\n    ConfigParser,\n    RawConfigParser,\n    NoOptionError,\n    NoSectionError,\n    ParsingError,\n)\n\nimport errno\nimport os\nimport sys\nimport os.path as op\nimport shutil\nimport signal\nimport sys\nimport logging\n\n\ndef is_exe(fpath):\n    return op.isfile(fpath) and os.access(fpath, os.X_OK)\n\n\ndef which(program):\n    \"\"\"\n    Emulates the unix which command.\n\n    \u003e\u003e\u003e which(\"cat\")\n    \"/bin/cat\"\n    \u003e\u003e\u003e which(\"nosuchprogram\")\n    \"\"\"\n    fpath, fname = op.split(program)\n    if fpath:\n        if is_exe(program):\n            return program\n    else:\n        for path in os.environ[\"PATH\"].split(os.pathsep):\n            exe_file = op.join(path, program)\n            if is_exe(exe_file):\n                return exe_file\n\n    return None\n\n\ndef getpath(cmd, name=None, url=None, cfg=\"~/.jcvirc\", warn=\"exit\"):\n    \"\"\"\n    Get install locations of common binaries\n    First, check ~/.jcvirc file to get the full path\n    If not present, ask on the console and store\n    \"\"\"\n    p = which(cmd)  # if in PATH, just returns it\n    if p:\n        return p\n\n    PATH = \"Path\"\n    config = RawConfigParser()\n    cfg = op.expanduser(cfg)\n    changed = False\n    if op.exists(cfg):\n        config.read(cfg)\n\n    assert name is not None, \"Need a program name\"\n\n    try:\n        fullpath = config.get(PATH, name)\n    except NoSectionError:\n        config.add_section(PATH)\n        changed = True\n\n    try:\n        fullpath = config.get(PATH, name)\n    except NoOptionError:\n        msg = \"=== Configure path for {0} ===\\n\".format(name, cfg)\n        if url:\n            msg += \"URL: {0}\\n\".format(url)\n        msg += \"[Directory that contains `{0}`]: \".format(cmd)\n        fullpath = input(msg).strip()\n        config.set(PATH, name, fullpath)\n        changed = True\n\n    path = op.join(op.expanduser(fullpath), cmd)\n    if warn == \"exit\":\n        try:\n            assert is_exe(path), \"***ERROR: Cannot execute binary `{0}`. \".format(path)\n        except AssertionError as e:\n            sys.exit(\"{0!s}Please verify and rerun.\".format(e))\n\n    if changed:\n        configfile = open(cfg, \"w\")\n        config.write(configfile)\n        logging.debug(\"Configuration written to `{0}`.\".format(cfg))\n\n    return path\n\n\n# Call to getpath\npath = getpath(\"not-part-of-path\", name=\"CLUSTALW2\", warn=\"warn\")\nprint(path)\n\n```\n\nTo run the PoC, you need to remove the config file `~/.jcvirc` to emulate the first run, \n\n```bash\n# Run the PoC with the payload\necho -e \"e\\rvvvvvvvv = zzzzzzzz\\n\" | python3 poc.py\n```\n\n![image](https://user-images.githubusercontent.com/13036531/247852364-f8a384a3-fc62-41ca-b467-877d197ac6ff.png)\n\nYou can notice the random key/value characters `vvvvvvvv = zzzzzzzz` were successfully injected.\n\n### Impact\n\nThe impact of a configuration injection may vary. Under some conditions, it may lead to command injection if there is for instance shell code execution from the configuration file values.\n","status":"published","published":"2023-06-23T21:44:35Z","modified":"2023-11-09T05:01:00Z","cvss":[{"version":"3.1","score":7.1,"vector":"CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:L","level":"high"}],"cwes":["CWE-77","CWE-1284"],"updated_at":"2026-11-02T14:37:17.64478Z"}],"nvd":[{"id":"CVE-2023-35932","description":"jcvi is a Python library to facilitate genome assembly, annotation, and comparative genomics. A configuration injection happens when user input is considered by the application in an unsanitized format and can reach the configuration file. A malicious user may craft a special payload that may lead to a command injection. The impact of a configuration injection may vary. Under some conditions, it may lead to command injection if there is for instance shell code execution from the configuration file values. This vulnerability does not currently have a fix.\n","status":"published","published":"2023-06-23T22:15:08.987Z","modified":"2026-06-17T06:05:29.647Z","cvss":[{"version":"3.1","score":7.1,"vector":"CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:L","level":"high","assessor":"secondary"},{"version":"3.1","score":8.8,"vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H","level":"high","assessor":"primary"}],"cwes":["CWE-77","CWE-1284"],"updated_at":"2026-11-02T14:08:12.414559Z"}],"osv":[{"id":"CVE-2023-35932","title":"jcvi vulnerable to Configuration Injection due to unsanitized user input ","description":"jcvi is a Python library to facilitate genome assembly, annotation, and comparative genomics. A configuration injection happens when user input is considered by the application in an unsanitized format and can reach the configuration file. A malicious user may craft a special payload that may lead to a command injection. The impact of a configuration injection may vary. Under some conditions, it may lead to command injection if there is for instance shell code execution from the configuration file values. This vulnerability does not currently have a fix.\n","status":"published","published":"2023-06-23T21:05:32.79Z","modified":"2026-10-28T02:30:49.766703857Z","cvss":[{"version":"3.1","score":7.1,"vector":"CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:L","level":"high"}],"cwes":["CWE-77"],"updated_at":"2026-11-02T15:44:32.510144Z"},{"id":"GHSA-x49m-3cw7-gq5q","title":"jcvi vulnerable to Configuration Injection due to unsanitized user input ","description":"### Summary\nA configuration injection happens when user input is considered by the application in an unsanitized format and can reach the configuration file. A malicious user may craft a special payload that may lead to a command injection.\n\n### PoC\n\nThe vulnerable code snippet is [/jcvi/apps/base.py#LL2227C1-L2228C41](https://github.com/tanghaibao/jcvi/blob/cede6c65c8e7603cb266bc3395ac8f915ea9eac7/jcvi/apps/base.py#LL2227C1-L2228C41). Under some circumstances a user input is retrieved and stored within the `fullpath` variable which reaches the configuration file `~/.jcvirc`.\n\n```python\n        fullpath = input(msg).strip()\n        config.set(PATH, name, fullpath)\n```\n\nI ripped a part of the codebase into a runnable PoC as follows. All the PoC does is call the `getpath()` function under some circumstances.\n\n```python\nfrom configparser import (\n    ConfigParser,\n    RawConfigParser,\n    NoOptionError,\n    NoSectionError,\n    ParsingError,\n)\n\nimport errno\nimport os\nimport sys\nimport os.path as op\nimport shutil\nimport signal\nimport sys\nimport logging\n\n\ndef is_exe(fpath):\n    return op.isfile(fpath) and os.access(fpath, os.X_OK)\n\n\ndef which(program):\n    \"\"\"\n    Emulates the unix which command.\n\n    \u003e\u003e\u003e which(\"cat\")\n    \"/bin/cat\"\n    \u003e\u003e\u003e which(\"nosuchprogram\")\n    \"\"\"\n    fpath, fname = op.split(program)\n    if fpath:\n        if is_exe(program):\n            return program\n    else:\n        for path in os.environ[\"PATH\"].split(os.pathsep):\n            exe_file = op.join(path, program)\n            if is_exe(exe_file):\n                return exe_file\n\n    return None\n\n\ndef getpath(cmd, name=None, url=None, cfg=\"~/.jcvirc\", warn=\"exit\"):\n    \"\"\"\n    Get install locations of common binaries\n    First, check ~/.jcvirc file to get the full path\n    If not present, ask on the console and store\n    \"\"\"\n    p = which(cmd)  # if in PATH, just returns it\n    if p:\n        return p\n\n    PATH = \"Path\"\n    config = RawConfigParser()\n    cfg = op.expanduser(cfg)\n    changed = False\n    if op.exists(cfg):\n        config.read(cfg)\n\n    assert name is not None, \"Need a program name\"\n\n    try:\n        fullpath = config.get(PATH, name)\n    except NoSectionError:\n        config.add_section(PATH)\n        changed = True\n\n    try:\n        fullpath = config.get(PATH, name)\n    except NoOptionError:\n        msg = \"=== Configure path for {0} ===\\n\".format(name, cfg)\n        if url:\n            msg += \"URL: {0}\\n\".format(url)\n        msg += \"[Directory that contains `{0}`]: \".format(cmd)\n        fullpath = input(msg).strip()\n        config.set(PATH, name, fullpath)\n        changed = True\n\n    path = op.join(op.expanduser(fullpath), cmd)\n    if warn == \"exit\":\n        try:\n            assert is_exe(path), \"***ERROR: Cannot execute binary `{0}`. \".format(path)\n        except AssertionError as e:\n            sys.exit(\"{0!s}Please verify and rerun.\".format(e))\n\n    if changed:\n        configfile = open(cfg, \"w\")\n        config.write(configfile)\n        logging.debug(\"Configuration written to `{0}`.\".format(cfg))\n\n    return path\n\n\n# Call to getpath\npath = getpath(\"not-part-of-path\", name=\"CLUSTALW2\", warn=\"warn\")\nprint(path)\n\n```\n\nTo run the PoC, you need to remove the config file `~/.jcvirc` to emulate the first run, \n\n```bash\n# Run the PoC with the payload\necho -e \"e\\rvvvvvvvv = zzzzzzzz\\n\" | python3 poc.py\n```\n\n![image](https://user-images.githubusercontent.com/13036531/247852364-f8a384a3-fc62-41ca-b467-877d197ac6ff.png)\n\nYou can notice the random key/value characters `vvvvvvvv = zzzzzzzz` were successfully injected.\n\n### Impact\n\nThe impact of a configuration injection may vary. Under some conditions, it may lead to command injection if there is for instance shell code execution from the configuration file values.\n","status":"published","published":"2023-06-23T21:44:35Z","modified":"2026-09-10T03:49:57.127455238Z","cvss":[{"version":"3.1","score":7.1,"vector":"CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:L","level":"high"}],"cwes":["CWE-1284","CWE-77"],"updated_at":"2026-11-02T15:46:59.484835Z"},{"id":"PYSEC-2026-1470","title":"jcvi vulnerable to Configuration Injection due to unsanitized user input ","description":"### Summary\nA configuration injection happens when user input is considered by the application in an unsanitized format and can reach the configuration file. A malicious user may craft a special payload that may lead to a command injection.\n\n### PoC\n\nThe vulnerable code snippet is [/jcvi/apps/base.py#LL2227C1-L2228C41](https://github.com/tanghaibao/jcvi/blob/cede6c65c8e7603cb266bc3395ac8f915ea9eac7/jcvi/apps/base.py#LL2227C1-L2228C41). Under some circumstances a user input is retrieved and stored within the `fullpath` variable which reaches the configuration file `~/.jcvirc`.\n\n```python\n        fullpath = input(msg).strip()\n        config.set(PATH, name, fullpath)\n```\n\nI ripped a part of the codebase into a runnable PoC as follows. All the PoC does is call the `getpath()` function under some circumstances.\n\n```python\nfrom configparser import (\n    ConfigParser,\n    RawConfigParser,\n    NoOptionError,\n    NoSectionError,\n    ParsingError,\n)\n\nimport errno\nimport os\nimport sys\nimport os.path as op\nimport shutil\nimport signal\nimport sys\nimport logging\n\n\ndef is_exe(fpath):\n    return op.isfile(fpath) and os.access(fpath, os.X_OK)\n\n\ndef which(program):\n    \"\"\"\n    Emulates the unix which command.\n\n    \u003e\u003e\u003e which(\"cat\")\n    \"/bin/cat\"\n    \u003e\u003e\u003e which(\"nosuchprogram\")\n    \"\"\"\n    fpath, fname = op.split(program)\n    if fpath:\n        if is_exe(program):\n            return program\n    else:\n        for path in os.environ[\"PATH\"].split(os.pathsep):\n            exe_file = op.join(path, program)\n            if is_exe(exe_file):\n                return exe_file\n\n    return None\n\n\ndef getpath(cmd, name=None, url=None, cfg=\"~/.jcvirc\", warn=\"exit\"):\n    \"\"\"\n    Get install locations of common binaries\n    First, check ~/.jcvirc file to get the full path\n    If not present, ask on the console and store\n    \"\"\"\n    p = which(cmd)  # if in PATH, just returns it\n    if p:\n        return p\n\n    PATH = \"Path\"\n    config = RawConfigParser()\n    cfg = op.expanduser(cfg)\n    changed = False\n    if op.exists(cfg):\n        config.read(cfg)\n\n    assert name is not None, \"Need a program name\"\n\n    try:\n        fullpath = config.get(PATH, name)\n    except NoSectionError:\n        config.add_section(PATH)\n        changed = True\n\n    try:\n        fullpath = config.get(PATH, name)\n    except NoOptionError:\n        msg = \"=== Configure path for {0} ===\\n\".format(name, cfg)\n        if url:\n            msg += \"URL: {0}\\n\".format(url)\n        msg += \"[Directory that contains `{0}`]: \".format(cmd)\n        fullpath = input(msg).strip()\n        config.set(PATH, name, fullpath)\n        changed = True\n\n    path = op.join(op.expanduser(fullpath), cmd)\n    if warn == \"exit\":\n        try:\n            assert is_exe(path), \"***ERROR: Cannot execute binary `{0}`. \".format(path)\n        except AssertionError as e:\n            sys.exit(\"{0!s}Please verify and rerun.\".format(e))\n\n    if changed:\n        configfile = open(cfg, \"w\")\n        config.write(configfile)\n        logging.debug(\"Configuration written to `{0}`.\".format(cfg))\n\n    return path\n\n\n# Call to getpath\npath = getpath(\"not-part-of-path\", name=\"CLUSTALW2\", warn=\"warn\")\nprint(path)\n\n```\n\nTo run the PoC, you need to remove the config file `~/.jcvirc` to emulate the first run, \n\n```bash\n# Run the PoC with the payload\necho -e \"e\\rvvvvvvvv = zzzzzzzz\\n\" | python3 poc.py\n```\n\n![image](https://user-images.githubusercontent.com/13036531/247852364-f8a384a3-fc62-41ca-b467-877d197ac6ff.png)\n\nYou can notice the random key/value characters `vvvvvvvv = zzzzzzzz` were successfully injected.\n\n### Impact\n\nThe impact of a configuration injection may vary. Under some conditions, it may lead to command injection if there is for instance shell code execution from the configuration file values.\n","status":"published","published":"2026-07-07T11:45:19.233547Z","modified":"2026-07-07T17:47:15.625912516Z","cvss":[{"version":"3.1","score":7.1,"vector":"CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:L","level":"high"}],"updated_at":"2026-11-02T15:52:55.06457Z"}]}}
