Skip to content

Commit 7c0e36e

Browse files
author
Max Azatian
committed
JWT_SECRET_KEY fix 4: regex instead of separate function
1 parent 7551313 commit 7c0e36e

File tree

2 files changed

+12
-42
lines changed

2 files changed

+12
-42
lines changed

backend/app/config.py

Lines changed: 6 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,18 @@
22

33
from app.runtime_registry import EXAMPLE_SCRIPTS as EXEC_EXAMPLE_SCRIPTS
44
from app.runtime_registry import SUPPORTED_RUNTIMES as RUNTIME_MATRIX
5-
from pydantic import Field, field_validator
5+
from pydantic import Field
66
from pydantic_settings import BaseSettings
77

88

99
class Settings(BaseSettings):
1010
PROJECT_NAME: str = "integr8scode"
1111
API_V1_STR: str = "/api/v1"
12-
SECRET_KEY: str = Field(default=None)
12+
SECRET_KEY: str = Field(
13+
...,
14+
min_length=32,
15+
regex="^(?!your_secret_key_here$|default_secret_key$).*$"
16+
)
1317
ALGORITHM: str = "HS256"
1418
ACCESS_TOKEN_EXPIRE_MINUTES: int = 30
1519
MONGODB_URL: str = "mongodb://mongo:27017/integr8scode"
@@ -43,25 +47,6 @@ class Settings(BaseSettings):
4347

4448
TESTING: bool = False
4549

46-
@field_validator("SECRET_KEY")
47-
@classmethod
48-
def validate_secret_key(cls, v: Optional[str], info) -> str:
49-
if not v:
50-
raise ValueError("SECRET_KEY environment variable must be set")
51-
if len(v) < 32:
52-
raise ValueError("SECRET_KEY must be at least 32 characters long")
53-
54-
# Check if we're in testing mode
55-
testing = info.data.get('TESTING', False)
56-
57-
# Allow CHANGE_ME prefix only in development/testing
58-
if v == "your_secret_key_here" or v == "default_secret_key":
59-
raise ValueError("SECRET_KEY must not use default placeholder values")
60-
if v.startswith("CHANGE_ME") and not testing:
61-
raise ValueError("SECRET_KEY must not use default placeholder values (CHANGE_ME detected)")
62-
63-
return v
64-
6550
class Config:
6651
env_file = ".env"
6752

backend/tests/unit/test_config.py

Lines changed: 6 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ def test_secret_key_missing(self) -> None:
1616
errors = exc_info.value.errors()
1717
assert len(errors) == 1
1818
assert errors[0]["loc"] == ("SECRET_KEY",)
19-
assert "SECRET_KEY environment variable must be set" in errors[0]["msg"]
19+
assert "Field required" in errors[0]["msg"]
2020

2121
def test_secret_key_too_short(self) -> None:
2222
with mock.patch.dict(os.environ, {"SECRET_KEY": "short_key"}, clear=True):
@@ -26,39 +26,24 @@ def test_secret_key_too_short(self) -> None:
2626
errors = exc_info.value.errors()
2727
assert len(errors) == 1
2828
assert errors[0]["loc"] == ("SECRET_KEY",)
29-
assert "SECRET_KEY must be at least 32 characters long" in errors[0]["msg"]
29+
assert "at least 32 characters" in errors[0]["msg"]
3030

3131
def test_secret_key_default_placeholder(self) -> None:
3232
# These should always fail
3333
test_cases = ["your_secret_key_here", "default_secret_key"]
3434

3535
for placeholder in test_cases:
36-
with mock.patch.dict(os.environ, {"SECRET_KEY": placeholder}, clear=True):
36+
# Pad to 32 chars to avoid length error
37+
padded_placeholder = placeholder.ljust(32, 'x')
38+
with mock.patch.dict(os.environ, {"SECRET_KEY": padded_placeholder}, clear=True):
3739
with pytest.raises(ValidationError) as exc_info:
3840
Settings()
3941

4042
errors = exc_info.value.errors()
4143
assert len(errors) == 1
4244
assert errors[0]["loc"] == ("SECRET_KEY",)
43-
assert "SECRET_KEY must not use default placeholder values" in errors[0]["msg"]
45+
assert "String should match pattern" in errors[0]["msg"]
4446

45-
def test_secret_key_change_me_without_testing(self) -> None:
46-
# CHANGE_ME should fail when not in testing mode
47-
with mock.patch.dict(os.environ, {"SECRET_KEY": "CHANGE_ME_this_is_a_dev_key_min_32_chars_required", "TESTING": "false"}, clear=True):
48-
with pytest.raises(ValidationError) as exc_info:
49-
Settings()
50-
51-
errors = exc_info.value.errors()
52-
assert len(errors) == 1
53-
assert errors[0]["loc"] == ("SECRET_KEY",)
54-
assert "CHANGE_ME detected" in errors[0]["msg"]
55-
56-
def test_secret_key_change_me_with_testing(self) -> None:
57-
# CHANGE_ME should be allowed in testing mode
58-
with mock.patch.dict(os.environ, {"SECRET_KEY": "CHANGE_ME_this_is_a_dev_key_min_32_chars_required", "TESTING": "true"}, clear=True):
59-
settings = Settings()
60-
assert settings.SECRET_KEY == "CHANGE_ME_this_is_a_dev_key_min_32_chars_required"
61-
assert settings.TESTING is True
6247

6348
def test_secret_key_valid(self) -> None:
6449
valid_key = "a" * 32 # 32 character key

0 commit comments

Comments
 (0)