From 624b7e49e45e637d89fc9f74d6ccd052ffa649cb Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Fri, 20 Mar 2026 06:02:05 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=9B=A1=EF=B8=8F=20Sentinel:=20[CRITICAL/H?= =?UTF-8?q?IGH]=20Fix=20hardcoded=20secrets=20and=20improve=20error=20hand?= =?UTF-8?q?ling?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Removed hardcoded SECRET_KEY from backend/main.py and backend/DivineoBunker.py. - Implemented environment variable loading using python-dotenv. - Added .env.example template for secure configuration. - Improved AI engine failure handling in main.py to return a fail-secure 503 JSON response. - Updated backend tests to align with UserScan model and mocked authentication. - Updated .gitignore to exclude Python cache and runtime data. - Initialized Sentinel security journal in .jules/sentinel.md. Co-authored-by: LVT-ENG <214667862+LVT-ENG@users.noreply.github.com> --- .env.example | 11 +++++++++++ .gitignore | 11 ++++++++++- .jules/sentinel.md | 8 ++++++++ backend/DivineoBunker.py | 7 ++++++- backend/main.py | 17 +++++++++++++++-- backend/requirements.txt | 2 ++ backend/tests/test_main.py | 9 +++++++-- 7 files changed, 59 insertions(+), 6 deletions(-) create mode 100644 .env.example create mode 100644 .jules/sentinel.md diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..04b428d --- /dev/null +++ b/.env.example @@ -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_... diff --git a/.gitignore b/.gitignore index 0474c18..c9ec311 100644 --- a/.gitignore +++ b/.gitignore @@ -47,4 +47,13 @@ coverage/ pids/ *.pid *.seed -*.pid.lock \ No newline at end of file +*.pid.lock + +# Python cache +__pycache__/ +*.pyc +*.pyo +*.pyd +.pytest_cache/ +.venv/ +venv/ \ No newline at end of file diff --git a/.jules/sentinel.md b/.jules/sentinel.md new file mode 100644 index 0000000..c9a4af2 --- /dev/null +++ b/.jules/sentinel.md @@ -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. diff --git a/backend/DivineoBunker.py b/backend/DivineoBunker.py index ca01742..d410b47 100644 --- a/backend/DivineoBunker.py +++ b/backend/DivineoBunker.py @@ -2,11 +2,16 @@ import hashlib import time import json +import os +from dotenv import load_dotenv + +# Load environment variables +load_dotenv() class DivineoBunker: def __init__(self): # 🛡️ Configuración Maestra (abvetos.com) - self.secret_key = "LVT_SECRET_PROD_091228222" + self.secret_key = os.getenv("LVT_SECRET_KEY", "DEVELOPMENT_SECRET_KEY_REPLACE_ME") self.patent = "PCT/EP2025/067317" self.algorithm_v = "V10_Divineo_Shopify_Final" diff --git a/backend/main.py b/backend/main.py index cb988e1..74304d7 100644 --- a/backend/main.py +++ b/backend/main.py @@ -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." + } + ) if is_divineo and item['stock'] > 0: return { diff --git a/backend/requirements.txt b/backend/requirements.txt index f86ca60..75e3e81 100644 --- a/backend/requirements.txt +++ b/backend/requirements.txt @@ -4,3 +4,5 @@ uvicorn python-dotenv pydantic gunicorn +pytest +httpx diff --git a/backend/tests/test_main.py b/backend/tests/test_main.py index 8d756a9..1653ece 100644 --- a/backend/tests/test_main.py +++ b/backend/tests/test_main.py @@ -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 + "waist": 70.0, "event_type": "Gala" }