🛡

Security Scan Report — NutriSync Platform

PR #482  feat: módulo de recetas con IA Escaneado: 2026-06-14 Rama: feature/ai-recipes Generado por: CULTIVA IA Skill / parseo-sarif
Semgrep 1.68.0 CodeQL 2.16.5 SARIF 2.1.0

Resumen Ejecutivo

21
Total hallazgos
en 21 resultados brutos
21
Únicos (dedup)
0 duplicado(s) eliminado(s)
7
CRÍTICOS
requieren acción inmediata
9
AVISOS
revisar en este sprint
5
NOTAS
deuda técnica menor
Semgrep
CRÍTICO4
AVISO5
NOTA3
CodeQL
CRÍTICO3
AVISO4
NOTA2
Archivos afectados
auth.test.ts
RecipeCard.tsx
auth-tokens.ts
stripe.ts
supabase-helpers.ts
callback.tsx
search.tsx
fileManager.ts

Hallazgos Críticos — Acción Inmediata

⚠  Se detectaron 7 vulnerabilidades de nivel ERROR. Este PR no debe mergearse hasta resolver al menos los hallazgos de inyección de credenciales y JWT.

Semgrep sql-injection src/api/recipes/queries.py L47
SQL query built with string concatenation from user-controlled input `recipe_name`. Use parameterized queries instead.
Semgrep fastapi-jwt-none-algorithm src/auth/jwt_utils.py L23
JWT decoder accepts 'none' algorithm. An attacker can forge tokens without a secret key. Set algorithms=['HS256'] explicitly.
Semgrep hardcoded-password src/core/config.py L12
Hard-coded database password found: `DB_PASS = 'nutrisync2024!'`. Move to environment variable.
Semgrep detected-aws-access-key tests/fixtures/aws_mock.py L8
AWS access key `AKIA...` hardcoded in test fixture. Revoke immediately and use IAM roles or secrets manager.
CodeQL js/xss frontend/src/components/RecipeCard.tsx L67
Cross-site scripting: user-supplied `recipeName` flows from HTTP request into `innerHTML` in RecipeCard component without sanitization.
CodeQL js/path-injection frontend/src/utils/fileManager.ts L43
Path traversal: `fileName` parameter from user upload request used directly in `fs.readFile()` without normalization or allowlist check.
CodeQL js/hardcoded-credentials frontend/src/lib/stripe.ts L5
Hard-coded API key `sk_live_...` found in Stripe integration helper. Move to environment variable STRIPE_SECRET_KEY.

Todos los Hallazgos (21 únicos)

# Severidad Herramienta Regla Descripción Archivo / Línea
1 CRÍTICO Semgrep Sql Injection SQL query built with string concatenation from user-controlled input `recipe_name`. Use parameterized queries instead. recipes/queries.py
L47
2 CRÍTICO Semgrep Fastapi Jwt None Algorithm JWT decoder accepts 'none' algorithm. An attacker can forge tokens without a secret key. Set algorithms=['HS256'] explicitly. auth/jwt_utils.py
L23
3 CRÍTICO Semgrep Hardcoded Password Hard-coded database password found: `DB_PASS = 'nutrisync2024!'`. Move to environment variable. core/config.py
L12
4 CRÍTICO Semgrep Detected Aws Access Key AWS access key `AKIA...` hardcoded in test fixture. Revoke immediately and use IAM roles or secrets manager. fixtures/aws_mock.py
L8
5 CRÍTICO CodeQL Js/Xss Cross-site scripting: user-supplied `recipeName` flows from HTTP request into `innerHTML` in RecipeCard component without sanitization. components/RecipeCard.tsx
L67
6 CRÍTICO CodeQL Js/Path Injection Path traversal: `fileName` parameter from user upload request used directly in `fs.readFile()` without normalization or allowlist check. utils/fileManager.ts
L43
7 CRÍTICO CodeQL Js/Hardcoded Credentials Hard-coded API key `sk_live_...` found in Stripe integration helper. Move to environment variable STRIPE_SECRET_KEY. lib/stripe.ts
L5
8 AVISO Semgrep Direct Response Write User-supplied `ingredient_name` written directly to HTML response without escaping. ingredients/views.py
L89
9 AVISO Semgrep No Auth Over Http Credentials passed in Authorization header over plain HTTP to external nutrition API. integrations/fatsecret_client.py
L34
10 AVISO Semgrep Insecure Hash Algorithm Md5 MD5 used to hash user profile images cache key. Use SHA-256 for hash integrity. utils/cache.py
L61
11 AVISO Semgrep Dangerous Subprocess Use subprocess called with shell=True and partial user input in PDF export command. reports/pdf_exporter.py
L112
12 AVISO Semgrep Disabled Cert Validation SSL certificate verification disabled (`verify=False`) in webhook delivery client. webhooks/dispatcher.py
L78
13 AVISO CodeQL Js/Sql Injection Potential SQL injection in Supabase raw query: `patientId` string interpolated into query template. lib/supabase-helpers.ts
L88
14 AVISO CodeQL Js/Prototype Pollution Prototype pollution via `Object.assign({}, req.query)` in settings merge utility. utils/settingsMerge.ts
L22
15 AVISO CodeQL Js/Open Redirect Open redirect: `returnUrl` from query string passed directly to `router.push()` without domain validation. auth/callback.tsx
L31
16 AVISO CodeQL Js/Xss Reflected XSS risk: `searchTerm` reflected into page title tag via `document.title` without encoding. pages/search.tsx
L54
17 NOTA Semgrep None Return In Function Function `get_patient_plan` may return None if plan not found; callers don't check. patients/service.py
L203
18 NOTA Semgrep None Return In Function Function `resolve_dietitian` may return None; callers should handle explicitly. dietitians/resolver.py
L56
19 NOTA Semgrep Hardcoded Password Static test password 'testpass123' in unit test. Consider using test fixtures. unit/test_auth.py
L17
20 NOTA CodeQL Js/Insufficient Password Hash SHA-1 used for password reset token generation. Use crypto.randomBytes(32) instead. lib/auth-tokens.ts
L18
21 NOTA CodeQL Js/Hardcoded Credentials Test fixture contains hardcoded JWT secret 'test-secret-jwt'. Acceptable in tests but ensure this never reaches production config. __tests__/auth.test.ts
L9

Plan de Remediación Sugerido

🚨 Sprint actual (bloquean release)
  • Revocar AWS key expuesta en tests/fixtures/aws_mock.py
  • Mover Stripe API key a variable de entorno STRIPE_SECRET_KEY
  • Corregir JWT none-algorithm en src/auth/jwt_utils.py
  • Usar queries parametrizadas en src/api/recipes/queries.py
  • Sanitizar recipeName antes de innerHTML en RecipeCard
⚠ Próximo sprint
  • Validar returnUrl contra allowlist de dominios propios
  • Reemplazar subprocess shell=True por lista de argumentos
  • Activar verificación TLS en cliente de webhooks
  • Mitigar prototype pollution en settingsMerge
  • Forzar HTTPS en cliente FatSecret
📄 Backlog / deuda técnica
  • Sustituir MD5 por SHA-256 en cache de imágenes
  • Usar crypto.randomBytes(32) en reset tokens
  • Añadir comprobaciones de None en get_patient_plan y resolve_dietitian
  • Añadir path traversal check en fileManager
Generado automáticamente · CULTIVA IA — Skill parseo-sarif · 2026-06-14