Skip to content

Commit bf487f1

Browse files
Aryamanz29claude
andcommitted
fix: block sensitive file paths in FileClient.upload_file
Extend validate_file_path to reject: - System directories: /etc/, /proc/, /sys/, /dev/, /root/, macOS equivalents - Credential directories: .aws, .ssh, .gnupg anywhere in the resolved path - Environment/secret files: .env, .env.local, .env.production, etc. Raises new INVALID_UPLOAD_FILE_PATH_SENSITIVE error (ATLAN-PYTHON-400-078) for all sensitive path matches, in addition to the existing traversal check (ATLAN-PYTHON-400-077) for '..' components. Closes SEC-147 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 9f1b9ab commit bf487f1

3 files changed

Lines changed: 78 additions & 1 deletion

File tree

pyatlan/client/common/file.py

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,23 @@
33
from pathlib import Path
44
from typing import Any
55

6+
# System directories that must never be read from
7+
_SENSITIVE_SYSTEM_PREFIXES = (
8+
"/etc/",
9+
"/proc/",
10+
"/sys/",
11+
"/dev/",
12+
"/root/",
13+
"/private/etc/", # macOS: /etc is a symlink to /private/etc
14+
"/private/var/", # macOS
15+
)
16+
17+
# Hidden credential/config directories that must never be read from
18+
_SENSITIVE_DIR_NAMES = frozenset({".aws", ".ssh", ".gnupg"})
19+
20+
# File name prefixes for environment/secret files
21+
_SENSITIVE_FILE_PREFIXES = (".env",)
22+
623
from pyatlan.client.constants import (
724
API,
825
PRESIGNED_URL,
@@ -56,15 +73,40 @@ def validate_file_path(file_path: str) -> Any:
5673
:param file_path: path to the file to upload
5774
:returns: opened file object
5875
:raises INVALID_UPLOAD_FILE_PATH_TRAVERSAL: if path traversal is detected
76+
:raises INVALID_UPLOAD_FILE_PATH_SENSITIVE: if path points to a sensitive location
5977
:raises INVALID_UPLOAD_FILE_PATH: if file not found
6078
"""
6179
path = Path(file_path)
80+
81+
# Block directory traversal via '..'
6282
if ".." in path.parts:
6383
raise ErrorCode.INVALID_UPLOAD_FILE_PATH_TRAVERSAL.exception_with_parameters(
6484
file_path
6585
)
86+
87+
resolved = path.resolve()
88+
resolved_str = str(resolved)
89+
90+
# Block sensitive system directories (e.g. /etc/, /proc/, /dev/)
91+
if resolved_str.startswith(_SENSITIVE_SYSTEM_PREFIXES):
92+
raise ErrorCode.INVALID_UPLOAD_FILE_PATH_SENSITIVE.exception_with_parameters(
93+
file_path
94+
)
95+
96+
# Block credential/config hidden directories (e.g. .aws, .ssh, .gnupg)
97+
if any(part in _SENSITIVE_DIR_NAMES for part in resolved.parts):
98+
raise ErrorCode.INVALID_UPLOAD_FILE_PATH_SENSITIVE.exception_with_parameters(
99+
file_path
100+
)
101+
102+
# Block environment/secret files (e.g. .env, .env.local, .env.production)
103+
if resolved.name.startswith(_SENSITIVE_FILE_PREFIXES):
104+
raise ErrorCode.INVALID_UPLOAD_FILE_PATH_SENSITIVE.exception_with_parameters(
105+
file_path
106+
)
107+
66108
try:
67-
return open(path.resolve(), "rb")
109+
return open(resolved, "rb")
68110
except FileNotFoundError as err:
69111
raise ErrorCode.INVALID_UPLOAD_FILE_PATH.exception_with_parameters(
70112
str(err.strerror), file_path

pyatlan/errors.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -682,6 +682,13 @@ class ErrorCode(Enum):
682682
"Ensure the file path does not contain '..' components.",
683683
InvalidRequestError,
684684
)
685+
INVALID_UPLOAD_FILE_PATH_SENSITIVE = (
686+
400,
687+
"ATLAN-PYTHON-400-078",
688+
"Access to sensitive file path is not allowed: {0}.",
689+
"Ensure the file path does not point to sensitive system files or credential directories.",
690+
InvalidRequestError,
691+
)
685692
AUTHENTICATION_PASSTHROUGH = (
686693
401,
687694
"ATLAN-PYTHON-401-000",

tests/unit/test_file_client.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,13 +161,41 @@ def test_file_client_methods_validation_error(client, method, params):
161161
"Error: No such file or directory, Path: some/invalid/file_path.png"
162162
),
163163
],
164+
# Path traversal
164165
[
165166
"../../etc/passwd",
166167
(
167168
"ATLAN-PYTHON-400-077 Path traversal detected in file path: "
168169
r"\.\.\/\.\.\/etc\/passwd"
169170
),
170171
],
172+
# Sensitive system files
173+
[
174+
"/etc/passwd",
175+
"ATLAN-PYTHON-400-078 Access to sensitive file path is not allowed",
176+
],
177+
[
178+
"/etc/shadow",
179+
"ATLAN-PYTHON-400-078 Access to sensitive file path is not allowed",
180+
],
181+
# Credential directories
182+
[
183+
"/home/user/.aws/credentials",
184+
"ATLAN-PYTHON-400-078 Access to sensitive file path is not allowed",
185+
],
186+
[
187+
"/home/user/.ssh/id_rsa",
188+
"ATLAN-PYTHON-400-078 Access to sensitive file path is not allowed",
189+
],
190+
# Environment files
191+
[
192+
"/app/.env",
193+
"ATLAN-PYTHON-400-078 Access to sensitive file path is not allowed",
194+
],
195+
[
196+
"/app/.env.production",
197+
"ATLAN-PYTHON-400-078 Access to sensitive file path is not allowed",
198+
],
171199
],
172200
)
173201
def test_file_client_upload_file_raises_invalid_request_error(

0 commit comments

Comments
 (0)