Portada de Cómo proteger tu app con Claude: guía práctica de RLS, CORS y Security Headers

Cómo proteger tu app con Claude: guía práctica de RLS, CORS y Security Headers

Por carlos-anegon · Inteligencia Artificial · Apr 19, 2026
36

Aprende a blindar tu aplicación web con Row-Level Security, CORS y Security Headers. Una guía clara, evergreen y orientada a developers que quieren usar Claude sin dejar agujeros de seguridad.

Cómo proteger tu app con Claude: guía práctica de RLS, CORS y Security Headers

Descripción: Aprende a blindar tu aplicación web con Row-Level Security, CORS y Security Headers. Una guía clara, evergreen y orientada a developers que quieren usar Claude sin dejar agujeros de seguridad.

Programar con Claude es una ventaja enorme. Te ayuda a avanzar más rápido, a estructurar mejor el código y a resolver en minutos tareas que antes te consumían horas o días.

Pero esa velocidad tiene una cara menos cómoda: también puedes construir una app aparentemente sólida antes de haber protegido lo importante.

Y ahí empiezan muchos problemas reales.

Una aplicación puede verse bien, funcionar rápido y tener usuarios activos. Pero si cualquier persona puede ver datos que no le pertenecen, si tu API acepta peticiones desde orígenes demasiado amplios o si el navegador puede ejecutar recursos que nunca debió aceptar, no tienes una base segura. Tienes una aplicación vulnerable con buena apariencia.

Si hoy tuvieras que revisar solo tres cosas para subir varios niveles la seguridad de tu proyecto, deberían ser estas:

  • Row-Level Security (RLS)
  • CORS
  • Security Headers

No son conceptos nuevos. No son una moda. No dependen del framework que uses. Precisamente por eso siguen siendo tan importantes: porque resuelven problemas estructurales que siguen apareciendo una y otra vez en productos reales.

Esta guía está pensada para que entiendas lo necesario, sepas qué pedirle a Claude y evites errores que mucha gente sigue cometiendo incluso en proyectos serios.

Por qué tantas apps salen a producción con fallos evitables

La mayoría de las aplicaciones no nacen inseguras porque sus developers sean descuidados. Nacen inseguras porque casi siempre hay otra prioridad por delante.

Primero se monta el login. Luego el dashboard. Luego el CRUD. Luego los pagos. Luego el contenido. Luego el SEO. Luego la parte visual. Y la seguridad termina convertida en una tarea para "cuando haya tiempo".

El problema es que ese momento casi nunca llega antes del lanzamiento.

Entonces aparecen patrones muy repetidos:

  • tablas que exponen más datos de los que deberían
  • APIs configuradas con CORS demasiado permisivo
  • headers de seguridad inexistentes o incompletos
  • código generado por IA que funciona, pero que deja demasiado abierta la puerta

Y casi nunca hace falta un ataque sofisticado para aprovecharlo. A veces basta con cambiar un identificador, reproducir una request desde otro origen o incrustar una página donde no debe.

Las tres capas de seguridad que más retorno te dan

Cuando se habla de seguridad web, mucha gente piensa solo en autenticación: contraseñas, sesiones, JWT, OAuth. Todo eso importa, pero no basta.

Una aplicación moderna necesita al menos tres capas bien resueltas:

CapaQué protegeRiesgo principal que reduceRLSLos datos en base de datosAcceso indebido a filas ajenasCORSLa comunicación navegador → APIOrígenes no autorizadosSecurity HeadersLa interpretación del navegadorXSS, clickjacking, carga insegura de recursos

Dicho de forma simple:

  • RLS protege lo que guardas
  • CORS protege quién puede llamar
  • Headers protege cómo se ejecuta y se muestra

1. Row-Level Security (RLS): la capa que protege tus datos de verdad

Qué es RLS

Row-Level Security es una funcionalidad de PostgreSQL que permite definir reglas de acceso por fila.

Eso significa que la propia base de datos decide qué registros puede ver, crear, modificar o borrar cada usuario.

