Skip to content

fix: add cwd to sandbox read allowlist - #835

Open
pasmud wants to merge 1 commit into
DataDog:v3from
pasmud:pasmud/fix-818-sandbox-cwd
Open

fix: add cwd to sandbox read allowlist#835
pasmud wants to merge 1 commit into
DataDog:v3from
pasmud:pasmud/fix-818-sandbox-cwd

Conversation

@pasmud

@pasmud pasmud commented Jul 31, 2026

Copy link
Copy Markdown

Summary

Fix local archive scans failing under the kernel-level sandbox with a misleading "not a gzip file" ReadError.

tarsafe calls os.getcwd() during archive extraction to bound path-traversal checks. The sandbox allowlist in guarddog/sandbox.py (_get_common_read_paths) never included the current working directory, so on platforms where the sandbox denies access to it (macOS Seatbelt), that call raises PermissionError. tarfile wraps it and reports "not a gzip file".

Changes

  • guarddog/sandbox.py: add os.getcwd() to the candidate read paths in _get_common_read_paths, alongside sys.prefix, /usr, /lib and the other always-readable paths.
  • tests/core/test_sandbox.py: test that the cwd is included in the common read paths.

Test plan

  • pytest tests/core/test_sandbox.py: 11 passed.
  • pytest tests/core: 190 passed, 2 skipped.
  • Sandboxed scan of a local npm tarball from an arbitrary cwd succeeds (guarddog npm scan lodash.tgz, no --no-sandbox).

Notes

Fixes #818

tarsafe calls os.getcwd() during archive extraction to bound path-traversal
checks. The kernel-level sandbox never granted READ on the current working
directory, so on platforms where the sandbox denies it (macOS Seatbelt) the
PermissionError surfaced through tarfile as a misleading 'not a gzip file'
ReadError. Grant READ on the cwd like the other common paths.
@pasmud
pasmud requested a review from a team as a code owner July 31, 2026 14:34
@christophetd

Copy link
Copy Markdown
Contributor

lgtm, adding a quick Codex review in case I missed anything then I'll merge, thanks for the contribution!

@christophetd

Copy link
Copy Markdown
Contributor

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1ebb5d2b6d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread guarddog/sandbox.py
# extraction to bound path-traversal checks. Without READ access here
# that call fails with PermissionError, which tarfile misreports as
# "not a gzip file".
candidates.append(os.getcwd())

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Do not expose the entire launch directory

When GuardDog is launched from a sensitive directory such as the user's home or a repository root, allow_path grants recursive READ access to that entire tree in both apply_sandbox and extract_sandboxed. This defeats the documented filesystem isolation for archive/parser exploits and can expose credentials or source files unrelated to the scan; satisfy tarsafe's getcwd() requirement by changing into an already-allowed temporary/extraction directory rather than globally allowlisting the caller's cwd.

Useful? React with 👍 / 👎.

Comment thread guarddog/sandbox.py
# extraction to bound path-traversal checks. Without READ access here
# that call fails with PermissionError, which tarfile misreports as
# "not a gzip file".
candidates.append(os.getcwd())

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Handle an unavailable current directory

When the process's working directory has been renamed or deleted after startup, os.getcwd() raises FileNotFoundError, so every sandboxed scan now fails while constructing the common allowlist—even remote scans whose inputs and temporary directories remain valid. Catch OSError here and omit the cwd, or obtain it only in the archive path that actually requires it.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[bug] Local archive scan fails with "not a gzip file" / ReadError under kernel-level sandbox

2 participants