Skip to content

Commit

Permalink
fix(security): validate the package name extracted from the part befo…
Browse files Browse the repository at this point in the history
…re the last hyphen (#77)
  • Loading branch information
frostming authored Oct 18, 2023
1 parent 0491f1b commit 09f4330
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 4 deletions.
29 changes: 25 additions & 4 deletions src/unearth/evaluator.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import dataclasses as dc
import hashlib
import logging
import os
import sys
from typing import Any

Expand Down Expand Up @@ -212,11 +213,31 @@ def evaluate_link(self, link: Link) -> Package | None:
raise LinkMismatchError(
f"Unsupported archive format: {link.filename}"
)
version = parse_version_from_egg_info(egg_info, self._canonical_name)
if version is None:
raise LinkMismatchError(
f"Missing version in the filename {egg_info}"
LOOSE_FILENAME = os.getenv(
"UNEARTH_LOOSE_FILENAME", "false"
).lower() in ("1", "true")
if LOOSE_FILENAME:
version = parse_version_from_egg_info(
egg_info, self._canonical_name
)
if version is None:
raise LinkMismatchError(
f"Missing version in the filename: {egg_info}"
)
else:
# For source releases, we know that the version should not contain
# any hyphens, so we can split on the last hyphen to get the
# project name.
filename_prefix, has_version, version = egg_info.rpartition("-")
if not has_version:
raise LinkMismatchError(
f"Missing version in the filename: {egg_info}"
)
if canonicalize_name(filename_prefix) != self._canonical_name:
raise LinkMismatchError(
f"The package name doesn't match {egg_info}, set env var "
"UNEARTH_LOOSE_FILENAME=1 to allow legacy filename."
)
try:
Version(version)
except InvalidVersion:
Expand Down
13 changes: 13 additions & 0 deletions tests/test_evaluator.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,19 @@ def test_evaluate_invalid_wheel_name(url):
assert evaluator.evaluate_link(link) is None


@pytest.mark.parametrize("loose", (True, False))
def test_evaluate_link_loose_filename(loose: bool, monkeypatch: pytest.MonkeyPatch):
if loose:
monkeypatch.setenv("UNEARTH_LOOSE_FILENAME", "1")
link = Link("https://test.pypi.org/files/foo-2-2.tar.gz")
evaluator = Evaluator("foo")
package = evaluator.evaluate_link(link)
if loose:
assert package.version == "2-2"
else:
assert package is None


@pytest.mark.parametrize(
"link,expected",
[
Expand Down

0 comments on commit 09f4330

Please sign in to comment.