Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion src/poetry/config/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
from poetry.config.config_source import split_key
from poetry.config.dict_config_source import DictConfigSource
from poetry.config.file_config_source import FileConfigSource
from poetry.exceptions import PoetryError
from poetry.locations import CONFIG_DIR
from poetry.locations import DEFAULT_CACHE_DIR
from poetry.locations import data_dir
Expand Down Expand Up @@ -345,7 +346,12 @@ def get(self, setting_name: str | Sequence[str], default: Any = None) -> Any:
env = "POETRY_" + "_".join(k.upper().replace("-", "_") for k in keys)
env_value = os.getenv(env)
if env_value is not None:
return self.process(self._get_normalizer(keys)(env_value))
try:
return self.process(self._get_normalizer(keys)(env_value))
except ValueError as e:
raise PoetryError(
f"Invalid value for {env}: {env_value!r}"
) from e

value = self._config

Expand Down
8 changes: 7 additions & 1 deletion src/poetry/console/commands/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -380,7 +380,13 @@ def _handle_single_value(
raise RuntimeError("You can only pass one value.")

value = values[0]
if not validator(value):
try:
valid = validator(value)
except ValueError:
# Some validators (e.g. those that parse integers) raise instead
# of returning False; surface them like any other invalid value.
valid = False
if not valid:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Medium · Invalid integers inject terminal controls

When a CI caller passes an invalid integer containing terminal escape sequences to poetry config, _handle_single_value now treats the validator’s ValueError as invalid input and reaches the direct f"{value}" error at config.py:390; the CLI emits embedded terminal control characters, allowing the supplied value to manipulate terminal output.

Escape terminal control characters in the displayed value before constructing the error message.

Prompt for AI agents
In `src/poetry/console/commands/config.py` at line 389:

**Invalid integers inject terminal controls**

When a CI caller passes an invalid integer containing terminal escape sequences to `poetry config`, `_handle_single_value` now treats the validator’s `ValueError` as invalid input and reaches the direct `f"{value}"` error at `config.py:390`; the CLI emits embedded terminal control characters, allowing the supplied value to manipulate terminal output.

Escape terminal control characters in the displayed value before constructing the error message.

raise RuntimeError(f'"{value}" is an invalid value for {key}')

source.add_property(key, normalizer(value))
Expand Down
13 changes: 13 additions & 0 deletions tests/config/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from poetry.config.config import boolean_normalizer
from poetry.config.config import int_normalizer
from poetry.config.config import str_list_normalizer
from poetry.exceptions import PoetryError
from poetry.utils.password_manager import PasswordManager
from tests.helpers import flatten_dict
from tests.helpers import isolated_environment
Expand All @@ -37,6 +38,18 @@ def get_options_based_on_normalizer(normalizer: Normalizer) -> Iterator[str]:
yield k


def test_invalid_integer_from_environment() -> None:
config = Config(use_environment=True)

with (
isolated_environment({"POETRY_REQUESTS_MAX_RETRIES": "abc"}),
pytest.raises(PoetryError) as e,
):
config.get("requests.max-retries")

assert str(e.value) == "Invalid value for POETRY_REQUESTS_MAX_RETRIES: 'abc'"


@pytest.mark.parametrize(
("value", "expected"),
[
Expand Down
17 changes: 17 additions & 0 deletions tests/console/commands/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,23 @@ def test_cannot_set_invalid_value(tester: CommandTester) -> None:
assert str(e.value) == '"foo" is an invalid value for virtualenvs.create'


@pytest.mark.parametrize(
("key", "value"),
[
("requests.max-retries", "abc"),
("installer.max-workers", "1.5"),
("solver.min-release-age", "abc"),
],
)
def test_cannot_set_invalid_integer_value(
tester: CommandTester, key: str, value: str
) -> None:
with pytest.raises(RuntimeError) as e:
tester.execute(f"{key} {value}")

assert str(e.value) == f'"{value}" is an invalid value for {key}'


def test_cannot_unset_with_value(tester: CommandTester) -> None:
with pytest.raises(RuntimeError) as e:
tester.execute("virtualenvs.create false --unset")
Expand Down
Loading