Skip to content

Commit 0f164f9

Browse files
authored
Validate stream name in add_stream method (#607)
Signed-off-by: ff137 <[email protected]>
1 parent 938ba32 commit 0f164f9

File tree

2 files changed

+47
-2
lines changed

2 files changed

+47
-2
lines changed

nats/js/manager.py

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,12 +91,26 @@ async def add_stream(
9191
if config is None:
9292
config = api.StreamConfig()
9393
config = config.evolve(**params)
94-
if config.name is None:
94+
95+
stream_name = config.name
96+
if stream_name is None:
9597
raise ValueError("nats: stream name is required")
9698

99+
# Validate stream name
100+
invalid_chars = set(".*>/\\")
101+
has_invalid_chars = any(char in stream_name for char in invalid_chars)
102+
has_whitespace = any(char.isspace() for char in stream_name)
103+
is_not_printable = not stream_name.isprintable()
104+
105+
if has_invalid_chars or has_whitespace or is_not_printable:
106+
raise ValueError(
107+
f"nats: stream name ({stream_name}) is invalid. Names cannot contain whitespace, '.', '*', '>', "
108+
"path separators (forward or backward slash), or non-printable characters."
109+
)
110+
97111
data = json.dumps(config.as_dict())
98112
resp = await self._api_request(
99-
f"{self._prefix}.STREAM.CREATE.{config.name}",
113+
f"{self._prefix}.STREAM.CREATE.{stream_name}",
100114
data.encode(),
101115
timeout=self._timeout,
102116
)

tests/test_js.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import io
1313
import tempfile
1414
from unittest.mock import AsyncMock
15+
import re
1516

1617
import pytest
1718
import nats
@@ -4367,3 +4368,33 @@ async def test_fetch_pull_subscribe_bind(self):
43674368
assert str(err.value) == 'nats: stream name is required'
43684369

43694370
await nc.close()
4371+
4372+
4373+
class BadStreamNamesTest(SingleJetStreamServerTestCase):
4374+
@async_test
4375+
async def test_add_stream_invalid_names(self):
4376+
nc = NATS()
4377+
await nc.connect()
4378+
js = nc.jetstream()
4379+
4380+
invalid_names = [
4381+
"stream name with spaces",
4382+
"stream.name.with.dots",
4383+
"stream*name*with*asterisks",
4384+
"stream>name>with>greaterthans",
4385+
"stream/name/with/forwardslashes",
4386+
"stream\\name\\with\\backslashes",
4387+
"stream\nname\nwith\nnewlines",
4388+
"stream\tname\twith\ttabs",
4389+
"stream\x00name\x00with\x00nulls",
4390+
]
4391+
4392+
for name in invalid_names:
4393+
with pytest.raises(
4394+
ValueError,
4395+
match=(
4396+
f"nats: stream name \\({re.escape(name)}\\) is invalid. Names cannot contain whitespace, '\\.', "
4397+
"'\\*', '>', path separators \\(forward or backward slash\\), or non-printable characters."
4398+
),
4399+
):
4400+
await js.add_stream(name=name)

0 commit comments

Comments
 (0)