Skip to content

bug: slave FD leak in parent process after pty.openpty() #78

@datasciencemonkey

Description

@datasciencemonkey

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:

  1. FD leak — one file descriptor leaked per session for the lifetime of that session
  2. 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
  3. 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).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions