Apr 9, 2026·7 min read·3 visits
Authenticated path traversal in AGiXT < 1.9.2 allows users to escape agent workspaces and access the host filesystem, resulting in arbitrary file read, write, and delete capabilities.
A path traversal vulnerability exists in the safe_join() function of the essential_abilities extension in AGiXT prior to version 1.9.2. An authenticated attacker can exploit this flaw to read, write, or delete arbitrary files on the host system, bypassing intended agent workspace restrictions.
AGiXT is an AI agent automation platform that utilizes an extension system to grant capabilities to designated agents. One core extension is essential_abilities, which handles fundamental agent interactions with the local environment, including reading, writing, modifying, and deleting files. To ensure security, these file operations are intended to be strictly sandboxed within a dedicated workspace directory for each agent.
A path traversal vulnerability (CWE-22) exists within the path resolution logic of this extension, specifically inside the safe_join() function. This function fails to adequately restrict user-supplied paths to the bounds of the intended workspace directory. By injecting directory traversal sequences into file manipulation commands, an attacker can coerce the application into operating on files outside the sandbox.
The vulnerability affects all versions of the agixt PyPI package prior to version 1.9.2. Because the agent file operations include write and delete capabilities, the impact extends beyond mere information disclosure. Successful exploitation compromises the confidentiality, integrity, and availability of the host system.
Exploitation requires the attacker to possess a valid API key to communicate with the AGiXT instance. The attacker must also have sufficient permissions to invoke file-related agent commands via the exposed REST API endpoints. No user interaction or complex exploitation chaining is required to trigger the vulnerability.
The root cause of this vulnerability lies in the implementation of the safe_join() function within agixt/extensions/essential_abilities.py. The function attempts to construct an absolute path by concatenating the designated workspace directory (self.WORKING_DIRECTORY) with an array of user-supplied path segments. The developer intended to sanitize this input using standard Python path manipulation libraries.
In the vulnerable implementation, the function relies on os.path.normpath and os.path.join to construct the final file path. The relevant code evaluates os.path.normpath(os.path.join(self.WORKING_DIRECTORY, *paths.split("/"))). While os.path.normpath collapses redundant separators and resolves up-level references (../), it does not inherently restrict the final resolved path to a specific prefix directory.
When a user supplies a payload containing sufficient ../ sequences, os.path.normpath resolves the path entirely outside of self.WORKING_DIRECTORY. Because the function subsequently returns this normalized path without validating that it remains a child of the workspace directory, the application implicitly trusts the malicious path. Any calling function utilizing safe_join() will then perform file I/O operations on the attacker-controlled location.
The vulnerability flow begins at the API edge. The agixt/endpoints/Extension.py endpoint accepts user-supplied JSON containing command_args. This payload is routed through the main execution engine in agixt/XT.py to the target extension. Once the essential_abilities extension receives the payload, it invokes safe_join() with the malicious filename argument, executing the filesystem operation out-of-bounds.
Analyzing the vulnerable implementation reveals a fundamental misunderstanding of Python's os.path module constraints. The following snippet illustrates the flawed logic present in versions prior to 1.9.2.
# Vulnerable implementation in essential_abilities.py
def safe_join(self, paths) -> str:
# Normalization occurs, but boundary enforcement is absent
new_path = os.path.normpath(os.path.join(self.WORKING_DIRECTORY, *paths.split("/")))
return new_pathIf self.WORKING_DIRECTORY is /opt/agixt/workspace/ and the user provides ../../etc/passwd, os.path.join creates /opt/agixt/workspace/../../etc/passwd. The os.path.normpath function then evaluates the ../ directives, resolving the path to /opt/etc/passwd or /etc/passwd depending on the directory depth. The function blindly returns this escaped path.
The patch introduced in version 1.9.2 addresses this by employing absolute path resolution alongside rigorous prefix validation. The updated code resolves both the intended base directory and the user-requested path to their absolute canonical forms using os.path.realpath.
# Patched implementation in essential_abilities.py (v1.9.2)
def safe_join(self, paths) -> str:
# Determine the canonical absolute path of the workspace
base = os.path.realpath(self.WORKING_DIRECTORY)
# Determine the canonical absolute path of the requested file
new_path = os.path.realpath(
os.path.normpath(os.path.join(self.WORKING_DIRECTORY, *paths.split("/")))
)
# CRITICAL FIX: Verify the resolved path remains inside the workspace boundary
if not (new_path.startswith(base + os.sep) or new_path == base):
raise PermissionError(
f"Path traversal detected: refusing to access path outside workspace"
)
return new_pathThis remediation strategy is robust. By invoking os.path.realpath, symlinks and all relative path sequences are fully expanded before validation. The strict .startswith(base + os.sep) check guarantees that the requested file resides completely within the directory tree of the designated workspace, neutralizing the traversal primitive entirely.
Exploiting this vulnerability requires network access to the AGiXT instance and a valid API token. The attacker leverages the /api/agent/{agent_name}/command endpoint to invoke built-in extensions. Specifically, the attacker targets commands that invoke the vulnerable safe_join() function, such as read_file, write_to_file, modify_file, and delete_file.
The HTTP request consists of a standard POST request with a JSON body defining the command name and its arguments. The attacker injects the directory traversal payload directly into the filename argument. The depth of the traversal sequence (../) must be sufficient to escape the agent's workspace directory and reach the filesystem root.
Upon processing the request, the application backend resolves the malicious path and performs the requested operation. In a file read scenario, the application returns the contents of the target file in the JSON response payload. The following Python script serves as a proof-of-concept for retrieving /etc/passwd from an affected instance.
import requests
BASE = "http://localhost:7437"
TOKEN = "<your_api_key>"
headers = {"Authorization": f"Bearer {TOKEN}"}
payload = {
"command_name": "read_file",
"command_args": {
"filename": "../../../../../../../etc/passwd"
}
}
r = requests.post(f"{BASE}/api/agent/MyAgent/command", json=payload, headers=headers)
print(r.text)This exploitation methodology is highly reliable and does not depend on memory corruption or race conditions. The API response will contain the raw text of the target file, confirming successful exploitation. To escalate the attack, an adversary could modify the payload to target write_to_file, supplying a malicious cron job or SSH key in the command arguments.
The impact of this vulnerability is severe, meriting a CVSS 3.1 score of 8.8 (CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H). The primary consequence is total loss of filesystem boundaries for the authenticated user. The attacker gains the same file access permissions as the underlying operating system user executing the AGiXT process.
The confidentiality impact is High. Attackers can read arbitrary files on the host, including sensitive environment variables, platform configuration files, database credentials, and cryptographic keys. Accessing files such as /etc/shadow or .ssh/id_rsa can immediately compromise the host system and adjacent infrastructure.
The integrity and availability impacts are also High due to the vulnerability affecting file write and delete operations. An attacker can overwrite existing system files, delete crucial application dependencies, or corrupt databases stored on disk. This allows for trivial denial-of-service against the application or the underlying system.
Furthermore, the write capability provides a direct path to Remote Code Execution (RCE). By writing executable files to critical locations (e.g., cron directories, .ssh/authorized_keys, or overwriting Python files in the application's site-packages), an attacker can achieve persistent, arbitrary code execution on the host server.
The most effective remediation is to upgrade the agixt package to version 1.9.2 or later. This release contains the patch that fundamentally resolves the vulnerability by introducing proper path canonicalization and prefix verification. Development teams should verify their requirements.txt or pipfile explicitly pins agixt>=1.9.2.
If an immediate upgrade is not possible, network administrators can deploy Web Application Firewall (WAF) rules to detect and block malicious requests targeting the application API. Rules should inspect JSON payloads sent to the /api/agent/*/command endpoints and block requests where the filename parameter contains traversal sequences such as ../, ..\, or URL-encoded variants (..%2f).
Security teams should actively monitor application logs for indicators of compromise. The patch introduced in version 1.9.2 emits a PermissionError containing the string "Path traversal detected". Administrators running patched versions should alert on this exception, as it indicates an active, albeit unsuccessful, exploitation attempt.
To proactively detect vulnerable instances within an organization, security engineers can deploy targeted scanning templates. A custom Nuclei template can be constructed to fuzz the filename argument of the read_file command. The template should authenticate using a known test API key and verify if the response body contains contents indicative of local system files, such as root:x:0:0.
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H| Product | Affected Versions | Fixed Version |
|---|---|---|
agixt Josh-XT | < 1.9.2 | 1.9.2 |
| Attribute | Detail |
|---|---|
| CWE | CWE-22 (Improper Limitation of a Pathname to a Restricted Directory) |
| Attack Vector | Network |
| CVSS Score | 8.8 (High) |
| Privileges Required | Low (Authenticated) |
| Impact | Arbitrary File Read/Write/Delete |
| Exploit Status | Proof of Concept Available |
Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')