Skip to content

Commit aff3034

Browse files
Network Cloud CLi - Fixing zip-slip vulnerability in custom operations (#9282)
* Removing unsupported commands from the managednetworkfabric CLI. * updating history * Network Cloud CLi - Fixing zip-slip vulnerability * updating history and setup.py versions * linting fixes
1 parent c58fd97 commit aff3034

File tree

3 files changed

+31
-3
lines changed

3 files changed

+31
-3
lines changed

src/networkcloud/HISTORY.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33
Release History
44
===============
55

6+
4.0.0b2
7+
++++++++
8+
* Fixing zip/slip vulnerability in our custom_operations code.
9+
610
4.0.0b1
711
++++++++
812
* This beta version supports NetworkCloud 2025-07-01-preview APIs.

src/networkcloud/azext_networkcloud/operations/custom_properties.py

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,30 @@ def _get_az_command():
8787
class CustomActionProperties:
8888
"""Helper class for all POST commands that return extra properties back to the customer"""
8989

90+
@staticmethod
91+
def is_within_directory(directory, target):
92+
"""
93+
Ensure the target path is within the intended directory
94+
"""
95+
abs_directory = os.path.abspath(directory)
96+
abs_target = os.path.abspath(target)
97+
return os.path.commonpath([abs_directory]) == os.path.commonpath(
98+
[abs_directory, abs_target]
99+
)
100+
101+
@staticmethod
102+
def safe_extract(tar, path="."):
103+
"""
104+
Validates each file's path before extraction to prevent malicious files from escaping the target directory
105+
"""
106+
for member in tar.getmembers():
107+
member_path = os.path.join(path, member.name)
108+
if not CustomActionProperties.is_within_directory(path, member_path):
109+
raise ValueError(
110+
f"Path traversal detected: {member_path} is outside target directory {path}"
111+
)
112+
tar.extractall(path)
113+
90114
# Custom handling of response will display the output head and the result_URL/result_ref
91115
# it will also save files into output directory if provided
92116
@staticmethod
@@ -120,7 +144,7 @@ def _output(parent_cmd, *args, **kwargs): # pylint: disable=unused-argument
120144
try:
121145
with urllib.request.urlopen(result_url) as result:
122146
with tarfile.open(fileobj=result, mode="r:gz") as tar:
123-
tar.extractall(path=output_directory)
147+
CustomActionProperties.safe_extract(tar, output_directory)
124148
logger.warning(
125149
"Extracted results are available in directory: %s",
126150
output_directory,
@@ -190,7 +214,7 @@ def _output(parent_cmd, *args, **kwargs): # pylint: disable=unused-argument
190214
try:
191215
# Extract the downloaded blob
192216
with tarfile.open(downloaded_blob_name, mode="r:gz") as tar:
193-
tar.extractall(path=output_directory)
217+
CustomActionProperties.safe_extract(tar, output_directory)
194218
logger.warning(
195219
"Extracted results are available in directory: %s",
196220
output_directory,

src/networkcloud/setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111

1212
# HISTORY.rst entry.
13-
VERSION = '4.0.0b1'
13+
VERSION = '4.0.0b2'
1414

1515
# The full list of classifiers is available at
1616
# https://pypi.python.org/pypi?%3Aaction=list_classifiers

0 commit comments

Comments
 (0)