VYPR
Moderate severityNVD Advisory· Published May 10, 2023· Updated Jan 27, 2025

in-toto vulnerable to Configuration Read From Local Directory

CVE-2023-32076

Description

in-toto is a framework to protect supply chain integrity. The in-toto configuration is read from various directories and allows users to configure the behavior of the framework. The files are from directories following the XDG base directory specification. In versions 1.4.0 and prior, among the files read is .in_totorc which is a hidden file in the directory in which in-toto is run. If an attacker controls the inputs to a supply chain step, they can mask their activities by also passing in an .in_totorc file that includes the necessary exclude patterns and settings. RC files are widely used in other systems and security issues have been discovered in their implementations as well. Maintainers found in their conversations with in-toto adopters that in_totorc is not their preferred way to configure in-toto. As none of the options supported in in_totorc is unique, and can be set elsewhere using API parameters or CLI arguments, the maintainers decided to drop support for in_totorc. in-toto's user_settings module has been dropped altogether in commit 3a21d84f40811b7d191fa7bd17265c1f99599afd. Users may also sandbox functionary code as a security measure.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
in-totoPyPI
< 2.0.02.0.0

Affected products

1

Patches

1
3a21d84f4081

Merge pull request from GHSA-wc64-c5rv-32pf

https://github.com/in-toto/in-totoAditya SirishMay 10, 2023via ghsa
7 files changed · +6 418
  • doc/source/settings.rst+5 48 modified
    @@ -1,53 +1,10 @@
     Settings
     ========
     
    -For historical reasons some command line options may also be configured via
    -rcfiles in one of the following locations *.in_totorc*, *~/.in_totorc*,
    -*~/.in_toto/config*, *~/.config/in_toto*, *~/.config/in_toto/config*,
    -*/etc/in_totorc*, */etc/in_toto/config* or via environment variables in above
    -presented order of precedence.
    -
    -Default values for these settings are defined in the `in_toto.settings
    -<https://github.com/in-toto/in-toto/blob/develop/in_toto/settings.py>`_ module.
    -Settings names are case sensitive and settings values that contain colons are
    -parsed as list.
    +Default values for some in-toto CLI/API arguments are defined in global variables of the
    +``in_toto.settings`` module. Historically, configuration required modifying these
    +globals directly in source code or at runtime. This method is discouraged. Instead,
    +CLI/API arguments should be used.
     
     .. note::
    -  Settings configured via rcfiles and environment variables are **only**
    -  considered if in-toto is invoked form the **command line**, and ignored when
    -  using the API.
    -  The default ``in_toto.settings``, on the other hand, are considered in both
    -  cases, unless overridden via API function arguments or, in the case of CLI
    -  usage, environment variables, rcfiles, or CLI arguments.
    -
    -
    -Setting Types
    --------------
    -
    -- ``ARTIFACT_EXCLUDE_PATTERNS`` -- gitignore-style paths patterns exclude
    -  artifacts from being recorded.
    -- ``ARTIFACT_BASE_PATH`` -- material and product paths passed to
    -  ``in-toto-run`` are searched relative to the base path. The base path itself
    -  is not included in the link metadata. Default is the current working
    -  directory.
    -- ``LINK_CMD_EXEC_TIMEOUT`` -- maximum timeout setting for the in-toto-run
    -  command.
    -
    -
    -Example Usage
    --------------
    -
    -.. code-block:: sh
    -
    -  # Configure settings via bash-style environment variable export
    -  export IN_TOTO_ARTIFACT_BASE_PATH='/home/user/project'
    -  export IN_TOTO_ARTIFACT_EXCLUDE_PATTERNS='*.link:.gitignore'
    -  export IN_TOTO_LINK_CMD_EXEC_TIMEOUT='10'
    -
    -.. code-block:: sh
    -
    -  # Configure settings via ~/.in_totorc
    -  [in-toto settings]
    -  ARTIFACT_BASE_PATH=/home/user/project
    -  ARTIFACT_EXCLUDE_PATTERNS=*.link:.gitignore
    -  LINK_CMD_EXEC_TIMEOUT=10
    +  The globals ``DEBUG`` and ``LINK_CMD_EXEC_TIMEOUT`` can only be configured directly.
    
  • in_toto/in_toto_record.py+0 4 modified
    @@ -33,7 +33,6 @@
     from securesystemslib import interface
     
     import in_toto.runlib
    -import in_toto.user_settings
     from in_toto import __version__
     from in_toto.common_args import (
         BASE_PATH_ARGS,
    @@ -233,9 +232,6 @@ def main():
     
         LOG.setLevelVerboseOrQuiet(args.verbose, args.quiet)
     
    -    # Override defaults in settings.py with environment variables and RCfiles
    -    in_toto.user_settings.set_settings()
    -
         # Regular signing and GPG signing are mutually exclusive
         if (args.key is None) == (args.gpg is None):
             parser.print_usage()
    
  • in_toto/in_toto_run.py+0 4 modified
    @@ -32,7 +32,6 @@
     
     from securesystemslib import interface
     
    -import in_toto.user_settings
     from in_toto import __version__, runlib
     from in_toto.common_args import (
         BASE_PATH_ARGS,
    @@ -254,9 +253,6 @@ def main():
     
         LOG.setLevelVerboseOrQuiet(args.verbose, args.quiet)
     
    -    # Override defaults in settings.py with environment variables and RCfiles
    -    in_toto.user_settings.set_settings()
    -
         # Regular signing and GPG signing are mutually exclusive
         if (args.key is None) == (args.gpg is None):
             parser.print_usage()
    
  • in_toto/runlib.py+1 2 modified
    @@ -111,8 +111,7 @@ def record_artifacts_as_dict(
           exclude_patterns: (optional)
                   Artifacts matched by the pattern are excluded from the result.
                   Exclude patterns can be passed as argument or specified via
    -              ARTIFACT_EXCLUDE_PATTERNS setting (see `in_toto.settings`) or
    -              via envvars or rcfiles (see `in_toto.user_settings`).
    +              ARTIFACT_EXCLUDE_PATTERNS setting (see `in_toto.settings`).
                   If passed, patterns specified via settings are overriden.
     
           base_path: (optional)
    
  • in_toto/settings.py+0 6 modified
    @@ -25,14 +25,8 @@
          import in_toto.settings
          in_toto.settings.ARTIFACT_BASE_PATH = "/home/user/project"
          ```
    -  - or, when using in-toto via command line tooling, with environment variables
    -    or RCfiles, see the `in_toto.user_settings` module
    -
     """
     # The debug setting is used to set to the in-toto base logger to logging.DEBUG
    -# TODO: This setting is currently not available via environment variables or
    -# rcfiles, partially because at the moment it is read before we parse
    -# envvars/rcfiles. Do we want to make it available to those as well?
     DEBUG = False
     
     # See docstring of `in-toto.record_artifacts_as_dict` for how this is used
    
  • in_toto/user_settings.py+0 227 removed
    @@ -1,227 +0,0 @@
    -# Copyright New York University and the in-toto contributors
    -# SPDX-License-Identifier: Apache-2.0
    -
    -"""
    -<Program Name>
    -  user_settings.py
    -
    -<Author>
    -  Lukas Puehringer <lukas.puehringer@nyu.edu>
    -
    -<Started>
    -  Oct 25, 2017
    -
    -<Copyright>
    -  See LICENSE for licensing information.
    -
    -<Purpose>
    -  Provides methods to parse environment variables (`get_env`) and RCfiles
    -  (`get_rc`) and to override default settings (`set_settings`) defined in the
    -  `in_toto.settings` module.
    -
    -  Check out the respective docstrings to learn about the requirements for
    -  environment variables and RCfiles (includes examples).
    -
    -"""
    -import logging
    -import os
    -
    -import in_toto.settings
    -
    -try:
    -    import configparser
    -except ImportError:  # pragma: no cover
    -    import ConfigParser as configparser
    -
    -# Inherits from in_toto base logger (c.f. in_toto.log)
    -LOG = logging.getLogger(__name__)
    -
    -
    -USER_PATH = os.path.expanduser("~")
    -
    -# Prefix required by environment variables to be considered as in_toto settings
    -ENV_PREFIX = "IN_TOTO_"
    -
    -# List of considered rcfile paths in the order they get parsed and overridden,
    -# i.e. the same setting in `/etc/in_toto/config` and `.in_totorc` (cwd) uses
    -# the latter
    -RC_PATHS = [
    -    os.path.join("/etc", "in_toto", "config"),
    -    os.path.join("/etc", "in_totorc"),
    -    os.path.join(USER_PATH, ".config", "in_toto", "config"),
    -    os.path.join(USER_PATH, ".config", "in_toto"),
    -    os.path.join(USER_PATH, ".in_toto", "config"),
    -    os.path.join(USER_PATH, ".in_totorc"),
    -    ".in_totorc",
    -]
    -
    -# List of settings, for which defaults exist in `settings.py`
    -# TODO: Should we use `dir` on the module instead? If we list them here, we
    -# have to manually update if `settings.py` changes.
    -IN_TOTO_SETTINGS = [
    -    "ARTIFACT_EXCLUDE_PATTERNS",
    -    "ARTIFACT_BASE_PATH",
    -    "LINK_CMD_EXEC_TIMEOUT",
    -]
    -
    -
    -def _colon_split(value):
    -    """If `value` contains colons, return a list split at colons,
    -    return value otherwise."""
    -    value_list = value.split(":")
    -    if len(value_list) > 1:
    -        return value_list
    -
    -    return value
    -
    -
    -def get_env():
    -    """
    -    <Purpose>
    -      Parse environment for variables with prefix `ENV_PREFIX` and return
    -      a dict of key-value pairs.
    -
    -      The prefix `ENV_PREFIX` is stripped from the keys in the returned dict.
    -
    -      Values that contain colons (:) are split at the postion of the colons and
    -      converted into a list.
    -
    -
    -      Example:
    -
    -      ```
    -      # Exporting variables in e.g. bash
    -      export IN_TOTO_ARTIFACT_BASE_PATH='/home/user/project'
    -      export IN_TOTO_ARTIFACT_EXCLUDE_PATTERNS='*.link:.gitignore'
    -      export IN_TOTO_LINK_CMD_EXEC_TIMEOUT='10'
    -      ```
    -
    -      produces
    -
    -      ```
    -      {
    -        "ARTIFACT_BASE_PATH": "/home/user/project"
    -        "ARTIFACT_EXCLUDE_PATTERNS": ["*.link", ".gitignore"]
    -        "LINK_CMD_EXEC_TIMEOUT": "10"
    -      }
    -      ```
    -
    -    <Exceptions>
    -      None.
    -
    -    <Side Effects>
    -      Calls function to read files from disk.
    -
    -    <Returns>
    -      A dictionary containing the parsed key-value pairs.
    -
    -    """
    -    env_dict = {}
    -
    -    for name, value in os.environ.items():
    -        if name.startswith(ENV_PREFIX) and len(name) > len(ENV_PREFIX):
    -            stripped_name = name[len(ENV_PREFIX) :]
    -
    -            env_dict[stripped_name] = _colon_split(value)
    -
    -    return env_dict
    -
    -
    -def get_rc():
    -    """
    -    <Purpose>
    -      Reads RCfiles from the paths defined in `RC_PATHS` and returns
    -      a dictionary with all parsed key-value pairs.
    -
    -      The RCfile format is as expected by Python's builtin `ConfigParser` with
    -      the addition that values that contain colons (:) are split at the position
    -      of the colons and converted into a list.
    -
    -      Section titles in RCfiles are ignored when parsing the key-value pairs.
    -      However, there has to be at least one section defined.
    -
    -      The paths in `RC_PATHS` are ordered in reverse precedence, i.e. each file's
    -      settings override a previous file's settings, e.g. a setting defined
    -      in `.in_totorc` (in the current working dir) overrides the same
    -      setting defined in `~/.in_totorc` (in the user's home dir) and so on ...
    -
    -      Example:
    -
    -      ```
    -      # E.g. file `.in_totorc` in current working directory
    -      [in-toto setting]
    -      ARTIFACT_BASE_PATH = /home/user/project
    -      ARTIFACT_EXCLUDE_PATTERNS = *.link:.gitignore
    -      LINK_CMD_EXEC_TIMEOUT = 10
    -      ```
    -
    -      produces
    -
    -      ```
    -      {
    -        "ARTIFACT_BASE_PATH": "/home/user/project"
    -        "ARTIFACT_EXCLUDE_PATTERNS": ["*.link", ".gitignore"]
    -        "LINK_CMD_EXEC_TIMEOUT": "10"
    -      }
    -      ```
    -
    -    <Exceptions>
    -      None.
    -
    -    <Side Effects>
    -      Calls function to read files from disk.
    -
    -    <Returns>
    -      A dictionary containing the parsed key-value pairs.
    -
    -    """
    -    rc_dict = {}
    -
    -    config = configparser.ConfigParser()
    -    # Reset `optionxform`'s default case conversion to enable case-sensitivity
    -    config.optionxform = str
    -    config.read(RC_PATHS)
    -
    -    for section in config.sections():
    -        for name, value in config.items(section):
    -            rc_dict[name] = _colon_split(value)
    -
    -    return rc_dict
    -
    -
    -def set_settings():
    -    """
    -    <Purpose>
    -      Calls functions that read in-toto related environment variables and RCfiles
    -      and overrides variables in `settings.py` with the retrieved values, if they
    -      are whitelisted in `IN_TOTO_SETTINGS`.
    -
    -      Settings defined in RCfiles take precedence over settings defined in
    -      environment variables.
    -
    -    <Exceptions>
    -      None.
    -
    -    <Side Effects>
    -      Calls functions that read environment variables and files from disk.
    -
    -    <Returns>
    -      None.
    -
    -    """
    -    user_settings = get_env()
    -    user_settings.update(get_rc())
    -
    -    # If the user has specified one of the settings whitelisted in
    -    # IN_TOTO_SETTINGS per envvar or rcfile, override the item in `settings.py`
    -    for setting in IN_TOTO_SETTINGS:
    -        user_setting = user_settings.get(setting)
    -        if user_setting:
    -            LOG.info("Setting (user): {0}={1}".format(setting, user_setting))
    -            setattr(in_toto.settings, setting, user_setting)
    -
    -        else:
    -            default_setting = getattr(in_toto.settings, setting)
    -            LOG.info(
    -                "Setting (default): {0}={1}".format(setting, default_setting)
    -            )
    
  • tests/test_user_settings.py+0 127 removed
    @@ -1,127 +0,0 @@
    -# Copyright New York University and the in-toto contributors
    -# SPDX-License-Identifier: Apache-2.0
    -
    -"""
    -<Program Name>
    -  test_user_settings.py
    -
    -<Author>
    -  Lukas Puehringer <lukas.puehringer@nyu.edu>
    -
    -<Started>
    -  Oct 26, 2017
    -
    -<Copyright>
    -  See LICENSE for licensing information.
    -
    -<Purpose>
    -  Test in_toto/user_settings.py
    -
    -"""
    -import os
    -import unittest
    -
    -import in_toto.settings
    -import in_toto.user_settings
    -
    -
    -class TestUserSettings(unittest.TestCase):
    -    @classmethod
    -    def setUpClass(self):
    -        self.working_dir = os.getcwd()
    -
    -        # Backup settings to restore them in `tearDownClass`
    -        self.settings_backup = {}
    -        for key in dir(in_toto.settings):
    -            self.settings_backup[key] = getattr(in_toto.settings, key)
    -
    -        # We use `rc_test` as test dir because it has an `.in_totorc`, which
    -        # is loaded (from CWD) in `user_settings.set_settings` related tests
    -        self.test_dir = os.path.join(os.path.dirname(__file__), "rc_test")
    -        os.chdir(self.test_dir)
    -
    -        os.environ["IN_TOTO_ARTIFACT_EXCLUDE_PATTERNS"] = "e:n:v"
    -        os.environ["IN_TOTO_ARTIFACT_BASE_PATH"] = "e/n/v"
    -        os.environ["IN_TOTO_LINK_CMD_EXEC_TIMEOUT"] = "0.1"
    -        os.environ["IN_TOTO_NOT_WHITELISTED"] = "parsed"
    -        os.environ["NOT_PARSED"] = "ignored"
    -
    -    @classmethod
    -    def tearDownClass(self):
    -        os.chdir(self.working_dir)
    -
    -        # Other unittests might depend on defaults:
    -        # Restore monkey patched settings ...
    -        for key, val in self.settings_backup.items():
    -            setattr(in_toto.settings, key, val)
    -
    -        # ... and delete test environment variables
    -        del os.environ["IN_TOTO_ARTIFACT_EXCLUDE_PATTERNS"]
    -        del os.environ["IN_TOTO_ARTIFACT_BASE_PATH"]
    -        del os.environ["IN_TOTO_LINK_CMD_EXEC_TIMEOUT"]
    -        del os.environ["IN_TOTO_NOT_WHITELISTED"]
    -        del os.environ["NOT_PARSED"]
    -
    -    def test_get_rc(self):
    -        """Test rcfile parsing in CWD."""
    -        rc_dict = in_toto.user_settings.get_rc()
    -
    -        # Parsed (and split) and used by `set_settings` to monkeypatch settings
    -        self.assertListEqual(
    -            rc_dict["ARTIFACT_EXCLUDE_PATTERNS"], ["r", "c", "file"]
    -        )
    -        self.assertEqual(rc_dict["LINK_CMD_EXEC_TIMEOUT"], "20")
    -
    -        # Parsed but ignored in `set_settings` (not in case sensitive whitelist)
    -        self.assertEqual(rc_dict["artifact_base_path"], "r/c/file")
    -        self.assertEqual(rc_dict["new_rc_setting"], "new rc setting")
    -
    -    def test_get_env(self):
    -        """Test environment variables parsing, prefix and colon splitting."""
    -        env_dict = in_toto.user_settings.get_env()
    -
    -        # Parsed and used by `set_settings` to monkeypatch settings
    -        self.assertEqual(env_dict["ARTIFACT_BASE_PATH"], "e/n/v")
    -
    -        # Parsed (and split) but overriden by rcfile setting in `set_settings`
    -        self.assertListEqual(
    -            env_dict["ARTIFACT_EXCLUDE_PATTERNS"], ["e", "n", "v"]
    -        )
    -
    -        # Parsed and used by `set_settings`
    -        self.assertEqual(env_dict["LINK_CMD_EXEC_TIMEOUT"], "0.1")
    -
    -        # Parsed but ignored in `set_settings` (not in case sensitive whitelist)
    -        self.assertEqual(env_dict["NOT_WHITELISTED"], "parsed")
    -
    -        # Not parsed because of missing prefix
    -        self.assertFalse("NOT_PARSED" in env_dict)
    -
    -    def test_set_settings(self):
    -        """Test precedence of rc over env and whitelisting."""
    -        in_toto.user_settings.set_settings()
    -
    -        # From envvar IN_TOTO_ARTIFACT_BASE_PATH
    -        self.assertEqual(in_toto.settings.ARTIFACT_BASE_PATH, "e/n/v")
    -
    -        # From RCfile setting (has precedence over envvar setting)
    -        self.assertListEqual(
    -            in_toto.settings.ARTIFACT_EXCLUDE_PATTERNS, ["r", "c", "file"]
    -        )
    -        self.assertEqual(in_toto.settings.LINK_CMD_EXEC_TIMEOUT, "20")
    -
    -        # Not whitelisted rcfile settings are ignored by `set_settings`
    -        self.assertTrue("new_rc_setting" in in_toto.user_settings.get_rc())
    -        self.assertRaises(
    -            AttributeError, getattr, in_toto.settings, "NEW_RC_SETTING"
    -        )
    -
    -        # Not whitelisted envvars are ignored by `set_settings`
    -        self.assertTrue("NOT_WHITELISTED" in in_toto.user_settings.get_env())
    -        self.assertRaises(
    -            AttributeError, getattr, in_toto.settings, "NOT_WHITELISTED"
    -        )
    -
    -
    -if __name__ == "__main__":
    -    unittest.main()
    

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

8

News mentions

0

No linked articles in our index yet.