Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions services/flask-backend/app/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ def create_app(config_class: type | None = None) -> Quart:

Returns:
Configured Quart application instance

Raises:
ValueError: If production config validation fails (missing or invalid secrets)
"""
app = Quart(__name__)

Expand All @@ -46,6 +49,10 @@ def create_app(config_class: type | None = None) -> Quart:
config_class = get_config()
app.config.from_object(config_class)

# Validate configuration (production only)
if hasattr(config_class, "validate"):
config_class.validate()

# Setup logging
_setup_logging(app)

Expand Down
6 changes: 6 additions & 0 deletions services/flask-backend/app/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ class ProductionConfig(Config):
# Strict security in production
SECURITY_PASSWORD_SALT = os.getenv("SECURITY_PASSWORD_SALT") # Required
SECRET_KEY = os.getenv("SECRET_KEY") # Required
JWT_SECRET_KEY = os.getenv("JWT_SECRET_KEY") # Required — must not fall back to dev default

@classmethod
def validate(cls) -> None:
Comment on lines +180 to 183

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: The hardcoded dev default string in validation is brittle and may drift from the actual dev default.

This check couples production validation to the hardcoded string "dev-secret-key-change-in-production", which can drift if the dev default changes elsewhere. Prefer referencing a single canonical dev/default value (e.g., Config.DEFAULT_JWT_SECRET_KEY or DevelopmentConfig.JWT_SECRET_KEY) rather than inlining the literal here.

Suggested implementation:

        if (
            not cls.JWT_SECRET_KEY
            or cls.JWT_SECRET_KEY == DevelopmentConfig.JWT_SECRET_KEY
        ):

If DevelopmentConfig.JWT_SECRET_KEY is not yet defined or the development default is stored elsewhere, you should:

  1. Define the canonical dev default in one place (e.g., DevelopmentConfig.JWT_SECRET_KEY = "dev-secret-key-change-in-production" or Config.DEFAULT_JWT_SECRET_KEY = "dev-secret-key-change-in-production").
  2. Update this production validation and any other dev default usages to reference that single canonical location.

Expand All @@ -188,6 +189,11 @@ def validate(cls) -> None:
raise ValueError("SECRET_KEY must be set in production")
if not cls.SECURITY_PASSWORD_SALT or "change" in cls.SECURITY_PASSWORD_SALT:
raise ValueError("SECURITY_PASSWORD_SALT must be set in production")
if (
not cls.JWT_SECRET_KEY
or cls.JWT_SECRET_KEY == "dev-secret-key-change-in-production"
):
raise ValueError("JWT_SECRET_KEY must be set in production")


class TestingConfig(Config):
Expand Down