DEV Community

Cover image for Tu API Elimina Metadatos C2PA: Cómo Detectarlo con una Prueba
Roobia
Roobia

Posted on • Originally published at apidog.com

Tu API Elimina Metadatos C2PA: Cómo Detectarlo con una Prueba

Claude ahora adjunta metadatos de procedencia C2PA firmados a los archivos que genera. También lo hacen los modelos de imagen de OpenAI, y también Gemini. Esto significa que una señal de procedencia real está llegando a su endpoint de carga por primera vez, y hay una buena probabilidad de que su pipeline la esté eliminando antes de que alguien la vea.

Pruebe Apidog hoy

No de forma maliciosa: ocurre por defecto. sharp().resize() genera un archivo limpio sin metadatos, salvo que indique lo contrario. Lo mismo sucede con ImageMagick, Pillow y la mayoría de los CDN de imágenes. El manifiesto entra, sale un JPEG más pequeño y sus registros no informan nada.

Este es un fallo comprobable. En este artículo verá cómo identificar dónde se pierden los metadatos, cómo probar su pipeline de extremo a extremo y cómo añadir una verificación permanente en CI. Apidog orquesta el flujo HTTP; c2patool verifica el archivo a nivel de bytes.

Qué se destruye realmente

Un manifiesto C2PA es un bloque firmado criptográficamente e incrustado en el contenedor del archivo. Registra quién firmó el activo y qué se afirmó sobre él. Como está firmado, cambiar los bytes sin volver a firmar invalida la firma de una forma detectable por cualquier verificador.

La clave está en el contenedor: si lo reescribe, el manifiesto puede desaparecer.

Operación ¿El manifiesto sobrevive por defecto?
Copia o movimiento byte a byte
sharp().resize().toBuffer() No
ImageMagick convert / magick No
Pillow Image.save() No
PNG a WebP, JPEG a AVIF No
Autooptimización de CDN de imágenes Usualmente no
Captura de pantalla No
Volver a guardar desde un editor de imágenes No
Subida a S3 sin transformación

Todo lo que aparece como “No” es habitual en una aplicación web: miniaturas, variantes responsivas, negociación de formato o limpieza de EXIF por privacidad. Cada operación es razonable de forma aislada, pero puede terminar silenciosamente la cadena de procedencia.

También hay un conflicto práctico: -strip suele utilizarse para eliminar coordenadas GPS y números de serie de cámaras presentes en EXIF. Sin embargo, eliminar todos los metadatos también elimina el manifiesto C2PA. La solución es eliminar de forma selectiva los bloques que no quiere conservar, en lugar de borrar todos los metadatos.

Pruébelo en dos minutos

Antes de cambiar el pipeline, confirme el problema. Necesita un archivo con un manifiesto válido: puede usar una imagen generada por Claude o una muestra firmada de la Content Authenticity Initiative.

Instale la CLI de referencia:

cargo install c2patool
Enter fullscreen mode Exit fullscreen mode

Compruebe que el fixture está firmado:

c2patool fixtures/signed-sample.png
Enter fullscreen mode Exit fullscreen mode

Debería recibir un informe JSON con el generador de la reclamación y el estado de validación de la firma.

Ahora envíe el archivo por su pipeline real y recupérelo usando la misma URL que consume su frontend:

# Subir a través de su endpoint real
curl -sS -X POST https://api.example.com/v1/assets \
  -H "Authorization: Bearer $API_TOKEN" \
  -F "file=@fixtures/signed-sample.png" \
  -o /tmp/upload.json

# Recuperarlo a través de la URL que usaría su frontend
ASSET_URL=$(jq -r '.url' /tmp/upload.json)
curl -sS "$ASSET_URL" -o /tmp/roundtrip.png

# ¿Sobrevivió el manifiesto?
c2patool /tmp/roundtrip.png
Enter fullscreen mode Exit fullscreen mode

Interprete el resultado:

  • Informe válido: el manifiesto sobrevivió.
  • Manifiesto no encontrado: alguna etapa del pipeline lo eliminó.
  • Error de validación: el manifiesto existe, pero la firma ya no coincide con los bytes.

El tercer caso es especialmente importante. Normalmente indica que una biblioteca preservó el bloque de metadatos mientras modificaba los píxeles. Para cualquier verificador posterior, eso parece una alteración del archivo.

Encuentre la etapa que lo elimina

Si la prueba de extremo a extremo falla, no adivine. Divida el pipeline y ejecute c2patool inmediatamente después de cada etapa:

  1. Después de recibir la carga.
  2. Después del redimensionamiento.
  3. Después de convertir el formato.
  4. Después de almacenar en el origen.
  5. Después de recuperar desde el CDN.

Los sospechosos habituales son los siguientes.

1. Redimensionamiento o generación de miniaturas

Es el caso más probable. En sharp, los metadatos se eliminan salvo que los conserve explícitamente:

// Elimina el manifiesto C2PA
await sharp(input).resize(1200).toFile(output);

// Conserva el bloque de metadatos
await sharp(input).resize(1200).keepMetadata().toFile(output);
Enter fullscreen mode Exit fullscreen mode

Conservar el bloque es necesario, pero no suficiente. Los píxeles cambiaron, por lo que la firma original ya no será válida para los bytes nuevos.

Para mantener una cadena de procedencia funcional:

  1. Conserve los metadatos necesarios.
  2. Aplique la transformación.
  3. Vuelva a firmar la salida.
  4. Registre la transformación como una aserción de acción, normalmente c2pa.resized.

Las bibliotecas c2pa para Rust, Python, JavaScript y C permiten implementar este flujo.

2. Conversión de formato

Servir AVIF o WebP crea un contenedor nuevo. La regla es la misma: preserve y vuelva a firmar, o acepte explícitamente que la cadena de procedencia termina en esa transformación.

3. CDN de imágenes

Muchos CDN reescriben imágenes en el momento de la entrega. Algunos preservan y vuelven a firmar Credenciales de Contenido de forma nativa; históricamente, la mayoría las eliminaban.

Pruebe siempre la URL de entrega real que visitan sus usuarios, no solo el archivo de origen. Una prueba contra el origen puede pasar aunque el CDN elimine el manifiesto.

4. Normalización durante la carga

Los servicios que recodifican archivos al recibirlos para estandarizar formatos suelen pasar desapercibidos. Con frecuencia, esta lógica vive en un repositorio de infraestructura separado del backend principal.

Conviértalo en una prueba permanente

Un único curl valida el estado actual, pero no evita que alguien introduzca una transformación en el próximo sprint. La verificación debe formar parte de CI.

Divida la prueba en dos capas:

  1. Orquestación HTTP de ida y vuelta.
  2. Verificación criptográfica del archivo recuperado.

Capa uno: viaje de ida y vuelta en Apidog

La orquestación es un escenario de API encadenado:

  1. Subir un fixture firmado.
  2. Extraer la URL devuelta.
  3. Recuperar el activo por la ruta de entrega real.
  4. Comprobar estado, tipo de contenido y tamaño.

En Apidog, cree un escenario con dos pasos.

Paso 1: POST /v1/assets

  • Cuerpo: multipart/form-data con el fixture firmado.
  • Aserciones: estado 201 y respuesta válida según su esquema.
  • Script posrespuesta para guardar la URL:
const body = pm.response.json();

pm.environment.set("ASSET_URL", body.url);

pm.test("upload returns a delivery URL", function () {
  pm.expect(body.url).to.be.a("string").and.to.include("https://");
});
Enter fullscreen mode Exit fullscreen mode

La mecánica de carga es la misma que en la prueba de APIs de carga de archivos.

Paso 2: GET {{ASSET_URL}}

  • Aserciones: estado 200, Content-Type esperado y tamaño de respuesta cercano al archivo original.
  • Una caída importante de tamaño es una señal útil de recodificación.
const uploadedBytes = Number(pm.environment.get("FIXTURE_BYTES"));
const returnedBytes = pm.response.responseSize;

pm.test("asset was not silently re-encoded", function () {
  pm.expect(returnedBytes).to.be.above(uploadedBytes * 0.9);
});
Enter fullscreen mode Exit fullscreen mode

El tamaño es una heurística, no una prueba criptográfica. Es útil para detectar fallos obvios de forma económica dentro de la misma suite HTTP. Consulte más patrones en aserción de APIs.

Capa dos: verificación a nivel de bytes en CI

Validar una firma exige analizar el contenedor del archivo. Ese trabajo corresponde a c2patool, no a un cliente HTTP.

Ejecute c2patool contra el archivo descargado por el escenario de ida y vuelta:

# .github/workflows/provenance.yml
name: provenance

on: [pull_request]

jobs:
  c2pa-round-trip:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - name: Instalar c2patool
        run: cargo install c2patool

      - name: Instalar Apidog CLI
        run: npm install -g apidog-cli

      - name: Ejecutar el escenario de ida y vuelta
        run: |
          apidog run --access-token "$APIDOG_ACCESS_TOKEN" \
            -t "$SCENARIO_ID" \
            -e "$ENV_ID" \
            -r cli,html \
            --out-dir ./apidog-reports
        env:
          APIDOG_ACCESS_TOKEN: ${{ secrets.APIDOG_ACCESS_TOKEN }}
          SCENARIO_ID: ${{ vars.PROVENANCE_SCENARIO_ID }}
          ENV_ID: ${{ vars.APIDOG_ENV_ID }}

      - name: Verificar que el manifiesto sobrevivió
        run: |
          set -euo pipefail
          curl -sS "$ASSET_URL" -o /tmp/roundtrip.png
          c2patool /tmp/roundtrip.png > /tmp/report.json
          jq -e '.validation_status == null or (.validation_status | length) == 0' /tmp/report.json
Enter fullscreen mode Exit fullscreen mode

set -euo pipefail es importante. Sin esta instrucción, un fallo de c2patool ante un archivo sin metadatos puede convertirse en una advertencia y dejar la compilación en verde: exactamente el fallo que esta prueba pretende evitar.

Para configurar escenarios en un pipeline, consulte la automatización de pruebas de API en GitHub Actions.

Capa tres opcional: endpoint de verificación

Si la procedencia es una característica de producto y no solo un control interno, añada un endpoint propio que ejecute una biblioteca c2pa y devuelva un resultado estructurado.

Así puede probarlo como JSON normal y el frontend recibe un estado explícito:

{
  "asset_id": "img_9f2c41",
  "provenance": {
    "status": "verified",
    "standard": "c2pa",
    "signer": "Anthropic",
    "signature_valid": true,
    "checked_at": "2026-08-11T09:14:22Z",
    "tool": "c2patool/0.9"
  }
}
Enter fullscreen mode Exit fullscreen mode

Mantenga al menos tres estados:

  • verified: hay un manifiesto y la firma es válida.
  • absent: no se encontró ningún manifiesto.
  • invalid: existe un manifiesto, pero la firma no coincide con los bytes.

No reduzca absent e invalid a un booleano. Representan situaciones distintas y invalid es una señal mucho más relevante. Si el verificador puede no estar disponible, añada unchecked para no confundir una interrupción con un resultado limpio.

Documente esta respuesta en OpenAPI y valídela para evitar que los campos desaparezcan durante una refactorización. Consulte Cómo validar especificaciones OpenAPI.

Los cuatro fixtures que debe conservar

Una suite de procedencia necesita casos deliberadamente defectuosos, no solo un camino feliz.

  1. Archivo firmado válido

    Resultado esperado: verified. Detecta eliminación excesiva de metadatos.

  2. Archivo sin metadatos

    Use la misma imagen, pero elimine el manifiesto con exiftool -all=.

    Resultado esperado: absent, no un error y nunca verified.

  3. Archivo manipulado

    Use un archivo firmado y altere un byte después de la firma.

    Resultado esperado: invalid. Este caso demuestra que valida la firma y no solo la existencia de un bloque de metadatos.

  4. Formato no compatible

    Use un formato sin soporte de manifiestos.

    Resultado esperado: absent de forma limpia, no un error 500.

Guarde los cuatro fixtures en el repositorio junto al escenario de prueba. Son pequeños, no deberían cambiar y convierten una prueba que “pasa” en una prueba que realmente valida el comportamiento esperado.

Por qué merece la pena

Hay tres motivos principales.

  • La afirmación de su producto. Si su interfaz muestra un distintivo de procedencia, pero el pipeline elimina manifiestos durante el redimensionamiento, ese distintivo será incorrecto para todos los activos transformados.

  • Cumplimiento. Si depende de C2PA para requisitos relacionados con el Artículo 50, un manifiesto eliminado significa que su control no funciona. La separación entre proveedor y desplegador se explica en el Artículo 50 de la Ley de IA de la UE para desarrolladores de API.

  • La señal de procedencia. C2PA solo aporta valor cuando la cadena se mantiene de extremo a extremo. Cada pipeline que elimina manifiestos silenciosamente reduce la utilidad del ecosistema, incluso cuando necesita verificar un activo usted mismo.

Descargue Apidog para crear el escenario de ida y vuelta contra sus endpoints y añada después la verificación con c2patool en CI.

Preguntas frecuentes

  • ¿El redimensionamiento de una imagen elimina los metadatos C2PA?

    Sí, por defecto en las bibliotecas más comunes. Conservar el bloque requiere una opción explícita y mantener una firma válida requiere volver a firmar la salida transformada.

  • ¿Cómo verifico si un archivo tiene metadatos C2PA?

    Ejecute c2patool <file> desde la línea de comandos o arrastre el archivo a la página de verificación de Content Credentials.

  • ¿Puedo mantener los metadatos C2PA al redimensionar?

    Sí, pero no basta con conservarlos. Debe preservar el bloque, volver a firmar la salida y registrar la transformación mediante una aserción de acción como c2pa.resized.

  • ¿Los CDN eliminan las Credenciales de Contenido?

    Muchos las eliminan cuando autooptimizan imágenes. Algunos las preservan y vuelven a firmar de forma nativa. Pruebe la URL de entrega real, no solo el origen.

  • ¿Cuál es la diferencia entre un manifiesto eliminado y uno inválido?

    absent significa que no hay manifiesto. invalid significa que existe, pero su firma no coincide con los bytes, lo que indica que el archivo cambió después de firmarse.

  • ¿Puede Apidog verificar directamente una firma C2PA?

    Apidog orquesta el viaje de ida y vuelta y puede validar respuestas HTTP o JSON de un endpoint de verificación. El análisis criptográfico de la firma corresponde a c2patool, ejecutado en CI o dentro de su propio servicio.

  • ¿Debo eliminar EXIF por privacidad y conservar C2PA?

    Sí. El enfoque correcto es selectivo: elimine los bloques EXIF específicos que no desea conservar y mantenga el manifiesto C2PA. Un -strip general elimina ambos.

La conclusión

Los metadatos de procedencia suelen llegar intactos a su API y perderse durante una transformación posterior sin que sus métricas lo detecten.

La implementación mínima es clara:

  1. Añada un fixture firmado.
  2. Súbalo por su endpoint real.
  3. Descárguelo desde la URL de entrega real.
  4. Verifíquelo con c2patool.
  5. Haga fallar CI cuando el manifiesto esté ausente o sea inválido.

Con una configuración breve, convierte un distintivo de procedencia en su interfaz en una garantía que su pipeline aplica de verdad.

Top comments (0)