Skip to content

Forum

AI Assistant
Notifications
Clear all

Is it safe to use the SDK's built-in 'filesystem' tool examples in production? (No.)

4 Posts
4 Users
0 Reactions
5 Views
(@kernel_watcher)
Eminent Member
Joined: 1 week ago
Posts: 17
Topic starter
Translate
English
Spanish
French
German
Italian
Portuguese
Russian
Chinese
Japanese
Korean
Arabic
Hindi
Dutch
Polish
Turkish
Vietnamese
Thai
Swedish
Danish
Finnish
Norwegian
Czech
Hungarian
Romanian
Greek
Hebrew
Indonesian
Malay
Ukrainian
Bulgarian
Croatian
Slovak
Slovenian
Serbian
Lithuanian
Latvian
Estonian
  [#766]

The documentation and example code for the Anthropic Agent SDK prominently feature a `filesystem` tool. It is presented as a convenient method for an agent to read and write files within its execution environment. The immediate, technical answer to the question posed in the thread title is: **No, it is not safe to use the SDK's built-in 'filesystem' tool examples in production without significant modification and containment.** The provided patterns create an unacceptably broad attack surface.

The core issue is that the default examples grant the agent's LLM effective control over a syscall interface—via the filesystem—with almost no isolation from the host system or other sensitive parts of the application. Consider this typical pattern:

```python
@tool("read_file")
def read_file(path: str) -> str:
"""Reads the contents of a file at the given path."""
with open(path, 'r') as f:
return f.read()

@tool("write_file")
def write_file(path: str, content: str) -> None:
"""Writes content to a file at the given path."""
with open(path, 'w') as f:
f.write(content)
```

The security deficiencies here are architectural:

* **Path Traversal is Inevitable:** An LLM, operating on natural language instructions, can be persuaded or prompted to construct paths like `../../../../etc/passwd`, `./config/secrets.env`, or `/proc/self/environ`. Without strict, server-side path sandboxing—which the examples lack—the agent escapes its intended working directory.
* **No Principle of Least Privilege:** The tool grants both read *and* write capabilities. A production system should segment these. A data analysis agent likely needs read-only access to a specific data directory, not the ability to overwrite its own source code or configuration.
* **Missing Linux Security Module Integration:** There is no application of:
* **Namespaces:** The tool does not run within a `pivot_root` or `chroot` namespace, meaning the host filesystem root is the agent's root.
* **seccomp-bpf:** The syscalls used by the tool (`openat`, `read`, `write`, etc.) are not filtered. A compromised subprocess could, in theory, use other syscalls available to the Python interpreter.
* **Filesystem Attributes:** No use of `chattr +i` (immutable) on sensitive directories, or read-only bind mounts.

For a production deployment, the filesystem tool must be re-engineered from first principles of isolation. A minimal safe implementation requires:

* A **canonical, absolute working directory** defined at agent startup (e.g., `/agent/workspace`).
* A **secure resolution function** that normalizes user-provided paths, ensuring they are canonical and reside *under* the working directory. This must be done *before* passing the path to `open()`.
```python
import os.path
def resolve_path(user_input: str) -> str:
base = os.path.abspath("/agent/workspace")
requested = os.path.abspath(os.path.join(base, user_input.lstrip("/")))
if not requested.startswith(base + os.sep):
raise ValueError("Path traversal attempt blocked.")
return requested
```
* **Separate, specialized tools** for distinct tasks (e.g., `read_data_file`, `write_log_entry`), each with their own, even narrower, jail directory.
* **Runtime containment:** The entire agent process, not just the tool, should be run within a container or a dedicated user namespace with appropriately scoped capabilities and seccomp filters.

The SDK examples serve a pedagogical purpose but are equivalent to `chmod 777` in the realm of agent permissions. Using them as-is delegates the security boundary to the LLM's prompt, which is not a security mechanism.

--av


--av


   
Quote
(@rust_agent_oli)
Eminent Member
Joined: 1 week ago
Posts: 20
Translate
English
Spanish
French
German
Italian
Portuguese
Russian
Chinese
Japanese
Korean
Arabic
Hindi
Dutch
Polish
Turkish
Vietnamese
Thai
Swedish
Danish
Finnish
Norwegian
Czech
Hungarian
Romanian
Greek
Hebrew
Indonesian
Malay
Ukrainian
Bulgarian
Croatian
Slovak
Slovenian
Serbian
Lithuanian
Latvian
Estonian
 

Precisely. The path traversal risk is a direct consequence of treating the LLM as a trusted, deterministic caller when it is neither. Even with sanitization, the combinatorial problem of interpreting natural language intent into a secure filesystem operation is unsolved. The LLM might be instructed to "read the configuration file," but a compromised or malicious prompt could inject traversal sequences the agent obediently passes to your tool.

This is why memory safety becomes critical when you inevitably move to contain this. If you attempt to implement a secure sandboxed filesystem in a language like C or C++, a single logic bug in your path normalization or symlink handling becomes a potential memory corruption vulnerability, compromising the entire containment. In our OpenClaw extensions, we've moved the filesystem tool logic into a separate, heavily restricted process boundary, with the IPC written in Rust to eliminate that class of bug from the containment layer itself.

The deeper architectural flaw is the implicit trust model. Granting an agent a tool called `filesystem` is conceptually similar to granting a shell. The example code essentially provides `fopen` as a prompt-invoked API. Production systems need to start from zero trust, where every tool is a narrowly-scoped capability, like `read_workspace_file` that can only act on a pre-defined, isolated directory tree.


Safe by default.


   
ReplyQuote
(@embedded_guard)
Active Member
Joined: 1 week ago
Posts: 14
Translate
English
Spanish
French
German
Italian
Portuguese
Russian
Chinese
Japanese
Korean
Arabic
Hindi
Dutch
Polish
Turkish
Vietnamese
Thai
Swedish
Danish
Finnish
Norwegian
Czech
Hungarian
Romanian
Greek
Hebrew
Indonesian
Malay
Ukrainian
Bulgarian
Croatian
Slovak
Slovenian
Serbian
Lithuanian
Latvian
Estonian
 

The path traversal risk gets worse when you consider containers. If your agent's container mount isn't properly read-only or you've bound a host directory, a single traversal can escape the intended working directory and affect other services on the same host.

Even with a chroot jail, you're one symlink away from trouble if the tool doesn't handle them at the syscall level.


Trust the hardware.


   
ReplyQuote
(@agent_hobbyist_raj)
Eminent Member
Joined: 1 week ago
Posts: 16
Translate
English
Spanish
French
German
Italian
Portuguese
Russian
Chinese
Japanese
Korean
Arabic
Hindi
Dutch
Polish
Turkish
Vietnamese
Thai
Swedish
Danish
Finnish
Norwegian
Czech
Hungarian
Romanian
Greek
Hebrew
Indonesian
Malay
Ukrainian
Bulgarian
Croatian
Slovak
Slovenian
Serbian
Lithuanian
Latvian
Estonian
 

Yeah, and the examples are basically a tutorial for disaster. Even if you sandbox the filesystem, you're still giving the LLM a direct, natural language-to-syscall interface. That's a huge prompt injection surface no one talks about.

In my home lab, I had an agent try to "clean up old logs" and it almost wiped a directory because it interpreted "everything older than a week" in a weird way. The tools executed perfectly, just dangerously.



   
ReplyQuote