Skip to content

fix: avoid stage1 bootstrap stdlib shadowing#3854

Merged
aignas merged 8 commits into
bazel-contrib:mainfrom
gleyba:fix-stage1-stdlib-shadowing
Jul 1, 2026
Merged

fix: avoid stage1 bootstrap stdlib shadowing#3854
aignas merged 8 commits into
bazel-contrib:mainfrom
gleyba:fix-stage1-stdlib-shadowing

Conversation

@gleyba

@gleyba gleyba commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

The stage 1 system-python bootstrap imports standard-library modules before it
re-execs into the configured runtime. If the target output directory contains
files named like standard-library modules, such as shutil.py or types.py,
the bootstrap can import those files instead and fail before user code starts.

This change removes Python's unsafe script-directory prepend before those early
imports, while preserving sys.path[0] when Python has already suppressed that
prepend through -P/PYTHONSAFEPATH or isolated mode. Stage 2 now uses the same
isolated-mode guard when removing or recreating the main-directory path.

It also pins the Windows venv entry point template to LF line endings so the
compile-pip CI dirty-worktree check is stable across checkout settings.

Before this change, a generated target output could shadow bootstrap stdlib
imports, and isolated-mode runs on older Python versions could lose a required
stdlib path.

After this change, bootstrap stdlib imports resolve from the interpreter's
standard library, isolated mode preserves the interpreter-provided path, and the
line-ending-sensitive CI check stays clean.

Tests:

bazel test --config=fast-tests \
  //tests/bootstrap_impls:stdlib_shadowing_system_python_test

bazel test --config=fast-tests \
  //tests/bootstrap_impls:stdlib_shadowing_system_python_test \
  //tests/bootstrap_impls:interpreter_args_test \
  //tests/bootstrap_impls:sys_path_order_bootstrap_script_test

Remove the launcher directory from sys.path before the Python stage1 bootstrap imports stdlib modules. Generated target outputs can otherwise shadow stdlib modules such as shutil.py before the bootstrap re-execs into the configured runtime.

Preserve sys.path when Python is already running in safe-path mode.

Add a regression test that places generated shutil.py and types.py outputs beside a system_python bootstrap launcher.
@gleyba gleyba requested review from aignas and rickeylev as code owners June 26, 2026 23:36

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request prevents target output files from shadowing standard library modules during the stage 1 bootstrap process by removing the script's directory from sys.path when sys.flags.safe_path is false. It also adds a test case to verify this behavior. Feedback suggests also checking sys.flags.isolated before modifying sys.path to avoid removing critical system paths when Python is run in isolated mode.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread python/private/python_bootstrap_template.txt Outdated

@aignas aignas left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Please also add a news/3854.fixed.md file to describe the fix.

Comment thread python/private/python_bootstrap_template.txt
Comment thread .gitattributes Outdated
@gleyba gleyba requested a review from aignas June 29, 2026 18:23
@aignas aignas added this pull request to the merge queue Jul 1, 2026
Merged via the queue into bazel-contrib:main with commit fbb2ccf Jul 1, 2026
6 checks passed
@rickeylev rickeylev mentioned this pull request Jul 1, 2026
8 tasks
rickeylev pushed a commit to rickeylev/rules_python that referenced this pull request Jul 1, 2026
The stage 1 system-python bootstrap imports standard-library modules
before it
re-execs into the configured runtime. If the target output directory
contains
files named like standard-library modules, such as `shutil.py` or
`types.py`,
the bootstrap can import those files instead and fail before user code
starts.

This change removes Python's unsafe script-directory prepend before
those early
imports, while preserving `sys.path[0]` when Python has already
suppressed that
prepend through `-P`/`PYTHONSAFEPATH` or isolated mode. Stage 2 now uses
the same
isolated-mode guard when removing or recreating the main-directory path.

It also pins the Windows venv entry point template to LF line endings so
the
compile-pip CI dirty-worktree check is stable across checkout settings.

Before this change, a generated target output could shadow bootstrap
stdlib
imports, and isolated-mode runs on older Python versions could lose a
required
stdlib path.

After this change, bootstrap stdlib imports resolve from the
interpreter's
standard library, isolated mode preserves the interpreter-provided path,
and the
line-ending-sensitive CI check stays clean.

Tests:

```shell
bazel test --config=fast-tests \
  //tests/bootstrap_impls:stdlib_shadowing_system_python_test

bazel test --config=fast-tests \
  //tests/bootstrap_impls:stdlib_shadowing_system_python_test \
  //tests/bootstrap_impls:interpreter_args_test \
  //tests/bootstrap_impls:sys_path_order_bootstrap_script_test
```

(cherry picked from commit fbb2ccf)
rickeylev pushed a commit that referenced this pull request Jul 1, 2026
The stage 1 system-python bootstrap imports standard-library modules
before it
re-execs into the configured runtime. If the target output directory
contains
files named like standard-library modules, such as `shutil.py` or
`types.py`,
the bootstrap can import those files instead and fail before user code
starts.

This change removes Python's unsafe script-directory prepend before
those early
imports, while preserving `sys.path[0]` when Python has already
suppressed that
prepend through `-P`/`PYTHONSAFEPATH` or isolated mode. Stage 2 now uses
the same
isolated-mode guard when removing or recreating the main-directory path.

It also pins the Windows venv entry point template to LF line endings so
the
compile-pip CI dirty-worktree check is stable across checkout settings.

Before this change, a generated target output could shadow bootstrap
stdlib
imports, and isolated-mode runs on older Python versions could lose a
required
stdlib path.

After this change, bootstrap stdlib imports resolve from the
interpreter's
standard library, isolated mode preserves the interpreter-provided path,
and the
line-ending-sensitive CI check stays clean.

Tests:

```shell
bazel test --config=fast-tests \
  //tests/bootstrap_impls:stdlib_shadowing_system_python_test

bazel test --config=fast-tests \
  //tests/bootstrap_impls:stdlib_shadowing_system_python_test \
  //tests/bootstrap_impls:interpreter_args_test \
  //tests/bootstrap_impls:sys_path_order_bootstrap_script_test
```

(cherry picked from commit fbb2ccf)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants