Skip to content
Draft
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
4 changes: 4 additions & 0 deletions .evergreen/run-mongodb-aws-ecs-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ apt-get -qq update < /dev/null > /dev/null
apt-get -q install -y build-essential

export SET_XTRACE_ON=1
export CI=true
# Install from the uv.lock generated on the host (which has git); this
# container doesn't, so it must not try to resolve mockupdb itself.
export UV_FROZEN=1
cd src
rm -rf .venv
rm -f .evergreen/scripts/test-env.sh || true
Expand Down
5 changes: 5 additions & 0 deletions .evergreen/run-tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ else
fi

# Start the test runner.
# UV_FROZEN means a uv.lock was already generated where git is available
# (e.g. for the ecs remote host); don't fight it by disabling lock usage.
if [ -z "${UV_FROZEN:-}" ]; then
export UV_NO_LOCK=1
fi
echo "Running tests with UV_PYTHON=${UV_PYTHON:-}..."
echo "UV_ARGS=${UV_ARGS}"
uv run ${UV_ARGS} --reinstall-package pymongo .evergreen/scripts/run_tests.py "$@"
Expand Down
7 changes: 0 additions & 7 deletions .evergreen/scripts/configure-env.sh
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,6 @@ UV_TOOL_DIR=$PROJECT_DIRECTORY/.local/uv/tools
UV_CACHE_DIR=$PROJECT_DIRECTORY/.local/uv/cache
DRIVERS_TOOLS_BINARIES="$DRIVERS_TOOLS/.bin"
MONGODB_BINARIES="$DRIVERS_TOOLS/mongodb/bin"
# GNU date on Linux and Windows, BSD date on macOS.
UV_EXCLUDE_NEWER="$(date -u -d '7 days ago' +%Y-%m-%d 2>/dev/null || date -u -v-7d +%Y-%m-%d)"
if [ -z "$UV_EXCLUDE_NEWER" ]; then
echo "Failed to compute UV_EXCLUDE_NEWER" >&2
exit 1
fi

# On Evergreen jobs, "CI" will be set, and we don't want to write to $HOME.
if [ "${CI:-}" == "true" ]; then
Expand Down Expand Up @@ -72,7 +66,6 @@ export UV_TOOL_DIR="$UV_TOOL_DIR"
export UV_CACHE_DIR="$UV_CACHE_DIR"
export UV_TOOL_BIN_DIR="$DRIVERS_TOOLS_BINARIES"
export UV_NO_LOCK=1
export UV_EXCLUDE_NEWER="$UV_EXCLUDE_NEWER"
export PYMONGO_BIN_DIR="$PYMONGO_BIN_DIR"
export PATH="$PATH_EXT"
# shellcheck disable=SC2154
Expand Down
8 changes: 4 additions & 4 deletions .evergreen/scripts/kms_tester.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ def _setup_azure_vm(base_env: dict[str, str]) -> None:
env["AZUREKMS_CMD"] = "sudo apt-get install -y python3-dev build-essential"
run_command(f"{azure_dir}/run-command.sh", env=env)

env["AZUREKMS_CMD"] = "bash .evergreen/just.sh setup-tests kms azure-remote"
env["AZUREKMS_CMD"] = "CI=true bash .evergreen/just.sh setup-tests kms azure-remote"
run_command(f"{azure_dir}/run-command.sh", env=env)
LOGGER.info("Setting up Azure VM... done.")

Expand All @@ -53,7 +53,7 @@ def _setup_gcp_vm(base_env: dict[str, str]) -> None:
env["GCPKMS_CMD"] = "sudo apt-get install -y python3-dev build-essential"
run_command(f"{gcp_dir}/run-command.sh", env=env)

env["GCPKMS_CMD"] = "bash ./.evergreen/just.sh setup-tests kms gcp-remote"
env["GCPKMS_CMD"] = "CI=true bash ./.evergreen/just.sh setup-tests kms gcp-remote"
run_command(f"{gcp_dir}/run-command.sh", env=env)
LOGGER.info("Setting up GCP VM...")

Expand Down Expand Up @@ -128,10 +128,10 @@ def test_kms_send_to_remote(sub_test_name: str) -> None:
key_name = os.environ["KEY_NAME"]
key_vault_endpoint = os.environ["KEY_VAULT_ENDPOINT"]
env["AZUREKMS_CMD"] = (
f'KEY_NAME="{key_name}" KEY_VAULT_ENDPOINT="{key_vault_endpoint}" bash ./.evergreen/just.sh run-tests'
f'KEY_NAME="{key_name}" KEY_VAULT_ENDPOINT="{key_vault_endpoint}" CI=true bash ./.evergreen/just.sh run-tests'
)
else:
env["GCPKMS_CMD"] = "./.evergreen/just.sh run-tests"
env["GCPKMS_CMD"] = "CI=true ./.evergreen/just.sh run-tests"
cmd = f"{DIRS[sub_test_name]}/run-command.sh"
run_command(cmd, env=env)

Expand Down
4 changes: 4 additions & 0 deletions .evergreen/scripts/run_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,10 @@ def run() -> None:

# Send ecs tests to run remotely.
if TEST_NAME == "auth_aws" and SUB_TEST_NAME == "ecs":
# Lock dependencies here, where git is available, so the ecs
# container (which has no git) can install from the lock frozen,
# without needing to resolve mockupdb's git dependency itself.
run_command("uv lock", cwd=ROOT)
run_command(f"{DRIVERS_TOOLS}/.evergreen/auth_aws/aws_setup.sh ecs")
return

