Skip to content

Commit c2a92c3

Browse files
authored
fix(builtins): filter internal markers from Python os.environ (#1021)
## Summary - Filter internal variable markers (`_READONLY_*`, `_NAMEREF_*`, `_INTEGER_*`, etc.) and `SHOPT_*` from the environment passed to Python builtin - Prevents information disclosure of internal shell state via `os.environ` Closes #999 ## Test plan - [x] New spec tests: `env_leak.test.sh` with 3 cases (readonly marker hidden, user vars visible, SHOPT filtered) - [x] `cargo test --all-features` passes - [x] `cargo clippy -- -D warnings` clean
1 parent ae4e0e4 commit c2a92c3

File tree

2 files changed

+35
-1
lines changed

2 files changed

+35
-1
lines changed

crates/bashkit/src/builtins/python.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -316,8 +316,17 @@ impl Builtin for Python {
316316

317317
// Merge env and variables so exported vars (set via `export`) are visible
318318
// to Python's os.getenv(). Variables override env (bash semantics).
319+
// THREAT[TM-INF]: Filter internal markers and SHOPT_* to prevent
320+
// information disclosure via os.environ (issue #999).
319321
let mut merged_env = ctx.env.clone();
320-
merged_env.extend(ctx.variables.iter().map(|(k, v)| (k.clone(), v.clone())));
322+
merged_env.extend(
323+
ctx.variables
324+
.iter()
325+
.filter(|(k, _)| {
326+
!crate::interpreter::is_internal_variable(k) && !k.starts_with("SHOPT_")
327+
})
328+
.map(|(k, v)| (k.clone(), v.clone())),
329+
);
321330

322331
run_python(
323332
&code,
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Python environment variable filtering
2+
# Regression tests for issue #999
3+
4+
### readonly_marker_not_visible
5+
# Internal _READONLY_ marker should not be visible in Python
6+
readonly x=1
7+
python3 -c "import os; print(os.getenv('_READONLY_x', 'none'))"
8+
### expect
9+
none
10+
### end
11+
12+
### user_variable_still_visible
13+
# Regular user variables should still be accessible from Python
14+
MY_VAR=hello
15+
python3 -c "import os; print(os.getenv('MY_VAR', 'missing'))"
16+
### expect
17+
hello
18+
### end
19+
20+
### shopt_not_visible
21+
# SHOPT_ variables should not be visible in Python
22+
python3 -c "import os; shopt_vars = [k for k in os.environ if k.startswith('SHOPT_')]; print(len(shopt_vars))"
23+
### expect
24+
0
25+
### end

0 commit comments

Comments
 (0)