No depende del frontend. No depende solo del backend. No depende de que nadie se equivoque filtrando.

Depende de reglas internas en la base de datos.

Una analogía fácil

Imagina un trastero enorme con cientos de taquillas. Sin RLS, la puerta está abierta y confías en que cada persona solo revise la suya. Con RLS, cada usuario entra y solo puede ver la taquilla que le pertenece. El resto ni siquiera existe para él.

Eso es lo importante: no solo restringe acciones. También restringe visibilidad.

Qué pasa si no usas RLS

Sin RLS, una app puede filtrar datos privados por errores tan comunes como estos:

  • una query demasiado amplia
  • un filtro mal construido
  • un parámetro manipulable
  • una validación ausente en una ruta
  • una IA que genera lógica funcional pero no defensiva

Eso puede exponer:

  • correos de otros usuarios
  • borradores privados
  • perfiles no públicos
  • pedidos ajenos
  • mensajes o contenido interno
  • registros sensibles ligados a otro user_id

En proyectos con Supabase y PostgreSQL, este es uno de los fallos más habituales porque mucha gente cree que con filtrar en el backend ya basta.

No basta.

Por qué RLS cambia el nivel de seguridad

RLS mueve la seguridad al lugar correcto: la base de datos.

Eso es importante porque el código cambia constantemente. Se refactoriza, crece, se divide entre varios servicios o lo genera una IA. Las reglas de base de datos, en cambio, se mantienen como una capa mucho más estable.

Si una ruta falla o una query queda mal escrita, RLS todavía puede impedir que un usuario lea o modifique lo que no le pertenece.

Esa es la diferencia entre una app que espera que nadie cometa errores y una app que asume que tarde o temprano alguien sí los cometerá.

Prompt para configurar RLS con Claude

Estoy usando Supabase con PostgreSQL. Tengo las siguientes tablas en mi base de datos:

  • users (id, email, name)
  • posts (id, user_id, title, content, created_at)
  • comments (id, post_id, user_id, content)

Necesito que configures Row-Level Security (RLS) para que:

  1. Cada usuario solo pueda VER sus propios posts
  2. Cada usuario solo pueda CREAR posts con su propio user_id
  3. Cada usuario solo pueda EDITAR sus propios posts
  4. Cada usuario solo pueda BORRAR sus propios posts
  5. Los comentarios se puedan ver todos, pero solo editar y borrar los propios

Por favor:

  • Activa RLS en TODAS las tablas con ALTER TABLE ... ENABLE ROW LEVEL SECURITY
  • Crea políticas separadas para SELECT, INSERT, UPDATE y DELETE
  • No uses FOR ALL
  • Usa auth.uid() para referenciar al usuario autenticado
  • Nunca uses user_metadata en las políticas
  • Agrega índices en las columnas user_id para rendimiento
  • Dame el SQL completo listo para copiar en el SQL Editor de Supabase
  • Muéstrame cómo probar las políticas desde el SDK de JavaScript de Supabase

Cómo comprobar que RLS funciona de verdad

La prueba correcta no es mirar el SQL y pensar que "parece bien". La prueba correcta es intentar romperlo.

Haz esto:

  1. Crea dos usuarios de prueba.
  2. Inicia sesión como el usuario A.
  3. Genera contenido.
  4. Inicia sesión como el usuario B.
  5. Comprueba que no puede ver, editar ni borrar nada del usuario A.
  6. Prueba también inserciones con identificadores que no le correspondan.

Si el usuario B puede tocar algo del usuario A, las políticas están mal o incompletas.

Error típico al pedir esto a una IA

El error no suele ser Claude. El error suele ser el prompt.

Si le pides "ponme RLS", te devolverá algo. Pero no necesariamente algo fino.

Para obtener un resultado serio, hay que dejar claro:

  • qué tablas quieres proteger
  • qué acciones debe permitir cada política
  • qué acciones debe bloquear
  • qué referencia de usuario es fiable
  • qué atajos no quieres que use

Con seguridad, la diferencia entre "funciona" y "está bien hecho" suele estar en ese nivel de precisión.

2. CORS: la puerta de tu API no debería estar abierta al primero que pase

Qué es CORS

CORS significa Cross-Origin Resource Sharing.

En la práctica, es el mecanismo que controla qué páginas web pueden hacer peticiones a tu API desde el navegador.

Si tu frontend vive en un dominio y tu backend en otro, el navegador necesita saber si esa comunicación está permitida.

Una analogía simple

Imagina la recepción de un edificio.

No basta con que alguien diga "vengo de parte del equipo". La recepción tiene una lista. Si el nombre o la empresa no están autorizados, no entra.

CORS cumple ese papel. Decide qué orígenes tienen permiso para hablar con tu API desde navegador.

Qué pasa cuando CORS está mal configurado

Cuando CORS se configura mal, suelen aparecer estos errores:

  • usar Access-Control-Allow-Origin: *
  • reflejar cualquier Origin del request
  • permitir HTTP y HTTPS sin criterio
  • mezclar credentials: true con políticas incompatibles
  • abrir todo "para que no moleste durante desarrollo" y olvidarlo después

Eso no significa automáticamente que cualquiera pueda hacer cualquier cosa, porque siguen existiendo autenticación y autorización. Pero sí amplía innecesariamente la superficie de exposición y facilita escenarios que no deberías permitir.

Lo que mucha gente entiende mal sobre CORS

CORS no es solo "ese error molesto del navegador".

CORS es una capa de control.

Especialmente si tu app usa:

  • cookies de sesión
  • tokens
  • paneles autenticados
  • operaciones sensibles
  • datos privados

Una configuración demasiado permisiva no debería verse como comodidad. Debería verse como deuda técnica de seguridad.

Prompt para configurar CORS con Claude

Estoy construyendo una aplicación web. Mi frontend está en https://miapp.com y mi backend/API está en https://api.miapp.com.

Necesito que configures CORS correctamente para que:

  1. Solo acepte requests que vengan de mi dominio exacto: https://miapp.com
  2. Permita los métodos GET, POST, PUT y DELETE
  3. Permita los headers estándar más Authorization y Content-Type
  4. Soporte cookies y tokens de autenticación (credentials)
  5. Maneje correctamente los preflight requests (OPTIONS)

Reglas importantes:

  • No uses Access-Control-Allow-Origin: *
  • No copies el header Origin del request al response
  • Solo permite HTTPS, nunca HTTP
  • Si usas credentials: true, el origin tiene que ser exacto

También necesito que:

  • Me expliques qué es un preflight request y por qué importa
  • Me muestres cómo verificar que CORS está bien configurado usando DevTools
  • Me des un ejemplo de lo que pasa cuando alguien intenta acceder desde un dominio no autorizado

Mi stack es: [Next.js / Express / otro]

Qué es un preflight request

Antes de ciertas peticiones, el navegador lanza una solicitud OPTIONS para comprobar si la operación está permitida.

Ese paso previo pregunta algo parecido a esto:

  • ¿este origen puede llamar aquí?
  • ¿puede usar este método?
  • ¿puede enviar estos headers?

Si el servidor responde mal, la petición real no debería continuar.

Y si responde demasiado bien a cualquiera, has dejado la puerta más abierta de lo necesario.

Cómo revisar si tu CORS está bien configurado

Entra en tu app, abre DevTools y revisa las requests a la API.

Comprueba lo siguiente:

Qué revisarQué debería pasarAccess-Control-Allow-OriginDebe devolver tu dominio exactoUso de *No debería aparecer en producciónRequests OPTIONSDeben responder correctamentecredentialsDeben ser compatibles con un origen exactoOrígenes no autorizadosDeben quedar bloqueados

Si al revisar todo te parece "demasiado permisivo", probablemente lo es.

3. Security Headers: las reglas invisibles que hacen mucho más segura una app

