fix tests

This commit is contained in:
seniorswe
2026-01-25 00:28:27 -05:00
parent 54541f916c
commit 55698584b8
2 changed files with 48 additions and 3 deletions
+34 -1
View File
@@ -200,6 +200,13 @@ def archive_existing_proto(proto_path: Path, api_name: str, api_version: str):
# Re-sanitize inputs to be paranoid
safe_name = sanitize_filename(api_name)
safe_ver = sanitize_filename(api_version)
# Ensure the source path matches the exact expected sanitized filename under proto/
expected_src = (PROJECT_ROOT / 'proto' / f"{safe_name}_{safe_ver}.proto").resolve()
if expected_src != proto_path:
logger.warning(
f"Archive source path mismatch: expected {expected_src}, got {proto_path}; skipping archive"
)
return
filename = f"{safe_name}_{safe_ver}_{timestamp}.proto"
dest = (archive_dir / filename).resolve() # codeql[py/uncontrolled-data-in-path-expression]: Destination path built from sanitized components and constrained to archive_dir via validate_path
@@ -312,9 +319,35 @@ async def upload_proto_file(
if not validate_path(PROJECT_ROOT, proto_path):
raise ValueError('Invalid proto path detected')
# Archive existing before overwrite
# Archive existing before overwrite (with strict filename equality guard)
archive_existing_proto(proto_path, api_name, api_version)
# Write only if the computed path matches the sanitized expectation
try:
expected_src = (
PROJECT_ROOT / 'proto' / f"{sanitize_filename(api_name)}_{sanitize_filename(api_version)}.proto"
).resolve()
except Exception:
return process_response(
ResponseModel(
status_code=400,
response_headers={Headers.REQUEST_ID: request_id},
error_code=ErrorCodes.PATH_VALIDATION,
error_message='Failed to compute expected proto path',
).dict(),
'rest',
)
if expected_src != proto_path:
return process_response(
ResponseModel(
status_code=400,
response_headers={Headers.REQUEST_ID: request_id},
error_code=ErrorCodes.PATH_VALIDATION,
error_message='Computed proto path mismatch after sanitization',
).dict(),
'rest',
)
proto_path.write_text(proto_content)
try:
# Ensure grpc_tools is available before attempting compilation
+14 -2
View File
@@ -21,6 +21,7 @@ from xml.etree import ElementTree as ET
import defusedxml.ElementTree as SafeET
import httpx
import os
logger = logging.getLogger('doorman.gateway')
@@ -278,10 +279,21 @@ def create_ws_security_header(
nonce_value = secrets.token_bytes(16)
nonce_b64 = __import__('base64').b64encode(nonce_value).decode('ascii')
if password and password_type in ('PasswordDigest', 'PasswordDigestSHA256'):
# Gate legacy SHA-1 UsernameToken digests behind an env flag for security hardening.
# Default behavior prefers SHA-256 unless explicitly allowed to use SHA-1.
allow_sha1 = os.getenv('DOORMAN_ALLOW_WSSE_SHA1', '').lower() in ('1', 'true', 'yes', 'on')
effective_type = password_type
if password_type == 'PasswordDigest' and not allow_sha1:
try:
logger.warning('WS-Security PasswordDigest (SHA-1) disabled by default; using SHA-256. Set DOORMAN_ALLOW_WSSE_SHA1=true to enable SHA-1 for interop.')
except Exception:
pass
effective_type = 'PasswordDigestSHA256'
if password and effective_type in ('PasswordDigest', 'PasswordDigestSHA256'):
# Digest = Base64(HASH(Nonce + Created + Password))
digest_input = nonce_value + created.encode('utf-8') + password.encode('utf-8')
if password_type == 'PasswordDigestSHA256':
if effective_type == 'PasswordDigestSHA256':
# WS-Security 1.1 requires SHA-256 for PasswordDigestSHA256.
# This is a network digest, NOT used for local password storage.
digest_bytes = hashlib.sha256(digest_input).digest() # codeql[py/weak-cryptographic-algorithm]: WS-Security UsernameToken digest (transport-level), not password storage