Expand Down
10 changes: 5 additions & 5 deletions .evergreen/scripts/setup-dev-env.sh
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,13 @@ fi
# Ensure dependencies are installed.
bash $HERE/install-dependencies.sh

# Add the default install path to the path if needed.
if [ -z "${PYMONGO_BIN_DIR:-}" ]; then
export PATH="$PATH:$HOME/.local/bin"
fi

# Only run the next part if not running on CI.
if [ -z "${CI:-}" ]; then
# Add the default install path to the path if needed.
if [ -z "${PYMONGO_BIN_DIR:-}" ]; then
export PATH="$PATH:$HOME/.local/bin"
fi

# Set up venv, making sure c extensions build unless disabled.
if [ -z "${NO_EXT:-}" ]; then
export PYMONGO_C_EXT_MUST_BUILD=1
Expand Down
6 changes: 6 additions & 0 deletions .evergreen/scripts/setup-tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ if [ -f $SCRIPT_DIR/env.sh ]; then
source $SCRIPT_DIR/env.sh
fi

# UV_FROZEN means a uv.lock was already generated where git is available
# (e.g. for the ecs remote host); don't fight it by disabling lock usage.
if [ -z "${UV_FROZEN:-}" ]; then
export UV_NO_LOCK=1
fi

echo "Setting up tests with args \"$*\"..."
uv run ${USE_ACTIVE_VENV:+--active} "$SCRIPT_DIR/setup_tests.py" "$@"
echo "Setting up tests with args \"$*\"... done."
3 changes: 0 additions & 3 deletions justfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,6 @@ set shell := ["bash", "-c"]

# Don't let `uv` create or read uv.lock.
export UV_NO_LOCK := "1"
# Match CI's resolution window so local installs agree.
# GNU date on Linux and Windows, BSD date on macOS.
export UV_EXCLUDE_NEWER := `date -u -d '7 days ago' +%Y-%m-%d 2>/dev/null || date -u -v-7d +%Y-%m-%d`

# Commonly used command segments.
typing_run := "uv run --group typing --extra aws --extra encryption --with numpy --extra ocsp --extra snappy --extra test --extra zstd"
Expand Down
7 changes: 7 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,13 @@ Documentation = "https://www.mongodb.com/docs/languages/python/pymongo-driver/cu
Source = "https://github.com/mongodb/mongo-python-driver"
Tracker = "https://jira.mongodb.org/projects/PYTHON/issues"

[tool.uv]
# Only sync the (empty) dev group by default; groups like mockupdb require
# an explicit --group flag so hosts without git aren't forced to resolve it.
default-groups = ["dev"]
Comment on lines +49 to +52

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Semgrep identified an issue in your code:

[tool.uv] has no exclude-newer setting, so uv may immediately install freshly published dependency versions. That lets a malicious new release of packages like gevent, simplejson, or ruff reach developer or CI environments right away.

More details about this

[tool.uv] sets default-groups = ["dev"] but does not set exclude-newer, so uv can resolve package versions published moments earlier during installs or syncs. In this project, a developer or CI job running uv sync could pull a just-uploaded release for dependencies such as gevent, coverage, simplejson, typing_extensions, or even tooling like ruff and mypy.

A plausible attack looks like this:

  1. An attacker compromises a package maintainer account or publishes a malicious dependency version that satisfies one of these version ranges, for example simplejson>=3.17.0 or gevent>=21.12.
  2. They upload the bad release to the package index and wait for this repository to run uv sync or another uv resolution step using this [tool.uv] configuration.
  3. Because [tool.uv] has no exclude-newer, uv is allowed to select that brand-new version immediately.
  4. The malicious package then runs in the developer or CI environment during install or import, letting the attacker steal tokens, read source code, or alter test/build output.

Without a cooldown in this exact uv config block, the project has no buffer period to avoid freshly published dependency versions that may be malicious or unstable.

To resolve this comment:

✨ Commit fix suggestion
  1. Add a dependency cooldown to the [tool.uv] section by inserting exclude-newer = "7 days" alongside the existing settings.
  2. Keep the existing default-groups = ["dev"] entry as-is, so the section looks like [tool.uv] ... default-groups = ["dev"] ... exclude-newer = "7 days".
  3. Use at least 7 days for this value; do not use a smaller number or a different format. This makes uv avoid resolving packages published too recently.
💬 Ignore this finding

Reply with Semgrep commands to ignore this finding.

  • /fp <comment> for false positive
  • /ar <comment> for acceptable risk
  • /other <comment> for all other reasons

Alternatively, triage in Semgrep AppSec Platform to ignore the finding created by uv-missing-dependency-cooldown.

🛟 Help? Slack #semgrep-help or go/semgrep-help.

Resolution Options:

  • Fix the code
  • Reply /fp $reason (if security gap doesn’t exist)
  • Reply /ar $reason (if gap is valid but intentional; add mitigations/monitoring)
  • Reply /other $reason (e.g., test-only)

You can view more details about this finding in the Semgrep AppSec Platform.

# Wait 7 days before resolving newly published package versions.
exclude-newer = "7 days"

[dependency-groups]
dev = []
lint = [
Expand Down
Loading