anthropics / anthropics/sandbox-runtime

denyRead for ".." and friends

Open
#79 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
TypeScript
Stars
5.2k
Forks
439
Avg merge
2d 9m
Merged PRs (30d)
13

Description

# @anthropic-ai/sandbox-runtime (srt) - Relative Path Issue Analysis

## Problem Summary

The `@anthropic-ai/sandbox-runtime` (srt) does not properly support relative paths like `..` and `../..` in `denyRead` configurations. When such paths are specified, the sandbox **changes the current working directory to the user's home directory** instead of maintaining the expected directory.

## Root Cause

When `denyRead: ["..", "../..", ...]` is configured:

1. **Relative paths are normalized to absolute paths** – The `normalizePathForSandbox()` function converts `..` to the absolute parent directory (e.g., `/tmp` when in `/tmp/srt_test2`)

2. **`denyRead` mounts tmpfs over denied paths** – On Linux, when a path is in `denyRead`, the sandbox mounts a `tmpfs` filesystem over that directory (or `/dev/null` over files) to hide its contents

3. **Mounting tmpfs over parent directories breaks path resolution** – When `/tmp` is covered by tmpfs, the path `/tmp/srt_test2` no longer resolves correctly. The kernel's current directory reference becomes invalid

4. **The sandbox falls back to `$HOME`** – Instead of handling this gracefully, the sandbox/shell changes the working directory to your home directory, causing `pwd` and file operations to behave unexpectedly

## Evidence

### Test Configuration
```json
{
"filesystem": {
"denyRead": [".."],
"allowWrite": ["."],
"denyWrite": []
},
"network": {
"allowedDomains": [],
"deniedDomains": []
}
}
```

### Results
- **`pwd`** returns `/home/username` instead of `/tmp/srt_test2`
- **`ls -la`** shows home directory contents, not the expected directory
- **Files in the original directory become inaccessible**
- **Both relative (`..`) and absolute (`/tmp`) paths** exhibit the same behavior

### Test Commands
```bash
# With denyRead: [".."]
$ srt --settings config.json "pwd"
/home/username

$ srt --settings config.json "ls -la"
# Shows home directory contents

# Without denyRead
$ srt --settings config2.json "pwd"
/tmp/srt_test2
```

## Underlying Code Issues

### 1. Path Normalization (`sandbox-utils.js`)
```javascript
function normalizePathForSandbox(pathPattern) {
const cwd = process.cwd();
// ...
else if (pathPattern.startsWith('./') || pathPattern.startsWith('../')) {
// Convert relative to absolute based on current working directory
normalizedPath = path.resolve(cwd, pathPattern);
}
// ...
}
```
Relative paths are converted to absolute paths based on `process.cwd()` at sandbox initialization time.

### 2. Linux bwrap Implementation (`linux-sandbox-utils.js`)
```javascript
async function generateFilesystemArgs(readConfig, writeConfig, ...) {
// ...
const readDenyPaths = [...(readConfig?.denyOnly || [])];
for (const pathPattern of readDenyPaths) {
const normalizedPath = normalizePathForSandbox(pathPattern);
if (!fs.existsSync(normalizedPath)) {
// ...
continue;
}
const readDenyStat = fs.statSync(normalizedPath);
if (readDenyStat.isDirectory()) {
args.push('--tmpfs', normalizedPath); // Mounts tmpfs over denied directory
} else {
args.push('--ro-bind', '/dev/null', normalizedPath);
}
}
return args;
}
```
This overlays tmpfs on denied directories, making subdirectories inaccessible.

### 3. Missing `--chdir` in bwrap Arguments
The sandbox doesn't explicitly preserve the working directory with bwrap's `--chdir` option, allowing it to change when path resolution fails.

## Related Issues

This is part of a broader pattern of filesystem path handling problems in srt:

- **GitHub Issue #72**: "allowWrite patterns don't work for nested directories on macOS (git clone fails)" – similar path resolution issues
- **Glob patterns on Linux**: The implementation filters out glob patterns on Linux, limiting expressiveness
- **Symlink handling**: The normalization resolves symlinks, which can cause unexpected behavior

## Workarounds

1. **Use absolute paths** instead of relative paths in configurations
2. **Avoid `denyRead` on parent directories** of your working directory
3. **Set explicit `allowWrite` paths** that don't conflict with `denyRead` rules
4. **Consider the working directory** when designing sandbox policies

## Security Implications

While the sandbox still provides security isolation (denied paths remain inaccessible), the unexpected change in working directory can:
- Cause confusion and misconfiguration
- Potentially lead to unintended file access if scripts rely on relative paths
- Break tools that depend on the current working directory

## Conclusion

The `@anthropic-ai/sandbox-runtime` doesn't properly support relative paths like `..` and `../..` because its security model (mounting tmpfs over denied directories) conflicts with maintaining a valid current working directory. When parent directories are denied read access, path resolution fails and the sandbox falls back to the user's home directory rather than preserving or gracefully handling the invalid working directory state.

This appears to be a design limitation rather than a simple bug, requiring architectural changes to properly support relative path restrictions while maintaining working directory integrity.

---

**Investigation Date**: 2025-01-27
**srt Version**: 0.0.19
**Test Platform**: Linux
Description written by an llm, but the issue is real!

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.