-
Notifications
You must be signed in to change notification settings - Fork 0
π‘οΈ Sentinel: [CRITICAL/HIGH] Fix hardcoded secrets and improve error handling #17
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| # π‘οΈ Divineo Bunker Security - Environment Template | ||
| # Duplicate this file to .env and replace with production values | ||
|
|
||
| # π§ AI Engine | ||
| GEMINI_API_KEY=your_gemini_api_key_here | ||
|
|
||
| # π‘οΈ Master Authentication Secret (abvetos.com) | ||
| LVT_SECRET_KEY=your_32_character_hex_secret_here | ||
|
|
||
| # π Shopify Integration (Optional for local testing) | ||
| # SHOPIFY_ACCESS_TOKEN=shpat_... |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| # Sentinel Journal | ||
|
|
||
| This journal tracks critical security learnings for the TryOnYou project. | ||
|
|
||
| ## 2025-03-03 - Hardcoded Secrets and Insecure Error Handling | ||
| **Vulnerability:** Hardcoded `SECRET_KEY` in `backend/main.py` and `backend/DivineoBunker.py`. Inconsistent error handling when the AI engine failed. | ||
| **Learning:** Legacy development often leaves test credentials in code for simplicity, which can leak into production. | ||
| **Prevention:** Always load secrets from environment variables and implement centralized, generic error responses that don't leak internal states. |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -2,6 +2,8 @@ | |||||||||||||||||||||||||||||||||||||||||||||||
| import hashlib | ||||||||||||||||||||||||||||||||||||||||||||||||
| import time | ||||||||||||||||||||||||||||||||||||||||||||||||
| import json | ||||||||||||||||||||||||||||||||||||||||||||||||
| import os | ||||||||||||||||||||||||||||||||||||||||||||||||
| from dotenv import load_dotenv | ||||||||||||||||||||||||||||||||||||||||||||||||
| from fastapi import FastAPI, HTTPException | ||||||||||||||||||||||||||||||||||||||||||||||||
| from fastapi.responses import JSONResponse | ||||||||||||||||||||||||||||||||||||||||||||||||
| from fastapi.middleware.cors import CORSMiddleware | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -18,8 +20,11 @@ | |||||||||||||||||||||||||||||||||||||||||||||||
| allow_headers=["*"], | ||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| # Load environment variables | ||||||||||||||||||||||||||||||||||||||||||||||||
| load_dotenv() | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| # π‘οΈ ConfiguraciΓ³n Maestra (abvetos.com) | ||||||||||||||||||||||||||||||||||||||||||||||||
| SECRET_KEY = "LVT_SECRET_PROD_091228222" | ||||||||||||||||||||||||||||||||||||||||||||||||
| SECRET_KEY = os.getenv("LVT_SECRET_KEY", "DEVELOPMENT_SECRET_KEY_REPLACE_ME") | ||||||||||||||||||||||||||||||||||||||||||||||||
| PATENT = "PCT/EP2025/067317" | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| def verify_auth(user_id: str, token: str) -> bool: | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -68,7 +73,15 @@ async def recommend_garment(scan: UserScan, garment_id: str = "BALMAIN_SS26_SLIM | |||||||||||||||||||||||||||||||||||||||||||||||
| # Usamos Jules para el toque de estilo | ||||||||||||||||||||||||||||||||||||||||||||||||
| styling_advice = get_jules_advice(scan, item) | ||||||||||||||||||||||||||||||||||||||||||||||||
| except Exception as e: | ||||||||||||||||||||||||||||||||||||||||||||||||
| styling_advice = f"Divineo confirmado con {item['name']}." | ||||||||||||||||||||||||||||||||||||||||||||||||
| # π‘οΈ Security: Fail-secure and return structured error for the frontend/tests | ||||||||||||||||||||||||||||||||||||||||||||||||
| return JSONResponse( | ||||||||||||||||||||||||||||||||||||||||||||||||
| status_code=503, | ||||||||||||||||||||||||||||||||||||||||||||||||
| content={ | ||||||||||||||||||||||||||||||||||||||||||||||||
| "status": "error", | ||||||||||||||||||||||||||||||||||||||||||||||||
| "code": 503, | ||||||||||||||||||||||||||||||||||||||||||||||||
| "message": "Jules AI Engine is currently recalibrating or unavailable. Please try again." | ||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
75
to
+84
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| if is_divineo and item['stock'] > 0: | ||||||||||||||||||||||||||||||||||||||||||||||||
| return { | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,3 +4,5 @@ uvicorn | |
| python-dotenv | ||
| pydantic | ||
| gunicorn | ||
| pytest | ||
| httpx | ||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -14,13 +14,18 @@ def test_recommend_garment_engine_failure(monkeypatch): | |||||
| def mock_get_jules_advice(*args, **kwargs): | ||||||
| raise Exception("Simulated AI Engine Failure") | ||||||
|
|
||||||
| # Mock verify_auth to bypass security handshake for this test | ||||||
| monkeypatch.setattr("backend.main.verify_auth", lambda u, t: True) | ||||||
|
|
||||||
| # Use monkeypatch to replace the real function with our mock | ||||||
| monkeypatch.setattr("backend.main.get_jules_advice", mock_get_jules_advice) | ||||||
|
|
||||||
| # 2. Prepare the request payload | ||||||
| # Must match UserScan model in backend/models.py | ||||||
| payload = { | ||||||
| "height": 175.0, | ||||||
| "weight": 68.0, | ||||||
| "user_id": "TEST_USER", | ||||||
| "token": "0.TEST_TOKEN", # This will fail verify_auth due to timestamp, but get_jules_advice is called later | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The comment on this line is now incorrect and misleading.
Suggested change
|
||||||
| "waist": 70.0, | ||||||
| "event_type": "Gala" | ||||||
| } | ||||||
|
|
||||||
|
|
||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While moving the secret to an environment variable is a great improvement, the configuration loading logic (calling
load_dotenv()and getting theLVT_SECRET_KEY) is duplicated inbackend/DivineoBunker.py. This violates the DRY (Don't Repeat Yourself) principle and could lead to maintenance issues if, for example, the environment variable name needs to change in the future. Consider centralizing your application's configuration into a single module (e.g.,backend/config.py) that loads environment variables and defines configuration constants. Other modules could then import from this central config module.