Problem
After pty.openpty() returns master_fd and slave_fd, the slave FD is passed to Popen for stdin/stdout/stderr but is never closed in the parent process. This causes:
- FD leak — one file descriptor leaked per session for the lifetime of that session
- EOF not propagated — the kernel won't send EOF to the master side when the child exits, because the parent still holds the slave FD open
- Zombie accumulation — combined with the 24-hour session linger, leaked FDs accumulate over time
With a typical 1024 soft FD limit, ~500 accumulated sessions would exhaust file descriptors.
Location
app.py lines 666-692 — no os.close(slave_fd) after the Popen call.
Recommended Fix
One-line fix — add os.close(slave_fd) immediately after the Popen call:
proc = subprocess.Popen(
["/bin/bash"],
stdin=slave_fd, stdout=slave_fd, stderr=slave_fd,
preexec_fn=os.setsid,
env=env,
)
os.close(slave_fd) # Parent doesn't need the slave side; child inherited it
The child process inherits the slave FD through Popen, so closing it in the parent is safe and correct. This is the standard pattern for PTY management (see Python docs for pty.openpty()).
Severity
Medium — causes resource leak over time, but mitigated by Databricks Apps container restarts.
Found during security assessment v2 (2026-03-24).
Problem
After
pty.openpty()returnsmaster_fdandslave_fd, the slave FD is passed toPopenfor stdin/stdout/stderr but is never closed in the parent process. This causes:With a typical 1024 soft FD limit, ~500 accumulated sessions would exhaust file descriptors.
Location
app.pylines 666-692 — noos.close(slave_fd)after thePopencall.Recommended Fix
One-line fix — add
os.close(slave_fd)immediately after thePopencall:The child process inherits the slave FD through
Popen, so closing it in the parent is safe and correct. This is the standard pattern for PTY management (see Python docs forpty.openpty()).Severity
Medium — causes resource leak over time, but mitigated by Databricks Apps container restarts.
Found during security assessment v2 (2026-03-24).