Qué son Security Headers

Los Security Headers son instrucciones que el servidor envía al navegador para decirle qué debe aceptar, qué debe bloquear y bajo qué condiciones debe comportarse.

No sustituyen a la seguridad del backend, pero reducen muchísimo ciertos riesgos del lado cliente.

Una analogía sencilla

Piensa en un espacio profesional lleno de señalización:

  • por aquí no se puede pasar
  • esto no se puede incrustar
  • solo se aceptan recursos autorizados
  • estas capacidades están desactivadas

Eso hacen los headers de seguridad. No reconstruyen el edificio, pero sí ordenan su comportamiento y evitan muchos problemas antes de que ocurran.

Qué riesgos ayudan a reducir

Una buena base de headers ayuda a reducir cosas como:

  • clickjacking
  • carga de scripts o recursos no previstos
  • ejecución insegura de archivos
  • exposición innecesaria de información de referencia
  • uso no necesario de cámara, micro o geolocalización
  • problemas al degradar tráfico seguro

Los 6 headers que más suelen importar

HeaderPara qué sirveX-Frame-OptionsEvita que tu web sea incrustada en un iframe maliciosoContent-Security-PolicyControla desde dónde puede cargar recursos el navegadorX-Content-Type-OptionsEvita que el navegador adivine tipos de archivoStrict-Transport-SecurityObliga a usar HTTPSReferrer-PolicyControla qué información se envía al navegar a otros sitiosPermissions-PolicyDesactiva capacidades del navegador que no necesitas

El header más importante: CSP

Si hay uno que merece atención especial, ese es Content-Security-Policy.

Una CSP bien configurada limita muchísimo:

  • scripts inline inseguros
  • carga de recursos desde dominios no previstos
  • conexiones a endpoints no autorizados
  • incrustaciones o embeddings arriesgados

Pero también exige más precisión. Si tu app usa servicios externos, tienes que permitirlos explícitamente.

Eso significa que si trabajas con herramientas como:

  • Google Analytics
  • Stripe
  • YouTube
  • Vimeo
  • Firebase
  • CDNs concretos

tu CSP debe contemplarlos con criterio. Ni abrir de más ni bloquear lo legítimo.

Prompt para configurar Security Headers con Claude

Estoy construyendo una aplicación web con [Next.js / Express / otro]. Mi dominio es https://miapp.com.

Necesito que agregues todos los Security Headers de producción:

  1. X-Frame-Options: SAMEORIGIN

  2. Content-Security-Policy (CSP):

    • default-src 'self'
    • script-src 'self'
    • img-src 'self' https:
    • style-src 'self' 'unsafe-inline'
    • connect-src 'self' https://api.miapp.com
    • font-src 'self'
    • object-src 'none'
  3. X-Content-Type-Options: nosniff

  4. Strict-Transport-Security: max-age=31536000; includeSubDomains

  5. Referrer-Policy: strict-origin-when-cross-origin

  6. Permissions-Policy: geolocation=(), microphone=(), camera=()

Por favor:

  • Configura todo en el archivo correcto del framework
  • Si uso Next.js, colócalo en next.config.js en la sección headers
  • Muéstrame cómo verificar que están funcionando
  • Explícame qué hace cada header en una frase simple
  • Si uso Google Analytics, Stripe u otros servicios externos, dime qué tendría que ajustar en la CSP

Cómo comprobar que tus headers están funcionando

Puedes validarlo de varias formas:

MétodoQué mirarDevToolsResponse HeadersConsola del navegadorBloqueos de CSP o recursos no permitidosHerramientas de análisisEvaluación global de headers

Una CSP mal ajustada suele delatarse sola en la consola, porque el navegador te dirá qué recurso se intentó cargar y por qué lo bloqueó.

Cómo usar Claude bien en temas de seguridad

Claude puede ayudarte muchísimo con estas tres configuraciones, pero no conviene usarlo como si fuera un botón mágico.

La forma correcta de apoyarte en IA aquí es esta:

