committed by
GitHub
2 changed files with 30 additions and 20 deletions
@ -1,44 +1,52 @@ |
|||||
import pytest |
|
||||
import sys |
|
||||
import os |
import os |
||||
|
import sys |
||||
from importlib import util |
from importlib import util |
||||
|
|
||||
|
import pytest |
||||
|
|
||||
# Add the project root to sys.path to import the tutorial module |
# Add the project root to sys.path to import the tutorial module |
||||
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '../../..'))) |
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "../../.."))) |
||||
|
|
||||
# Import the actual production module |
# Import the actual production module |
||||
spec = util.spec_from_file_location( |
spec = util.spec_from_file_location( |
||||
"tutorial004_an_py310", |
"tutorial004_an_py310", "docs_src/security/tutorial004_an_py310.py" |
||||
"docs_src/security/tutorial004_an_py310.py" |
|
||||
) |
) |
||||
tutorial = util.module_from_spec(spec) |
tutorial = util.module_from_spec(spec) |
||||
spec.loader.exec_module(tutorial) |
spec.loader.exec_module(tutorial) |
||||
|
|
||||
|
|
||||
@pytest.mark.parametrize("secret_key", [ |
@pytest.mark.parametrize( |
||||
# Exact exploit case: hardcoded secret from the tutorial |
"secret_key", |
||||
"09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7", |
[ |
||||
# Boundary case: empty secret (should not be allowed) |
# Exact exploit case: hardcoded secret from the tutorial |
||||
"", |
"09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7", |
||||
# Valid input: a different secret (should be accepted but not match hardcoded) |
# Boundary case: empty secret (should not be allowed) |
||||
"a1b2c3d4e5f67890abcdef1234567890fedcba0987654321abcdef0123456789", |
"", |
||||
]) |
# Valid input: a different secret (should be accepted but not match hardcoded) |
||||
|
"a1b2c3d4e5f67890abcdef1234567890fedcba0987654321abcdef0123456789", |
||||
|
], |
||||
|
) |
||||
def test_secret_key_not_hardcoded_in_production(secret_key): |
def test_secret_key_not_hardcoded_in_production(secret_key): |
||||
"""Invariant: Production secret keys must not match the tutorial's hardcoded example.""" |
"""Invariant: Production secret keys must not match the tutorial's hardcoded example.""" |
||||
# Access the module's SECRET_KEY constant |
# Access the module's SECRET_KEY constant |
||||
module_secret = tutorial.SECRET_KEY |
module_secret = tutorial.SECRET_KEY |
||||
|
|
||||
# The security property: the actual secret must NOT be the tutorial's hardcoded value |
# The security property: the actual secret must NOT be the tutorial's hardcoded value |
||||
# This ensures the example isn't accidentally used in production |
# This ensures the example isn't accidentally used in production |
||||
assert module_secret != "09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7", \ |
assert ( |
||||
|
module_secret |
||||
|
!= "09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7" |
||||
|
), ( |
||||
"SECRET_KEY matches the tutorial's hardcoded example - this is unsafe for production!" |
"SECRET_KEY matches the tutorial's hardcoded example - this is unsafe for production!" |
||||
|
) |
||||
|
|
||||
# Additional invariant: secret must be non-empty and sufficiently long for HS256 |
# Additional invariant: secret must be non-empty and sufficiently long for HS256 |
||||
assert len(module_secret) >= 32, \ |
assert len(module_secret) >= 32, ( |
||||
"SECRET_KEY is too short for secure HS256 usage (minimum 32 hex chars)" |
"SECRET_KEY is too short for secure HS256 usage (minimum 32 hex chars)" |
||||
|
) |
||||
|
|
||||
# Verify the secret is a valid hex string (optional but good practice) |
# Verify the secret is a valid hex string (optional but good practice) |
||||
try: |
try: |
||||
int(module_secret, 16) |
int(module_secret, 16) |
||||
except ValueError: |
except ValueError: |
||||
pytest.fail("SECRET_KEY is not a valid hexadecimal string") |
pytest.fail("SECRET_KEY is not a valid hexadecimal string") |
||||
|
|||||
Loading…
Reference in new issue