Skip to content

Commit 918f094

Browse files
authored
fix: prevent path traversal for message_id in file_session_manager (#728)
* fix: prevent path traversal for message_id in file_session_manager * fix: prevent path traversal for message_id in session managers * fix: prevent path traversal for message_id in session managers
1 parent e5e308f commit 918f094

File tree

4 files changed

+51
-4
lines changed

4 files changed

+51
-4
lines changed

src/strands/session/file_session_manager.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,13 @@ def _get_message_path(self, session_id: str, agent_id: str, message_id: int) ->
8686
message_id: Index of the message
8787
Returns:
8888
The filename for the message
89+
90+
Raises:
91+
ValueError: If message_id is not an integer.
8992
"""
93+
if not isinstance(message_id, int):
94+
raise ValueError(f"message_id=<{message_id}> | message id must be an integer")
95+
9096
agent_path = self._get_agent_path(session_id, agent_id)
9197
return os.path.join(agent_path, "messages", f"{MESSAGE_PREFIX}{message_id}.json")
9298

src/strands/session/s3_session_manager.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,11 +113,16 @@ def _get_message_path(self, session_id: str, agent_id: str, message_id: int) ->
113113
session_id: ID of the session
114114
agent_id: ID of the agent
115115
message_id: Index of the message
116-
**kwargs: Additional keyword arguments for future extensibility.
117116
118117
Returns:
119118
The key for the message
119+
120+
Raises:
121+
ValueError: If message_id is not an integer.
120122
"""
123+
if not isinstance(message_id, int):
124+
raise ValueError(f"message_id=<{message_id}> | message id must be an integer")
125+
121126
agent_path = self._get_agent_path(session_id, agent_id)
122127
return f"{agent_path}messages/{MESSAGE_PREFIX}{message_id}.json"
123128

tests/strands/session/test_file_session_manager.py

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -224,14 +224,14 @@ def test_read_messages_with_new_agent(file_manager, sample_session, sample_agent
224224
file_manager.create_session(sample_session)
225225
file_manager.create_agent(sample_session.session_id, sample_agent)
226226

227-
result = file_manager.read_message(sample_session.session_id, sample_agent.agent_id, "nonexistent_message")
227+
result = file_manager.read_message(sample_session.session_id, sample_agent.agent_id, 999)
228228

229229
assert result is None
230230

231231

232232
def test_read_nonexistent_message(file_manager, sample_session, sample_agent):
233233
"""Test reading a message that doesnt exist."""
234-
result = file_manager.read_message(sample_session.session_id, sample_agent.agent_id, "nonexistent_message")
234+
result = file_manager.read_message(sample_session.session_id, sample_agent.agent_id, 999)
235235
assert result is None
236236

237237

@@ -390,3 +390,21 @@ def test__get_session_path_invalid_session_id(session_id, file_manager):
390390
def test__get_agent_path_invalid_agent_id(agent_id, file_manager):
391391
with pytest.raises(ValueError, match=f"agent_id={agent_id} | id cannot contain path separators"):
392392
file_manager._get_agent_path("session1", agent_id)
393+
394+
395+
@pytest.mark.parametrize(
396+
"message_id",
397+
[
398+
"../../../secret",
399+
"../../attack",
400+
"../escape",
401+
"path/traversal",
402+
"not_an_int",
403+
None,
404+
[],
405+
],
406+
)
407+
def test__get_message_path_invalid_message_id(message_id, file_manager):
408+
"""Test that message_id that is not an integer raises ValueError."""
409+
with pytest.raises(ValueError, match=r"message_id=<.*> \| message id must be an integer"):
410+
file_manager._get_message_path("session1", "agent1", message_id)

tests/strands/session/test_s3_session_manager.py

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,7 @@ def test_read_nonexistent_message(s3_manager, sample_session, sample_agent, samp
251251
s3_manager.create_agent(sample_session.session_id, sample_agent)
252252

253253
# Read message
254-
result = s3_manager.read_message(sample_session.session_id, sample_agent.agent_id, "nonexistent_message")
254+
result = s3_manager.read_message(sample_session.session_id, sample_agent.agent_id, 999)
255255

256256
assert result is None
257257

@@ -356,3 +356,21 @@ def test__get_session_path_invalid_session_id(session_id, s3_manager):
356356
def test__get_agent_path_invalid_agent_id(agent_id, s3_manager):
357357
with pytest.raises(ValueError, match=f"agent_id={agent_id} | id cannot contain path separators"):
358358
s3_manager._get_agent_path("session1", agent_id)
359+
360+
361+
@pytest.mark.parametrize(
362+
"message_id",
363+
[
364+
"../../../secret",
365+
"../../attack",
366+
"../escape",
367+
"path/traversal",
368+
"not_an_int",
369+
None,
370+
[],
371+
],
372+
)
373+
def test__get_message_path_invalid_message_id(message_id, s3_manager):
374+
"""Test that message_id that is not an integer raises ValueError."""
375+
with pytest.raises(ValueError, match=r"message_id=<.*> \| message id must be an integer"):
376+
s3_manager._get_message_path("session1", "agent1", message_id)

0 commit comments

Comments
 (0)