openai / openai/openai-agents-python

Sandbox tar extraction and 12 sandbox tests fail on Windows without symlink privilege

Open
#4,852 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

feature:sandboxes project
Dominant language
Python
Stars
29.6k
Forks
4.8k
Avg merge
1d 20h
Merged PRs (30d)
123

Description

Running the sandbox suite on Windows as a normal, non-elevated user:

tests/sandbox/test_tar_utils.py + test_workspace_paths.py:
12 failed, 93 passed, 15 skipped
All twelve fail with OSError: [WinError 1314] A required privilege is not held by the client. Windows permits symlink creation only for an elevated process or with Developer Mode enabled — neither is the default.

They split into two distinct problems.

  1. Product: safe_extract_tarfile cannot extract archives containing symlinks
    Seven of the failures originate in library code, not test setup:

tests/sandbox/test_tar_utils.py:75: in _safe_extract
src/agents/sandbox/util/tar_utils.py:468: in safe_extract_tarfile

E   OSError: [WinError 1314] A required privilege is not held by the client:
    '/usr/local/bin/python3' -> '...\link.txt'
tar_utils.py:468:

    for member in members:
        if not member.issym():
            continue
        rel_path = safe_tar_member_rel_path(member, allow_symlinks=True)
        if rel_path is None:
            continue
        dest = root_resolved / rel_path
        _prepare_replaceable_leaf(dest=dest, rel_path=rel_path, name=member.name)
        os.symlink(member.linkname, dest)

There is no platform handling anywhere in that file. So on an ordinary Windows machine, extracting any archive that contains a symlink member raises, aborting the extraction partway — after the regular files have already been written.

Affected tests, all exercising real extraction behaviour:

test_safe_extract_tarfile_can_rehydrate_existing_leaf_symlink
test_safe_extract_tarfile_can_replace_existing_leaf_file_with_symlink
test_safe_extract_tarfile_can_replace_existing_leaf_symlink_with_file
test_safe_extract_tarfile_can_replace_existing_leaf_symlink_with_directory
test_safe_extract_tarfile_rejects_preexisting_symlink_parent
test_safe_extract_tarfile_rejects_symlink_under_preexisting_symlink_parent
(and one more in the same file)

I have deliberately not proposed a patch for this half. The sandbox has security semantics around symlinks — safe_tar_member_rel_path(..., allow_symlinks=True), escape rejection, _prepare_replaceable_leaf — and the options each carry different meaning:

Skip symlink members on Windows. Extraction completes, but the result silently differs from the archive, which may matter for a sandbox that later validates paths.
Raise a clear, typed error. Honest, but still fails the operation.
Materialise as a copy of the target. Preserves content, changes escape semantics — a copy cannot point outside the root, so some of the existing protections become moot.
Which of those is right is a maintainer decision, not one I should make from outside.

  1. Tests: unguarded symlink creation in test setup
    The other five come from the tests themselves, e.g. tests/sandbox/test_workspace_paths.py:798:

os.symlink(target, workspace / "link.txt")
Nothing guards these, and there is no module-level skip or marker.

test_normalize_path_with_symlink_resolution
test_host_io_rejects_write_under_resolved_read_only_extra_path_grant
test_host_io_rejects_extra_path_grant_symlink_to_root
test_host_path_grant_rejects_symlink_to_root
test_host_path_grant_returns_validated_resolved_source

This half is straightforward and I am happy to submit a PR: a small symlink_or_skip() helper used at the affected call sites, so the tests skip with a clear reason where the platform refuses rather than erroring. That is the same approach psf/black uses for its symlink tests.

Why CI doesn't catch either
tests-windows in .github/workflows/tests.yml runs uv run pytest — the full suite, including tests/sandbox/ — on windows-latest, and it is green. GitHub's Windows runners can create symlinks; an ordinary user cannot. So both problems are invisible to CI on the very platform it covers, and appear only on a contributor's or user's machine.

Environment
Windows-11-10.0.26200-SP0
Python 3.13.15
openai-agents-python at HEAD, uv sync dev environment
Non-elevated shell, Developer Mode off

Reproduction

git clone https://github.com/openai/openai-agents-python
cd openai-agents-python
uv sync
uv run pytest tests/sandbox/test_tar_utils.py tests/sandbox/test_workspace_paths.py

Note: a wider tests/sandbox/ run also reports failures in test_docker.py, test_docker_network_mode.py and test_mount_security.py, but those are a missing docker module in my environment and are unrelated to this report.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Run the reproduction against tests/sandbox/test_tar_utils.py and tests/sandbox/test_workspace_paths.py on a non-elevated Windows setup. Read src/agents/sandbox/util/tar_utils.py, especially safe_extract_tarfile and its symlink helpers, then review the listed symlink call sites in test_workspace_paths.py. Done means the maintainer-approved symlink behavior is covered and unsupported test setups skip clearly without hiding other failures.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
operating-systems, security, testing-qa
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
52/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.