Files
nltk--nltk/nltk/test/unit/test_repp_security.py
wehub-resource-sync 3454a55636
cffconvert / validate (push) Has been cancelled
ci-workflow / pre-commit (push) Has been cancelled
ci-workflow / Minimal NLTK Download Test (macos-latest) (push) Has been cancelled
ci-workflow / Minimal NLTK Download Test (ubuntu-latest) (push) Has been cancelled
ci-workflow / Minimal NLTK Download Test (windows-latest) (push) Has been cancelled
ci-workflow / Python 3.10 on macos-latest (push) Has been cancelled
ci-workflow / Python 3.11 on macos-latest (push) Has been cancelled
ci-workflow / Python 3.12 on macos-latest (push) Has been cancelled
ci-workflow / Python 3.13 on macos-latest (push) Has been cancelled
ci-workflow / Python 3.14 on macos-latest (push) Has been cancelled
ci-workflow / Python 3.14t on macos-latest (push) Has been cancelled
ci-workflow / Python 3.10 on ubuntu-latest (push) Has been cancelled
ci-workflow / Python 3.11 on ubuntu-latest (push) Has been cancelled
ci-workflow / Python 3.12 on ubuntu-latest (push) Has been cancelled
ci-workflow / Python 3.13 on ubuntu-latest (push) Has been cancelled
ci-workflow / Python 3.14 on ubuntu-latest (push) Has been cancelled
ci-workflow / Python 3.14t on ubuntu-latest (push) Has been cancelled
ci-workflow / Python 3.10 on windows-latest (push) Has been cancelled
ci-workflow / Python 3.11 on windows-latest (push) Has been cancelled
ci-workflow / Python 3.12 on windows-latest (push) Has been cancelled
ci-workflow / Python 3.13 on windows-latest (push) Has been cancelled
ci-workflow / Python 3.14 on windows-latest (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:46:15 +08:00

70 lines
2.6 KiB
Python

"""Regression tests for the untrusted-search-path fix in ReppTokenizer (CWE-426).
``find_repptokenizer`` used ``os.path.exists(repp_dirname)`` to accept a directory
as-is. For a *relative* ``repp_dirname`` that resolves against the current working
directory and is checked *before* the ``REPP_TOKENIZER`` environment variable, so
an attacker who can write a ``./<name>/src/repp`` executable into the CWD could
have it run (the command path contains a separator, so ``subprocess`` executes it
directly) -- overriding a trusted ``REPP_TOKENIZER``.
Only an explicit *absolute* directory is now taken as-is; a relative name is
resolved through ``REPP_TOKENIZER``.
"""
import os
import pathlib
import pytest
from nltk.tokenize.repp import ReppTokenizer
def _make_repp_dir(path):
(path / "src").mkdir(parents=True, exist_ok=True)
(path / "erg").mkdir(parents=True, exist_ok=True)
(path / "src" / "repp").write_bytes(b"")
(path / "erg" / "repp.set").write_bytes(b"")
return path
def test_relative_dirname_not_resolved_against_cwd(tmp_path, monkeypatch):
"""A relative repp_dirname matching a CWD directory must NOT be used."""
cwd = tmp_path / "cwd"
cwd.mkdir()
_make_repp_dir(cwd / "reppdir") # attacker-planted in the CWD
monkeypatch.chdir(cwd)
monkeypatch.delenv("REPP_TOKENIZER", raising=False)
with pytest.raises(LookupError):
ReppTokenizer("reppdir")
def test_cwd_does_not_override_configured_repp_tokenizer(tmp_path, monkeypatch):
"""A CWD directory must not shadow a configured REPP_TOKENIZER."""
cwd = tmp_path / "cwd"
cwd.mkdir()
_make_repp_dir(cwd / "reppdir") # attacker-planted in the CWD
trusted = _make_repp_dir(tmp_path / "trusted") # the configured location
monkeypatch.chdir(cwd)
monkeypatch.setenv("REPP_TOKENIZER", str(trusted))
tok = ReppTokenizer("reppdir")
assert os.path.realpath(tok.repp_dir) == os.path.realpath(
str(trusted)
), "CWD directory overrode the trusted REPP_TOKENIZER"
def test_absolute_path_still_accepted(tmp_path, monkeypatch):
"""An explicit absolute directory is still used as-is, incl. as a Path."""
abs_dir = _make_repp_dir(tmp_path / "absrepp")
monkeypatch.delenv("REPP_TOKENIZER", raising=False)
assert os.path.realpath(ReppTokenizer(str(abs_dir)).repp_dir) == os.path.realpath(
str(abs_dir)
)
# a pathlib.Path is accepted too (normalised via os.fspath) and resolves to
# the same directory.
assert os.path.realpath(
ReppTokenizer(pathlib.Path(abs_dir)).repp_dir
) == os.path.realpath(str(abs_dir))