# feeltic.com — CSP y cabeceras de seguridad (servidor20)

# feeltic.com — Content-Security-Policy y cabeceras de seguridad

**Servidor:** servidor20.xerintel.com
**Cuenta cPanel:** jcamarke
**Stack:** Laravel 10 + PHP 8.2 + MySQL + Apache (mod_headers)
**Dominio:** feeltic.com

---

## Fichero de configuración

```
/etc/apache2/conf.d/userdata/ssl/2_4/jcamarke/feeltic.com/security-headers.conf
```

**Requiere root** para editar. Tras cualquier cambio:

```bash
/scripts/rebuildhttpdconf && /scripts/restartsrv_httpd
```

**Backup actual:** `security-headers.conf.bak.20260319`

---

## Cabeceras activas

| Cabecera | Valor |
|----------|-------|
| Strict-Transport-Security | max-age=31536000; includeSubDomains |
| X-Frame-Options | SAMEORIGIN |
| X-Content-Type-Options | nosniff |
| Referrer-Policy | strict-origin-when-cross-origin |
| Permissions-Policy | camera=(), microphone=(), geolocation=(self), payment=(self) |
| Content-Security-Policy | Ver detalle abajo |

---

## Content-Security-Policy — Detalle por directiva

### default-src

`self`

### script-src

| Dominio | Servicio |
|---------|----------|
| `self` | Scripts propios |
| `unsafe-inline` `unsafe-eval` | Requerido por GTM, reCAPTCHA, Stripe |
| `www.google.com` `www.gstatic.com` | reCAPTCHA |
| `www.googletagmanager.com` | Google Tag Manager |
| `ajax.googleapis.com` | Google APIs |
| `js.stripe.com` `connect-js.stripe.com` `checkout.stripe.com` | Stripe |
| `pay.google.com` | Google Pay |
| `cdnjs.cloudflare.com` `code.jquery.com` `cdn.jsdelivr.net` | CDNs |
| `d3e54v103j8qbb.cloudfront.net` | Webflow assets |
| `static.zdassets.com` | Zendesk widget |

### style-src

| Dominio | Servicio |
|---------|----------|
| `self` `unsafe-inline` | Estilos propios + inline |
| `fonts.googleapis.com` | Google Fonts |
| `cdnjs.cloudflare.com` `cdn.jsdelivr.net` `stackpath.bootstrapcdn.com` | CDNs |
| `ajax.googleapis.com` | Google APIs |

### font-src

| Dominio | Servicio |
|---------|----------|
| `self` `data:` | Fuentes propias + data URIs (ttf inline) |
| `fonts.gstatic.com` `fonts.googleapis.com` | Google Fonts |
| `cdnjs.cloudflare.com` | CDN (Font Awesome, etc.) |

### img-src

| Dominio | Servicio |
|---------|----------|
| `self` `data:` `blob:` | Imágenes propias, data URIs, blobs |
| `feeltic.com` `*.feeltic.com` | **Dominio propio** (storage/avatars) |
| `*.stripe.com` | Stripe |
| `maps.google.com` `maps.googleapis.com` | Google Maps |
| `lh3.googleusercontent.com` | Avatares Google |
| `platform-lookaside.fbsbx.com` `graph.facebook.com` | Facebook |

### connect-src

| Dominio | Servicio |
|---------|----------|
| `self` | API propia |
| `js.stripe.com` `checkout.stripe.com` | Stripe |
| `api-m.sandbox.paypal.com` `api-m.paypal.com` | PayPal |
| `panel.sendcloud.sc` `servicepoints.sendcloud.sc` | SendCloud |
| `apis-sandbox.fedex.com` `apis.fedex.com` | FedEx |
| `maps.googleapis.com` `translation.googleapis.com` | Google Maps/Translate |
| `www.google.com` `www.googletagmanager.com` | Google/GTM |
| `ekr.zdassets.com` `static.zdassets.com` | Zendesk (assets) |
| `*.zendesk.com` | **Zendesk (eventos/config)** |
| `*.google-analytics.com` `region1.google-analytics.com` | **Google Analytics 4** |

### frame-src

| Dominio | Servicio |
|---------|----------|
| `self` | Frames propios |
| `www.google.com` `www.googletagmanager.com` | reCAPTCHA/GTM |
| `maps.google.com` | Google Maps embed |
| `www.youtube.com` | YouTube embed |
| `js.stripe.com` `hooks.stripe.com` | Stripe |
| `pay.google.com` | Google Pay |

### Otras directivas

| Directiva | Valor |
|-----------|-------|
| form-action | `self` |
| object-src | `none` |
| base-uri | `self` |
| frame-ancestors | `self` |

---

## Historial de cambios

### 2026-03-19 — Corrección CSP (reclamación cliente)

**Problema:** La CSP implementada el 2026-03-10 bloqueaba recursos legítimos en `/cart/show`:

- Zendesk frontend events (`feeltic.zendesk.com/frontendevents/`) — faltaba `*.zendesk.com` en connect-src
- Google Analytics 4 collect (`region1.google-analytics.com/g/collect`) — faltaba en connect-src
- Fuentes inline data URI (`data:application/x-font-ttf`) — faltaba `data:` en font-src
- Avatares propios (`feeltic.com/storage/users/avatar/`) — faltaba dominio propio en img-src

**Solución:**

- `connect-src`: añadido `*.zendesk.com`, `*.google-analytics.com`, `region1.google-analytics.com`
- `font-src`: añadido `data:`
- `img-src`: añadido `feeltic.com`, `*.feeltic.com`

**Backup:** `security-headers.conf.bak.20260319`

### 2026-03-10 — Implementación inicial

CSP implementada como parte de hardening post-auditoría de seguridad externa. Ver informes:

- `2026-03-10-feeltic-informe-acciones-cliente.md`
- `2026-03-10-feeltic-informe-interno-xerintel.md`

---

## Nota sobre unsafe-inline

La CSP incluye `unsafe-inline` para scripts y estilos. Necesario porque Google Tag Manager, reCAPTCHA y Stripe inyectan scripts inline. Eliminar requiere migrar a sistema de nonces criptográficos en todas las vistas Laravel — mejora planificable a medio plazo, no urgente.

---

## Procedimiento para futuras reclamaciones CSP

Cuando el cliente reporte errores de consola tipo `Content-Security-Policy blocked`:

1. Identificar la directiva afectada (el error dice cuál: `connect-src`, `img-src`, etc.)
2. Identificar el dominio bloqueado (el error incluye la URL completa)
3. **Verificar que el dominio es legítimo** (servicio conocido del cliente, no malware/tracking no autorizado)
4. Editar `security-headers.conf` añadiendo el dominio a la directiva correspondiente
5. `rebuildhttpdconf && restartsrv_httpd`
6. Verificar: `curl -sI https://www.feeltic.com | grep content-security-policy`
7. Actualizar esta página de wiki con el cambio