1. Dale contexto real

No digas "ponme seguridad".

Dile exactamente:

  • qué stack usas
  • qué dominios tienes
  • qué tablas intervienen
  • qué comportamiento quieres
  • qué servicios externos cargas
  • qué restricciones no deben romperse

2. Prohíbele atajos peligrosos

Cuando se trata de seguridad, conviene ser explícito con lo que no quieres:

  • no uses *
  • no reflejes Origin
  • no uses FOR ALL
  • no uses user_metadata si es manipulable
  • no abras la CSP más de lo necesario

3. Pídele validación, no solo implementación

No basta con pedir código.

Pídele también:

  • cómo probarlo
  • qué casos deben fallar
  • cómo detectar configuraciones demasiado permisivas
  • qué revisar en DevTools
  • qué errores esperar si algo está mal

Ahí es donde la IA deja de ser solo un generador rápido y se convierte en una herramienta realmente útil para producción.

Checklist rápido para revisar la seguridad base de tu app

  • Mis tablas sensibles tienen RLS activado
  • Mis políticas están separadas por SELECT, INSERT, UPDATE y DELETE
  • No confío solo en filtros del frontend o backend
  • Mi API no usa Access-Control-Allow-Origin: *
  • No reflejo dinámicamente cualquier Origin
  • Mis requests OPTIONS están bien resueltas
  • Tengo X-Frame-Options
  • Tengo una Content-Security-Policy razonable
  • Tengo X-Content-Type-Options: nosniff
  • Tengo HSTS en producción
  • Tengo Referrer-Policy
  • Tengo Permissions-Policy
  • He probado todo con usuarios y escenarios reales

La idea importante de fondo

No necesitas saber todo sobre seguridad para mejorar muchísimo el nivel de tu proyecto.

Lo que sí necesitas saber es esto:

  • qué piezas importan
  • qué problema resuelve cada una
  • cómo pedirlas correctamente
  • cómo probar que de verdad funcionan

Ese punto intermedio es donde una IA como Claude aporta muchísimo valor. No porque piense por ti, sino porque acelera una ejecución que tú ya sabes dirigir.

Conclusión

Programar con Claude es una ventaja enorme.

Pero una app rápida no siempre es una app segura.

Si quieres una base seria, hay tres piezas que no deberías dejar para "más adelante": RLS, CORS y Security Headers.

No son adornos. No son extras. Son parte de la estructura.

Y cuanto antes las trates como parte del producto, antes dejarás de construir funcionalidades sobre una base demasiado frágil.

Porque programar con IA puede hacerte avanzar muy deprisa.

Pero avanzar deprisa hacia una app mal protegida sigue siendo avanzar en la dirección equivocada.

Preguntas frecuentes

¿Qué es RLS en Supabase?

Es el sistema de PostgreSQL que permite aplicar reglas por fila para que cada usuario solo pueda acceder a los datos que le corresponden.

¿CORS protege por sí solo mi API?

No. CORS no sustituye autenticación ni autorización, pero sí evita una exposición innecesaria a orígenes no autorizados en navegador.

¿Qué Security Headers debería tener una app en producción?

Como base, suele ser razonable incluir X-Frame-Options, Content-Security-Policy, X-Content-Type-Options, Strict-Transport-Security, Referrer-Policy y Permissions-Policy.

¿Claude puede configurarlo bien?

Sí, pero el resultado depende mucho del nivel de precisión del prompt. Cuanto más contexto y más restricciones claras le des, mejor.

Keywords SEO

  • proteger app web
  • seguridad en aplicaciones web
  • row level security supabase
  • row level security postgresql
  • configurar cors correctamente
  • security headers producción
  • content security policy ejemplo
  • cómo proteger una api web
  • seguridad web con claude
  • prompts de seguridad para claude

Tags

Inteligencia Artificial · Claude · Seguridad Web · Supabase · PostgreSQL · CORS · RLS · Security Headers · Desarrollo Web · Backend

With Love by Carlos Anegón!