bazel-contrib / bazel-contrib/rules_python

py_binary system_python bootstrap can import target outputs instead of stdlib modules

Open
#3,853 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
Starlark
Stars
688
Forks
721
Avg merge
14h 49m
Merged PRs (30d)
81

Description

# 🐞 bug report

### Affected Rule

The issue is caused by the rule:

`py_binary` when using the Python stage1 bootstrap selected by
`--@rules_python//python/config_settings:bootstrap_impl=system_python`.

The problem is in `python/private/python_bootstrap_template.txt`: stage1 imports
stdlib modules before removing the launcher's directory from `sys.path[0]`.

### Is this a regression?

Unknown. Reproduced with rules_python `main` at
`2.1.0-rc0-11-g1a15c3b4`.

### Description

A clear and concise description of the problem...

The generated Python stage1 bootstrap imports stdlib modules while Python still
has the launcher directory at `sys.path[0]`. If the target package has generated
outputs next to the launcher with stdlib module names, those target files can be
imported instead of the Python standard library before rules_python finishes
bootstrap setup.

In the minimal reproduction below, the target generates `shutil.py` and
`types.py` next to the launcher in `bazel-bin/shadow_pkg/`. When stage1 executes,
its `import shutil` resolves to the generated target output instead of stdlib
`shutil`.

This is similar in root cause to
https://github.com/bazel-contrib/rules_python/issues/382, but this report is
specifically about stdlib shadowing inside the generated stage1 bootstrap before
the user's program runs.

## 🔬 Minimal Reproduction

Minimal local reproduction:

```text
/av/develop/tmp/rules_python_reproductions/stdlib_shadowing
```

The repro uses `local_path_override` to point at:

```text
/av/develop/tmp/rules_python
```

Relevant files:

```starlark
# .bazelrc
build --@rules_python//python/config_settings:bootstrap_impl=system_python
```

```starlark
# shadow_pkg/BUILD.bazel
load("@rules_python//python:py_binary.bzl", "py_binary")

genrule(
name = "generated_stdlib_modules",
outs = [
"shutil.py",
"types.py",
],
cmd = """
cat > $(@D)/shutil.py <<'PY'
raise RuntimeError('target output shutil.py shadowed the stdlib shutil module')
PY
cat > $(@D)/types.py <<'PY'
raise RuntimeError('target output types.py shadowed the stdlib types module')
PY
""",
)

py_binary(
name = "hello",
srcs = [
"main.py",
":generated_stdlib_modules",
],
main = "main.py",
)
```

```python
# shadow_pkg/main.py
print("hello from main")
```

Run:

```bash
bazel run //shadow_pkg:hello
```

Expected result:

```text
hello from main
```

Actual result:

The bootstrap fails before `main.py` runs because it imports generated
`bazel-bin/shadow_pkg/shutil.py` instead of stdlib `shutil`.

## 🔥 Exception or Error



Traceback (most recent call last):
File ".../execroot/_main/bazel-out/k8-fastbuild/bin/shadow_pkg/hello", line 12, in <module>
import shutil
File ".../execroot/_main/bazel-out/k8-fastbuild/bin/shadow_pkg/shutil.py", line 1, in <module>
raise RuntimeError('target output shutil.py shadowed the stdlib shutil module')
RuntimeError: target output shutil.py shadowed the stdlib shutil module

## 🌍 Your Environment

**Operating System:**

  

Linux gkolobkov 6.8.0-124-generic #124-Ubuntu SMP PREEMPT_DYNAMIC Tue May 26 13:00:45 UTC 2026 x86_64 x86_64 x86_64 GNU/Linux

**Output of `bazel version`:**

  

Bazelisk version: v1.27.0
Build label: 9.1.1
Build target: @@//src/main/java/com/google/devtools/build/lib/bazel:BazelServer
Build time: Wed Jun 03 15:41:13 2026 (1780501273)
Build timestamp: 1780501273
Build timestamp as int: 1780501273

**Rules_python version:**

  

rules_python main at 2.1.0-rc0-11-g1a15c3b4

**Anything else relevant?**

The issue is avoided if Python safe-path mode is enabled:

```bash
PYTHONSAFEPATH=1 bazel run //shadow_pkg:hello
```

That succeeds and prints:

```text
hello from main
```

This suggests the stage1 bootstrap should remove the unsafe `sys.path[0]` entry
before importing any stdlib modules, or otherwise ensure safe-path behavior for
the stage1 process.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.