DEV Community

Cover image for API ของคุณลบเมตาดาต้า C2PA: วิธีตรวจจับด้วยการทดสอบ
Thanawat Wongchai
Thanawat Wongchai

Posted on Originally published at apidog.com

API ของคุณลบเมตาดาต้า C2PA: วิธีตรวจจับด้วยการทดสอบ

ปัจจุบัน Claude แนบเมตาดาต้า C2PA provenance ที่ลงนามแล้วกับไฟล์ที่สร้างขึ้น โมเดลภาพของ OpenAI ก็ทำเช่นกัน และ Gemini ก็เช่นกัน ซึ่งหมายความว่าสัญญาณ provenance ที่แท้จริงกำลังมาถึง endpoint อัปโหลดของคุณเป็นครั้งแรก แต่มีโอกาสสูงที่ pipeline จะลบมันทิ้งก่อนถึงผู้ใช้

ลองใช้ Apidog วันนี้

โดยปกติไม่ได้เกิดจากเจตนาร้าย แต่เกิดจากค่าเริ่มต้น เช่น sharp().resize() จะสร้างไฟล์ใหม่โดยไม่มีเมตาดาต้า เว้นแต่จะระบุให้เก็บไว้ เช่นเดียวกับ ImageMagick, Pillow และ Image CDN ส่วนใหญ่ ผลลัพธ์คือ manifest ถูกอัปโหลดเข้ามา แต่ไฟล์ JPEG ที่เล็กลงถูกส่งออกไปโดยไม่มี provenance และไม่มี log แจ้งเตือน

บทความนี้จะแสดงวิธีตรวจสอบว่าปัญหาเกิดขึ้นใน pipeline ของคุณหรือไม่ ระบุขั้นตอนที่ทำให้ manifest หาย และเพิ่มการตรวจสอบแบบ round-trip เข้า CI โดยใช้ Apidog สำหรับ flow ของ API และ c2patool สำหรับการตรวจสอบระดับไบต์

อะไรที่ถูกทำลายไปจริงๆ

Manifest ของ C2PA คือข้อมูลที่ลงนามด้วยการเข้ารหัสและฝังอยู่ในคอนเทนเนอร์ของไฟล์ โดยระบุผู้ลงนามในสินทรัพย์และคำกล่าวอ้างที่เกี่ยวข้องกับไฟล์นั้น

เพราะ manifest ถูกลงนามไว้ การเปลี่ยนไบต์ของไฟล์โดยไม่ลงนามใหม่จะทำให้ลายเซ็นไม่ถูกต้อง และตัวตรวจสอบสามารถตรวจพบได้

ประเด็นสำคัญคือ ระดับคอนเทนเนอร์: เมื่อคุณเขียนคอนเทนเนอร์ไฟล์ใหม่ manifest เดิมมักหายไป

การดำเนินการ Manifest ยังคงอยู่โดยค่าเริ่มต้นหรือไม่?
คัดลอกหรือย้ายแบบไบต์ต่อไบต์ ใช่
sharp().resize().toBuffer() ไม่
ImageMagick convert / magick ไม่
Pillow Image.save() ไม่
PNG เป็น WebP, JPEG เป็น AVIF ไม่
การปรับแต่งอัตโนมัติของ Image CDN โดยปกติไม่
ภาพหน้าจอ ไม่
บันทึกซ้ำจากโปรแกรมแก้ไขรูปภาพ ไม่
การอัปโหลด S3 โดยไม่มีการแปลง ใช่

รายการในคอลัมน์ “ไม่” คือสิ่งที่ web application ทำกับรูปภาพอยู่แล้ว: สร้าง thumbnail, สร้าง responsive variant, แปลง format, หรือล้าง EXIF เพื่อความเป็นส่วนตัว แต่ละขั้นตอนอาจสมเหตุสมผล แต่สามารถตัดห่วงโซ่ provenance ได้แบบเงียบ ๆ

ตัวอย่างที่ต้องระวังคือ -strip เพื่อความเป็นส่วนตัว เนื่องจาก EXIF อาจมีพิกัด GPS หรือหมายเลขซีเรียลของกล้อง แต่การลบเมตาดาต้าทั้งหมดจะลบ C2PA manifest ไปด้วย หากต้องการลบข้อมูลส่วนตัวแต่ยังเก็บ provenance ให้ลบเฉพาะบล็อก EXIF ที่ต้องการ แทนการ strip ทุกอย่าง

พิสูจน์ได้ในสองนาที

ก่อนแก้ pipeline ให้ตรวจสอบก่อนว่าปัญหาเกิดขึ้นจริงหรือไม่

เตรียม fixture หนึ่งไฟล์ที่มี manifest ถูกต้อง เช่น ไฟล์ภาพที่ Claude สร้าง หรือไฟล์ตัวอย่างที่ลงนามแล้วจาก Content Authenticity Initiative

ติดตั้ง CLI อ้างอิง:

cargo install c2patool
Enter fullscreen mode Exit fullscreen mode

ตรวจสอบว่า fixture มีลายเซ็นที่ใช้ได้:

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

คุณควรได้รายงาน JSON ที่มีข้อมูลผู้สร้างคำกล่าวอ้างและสถานะลายเซ็น จากนั้นอัปโหลดผ่าน endpoint จริง แล้วดึงไฟล์กลับผ่าน URL เดียวกับที่ frontend ใช้งาน:

# Upload through your real endpoint
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

# Fetch it back through the URL your frontend would use
ASSET_URL=$(jq -r '.url' /tmp/upload.json)
curl -sS "$ASSET_URL" -o /tmp/roundtrip.png

# Did the manifest survive?
c2patool /tmp/roundtrip.png
Enter fullscreen mode Exit fullscreen mode

ตีความผลลัพธ์เป็น 3 กรณี:

  1. รายงานถูกต้อง — manifest ยังอยู่และลายเซ็นตรวจสอบผ่าน
  2. ไม่พบ manifest — มีขั้นตอนใน pipeline ลบ manifest ออก
  3. ข้อผิดพลาดในการตรวจสอบ — manifest ยังอยู่ แต่ลายเซ็นไม่ตรงกับไบต์ปัจจุบัน

กรณีที่สามต้องให้ความสำคัญเป็นพิเศษ เพราะมักหมายความว่าเครื่องมือแปลงภาพเก็บ metadata block ไว้ แต่เขียนพิกเซลใหม่ ทำให้ไฟล์ดูเหมือนถูกแก้ไขหลังการลงนาม

ค้นหาขั้นตอนที่เป็นต้นเหตุ

หาก round-trip ล้มเหลว อย่าคาดเดา ให้ตรวจสอบ manifest หลังแต่ละขั้นตอนของ pipeline เพื่อหา breakpoint

ผู้ต้องสงสัยหลักมีดังนี้

1. การปรับขนาดและสร้าง thumbnail

ใน sharp เมตาดาต้าจะถูกลบโดยค่าเริ่มต้น:

// Drops the C2PA manifest
await sharp(input).resize(1200).toFile(output);

// Preserves the metadata block
await sharp(input).resize(1200).keepMetadata().toFile(output);
Enter fullscreen mode Exit fullscreen mode

อย่างไรก็ตาม keepMetadata() เพียงอย่างเดียวไม่ทำให้ provenance ใช้งานได้เสมอไป เพราะพิกเซลเปลี่ยนแล้ว ลายเซ็นเดิมจึงไม่สามารถยืนยันกับไบต์ใหม่ได้

หากต้องการรักษาห่วงโซ่ provenance ที่ถูกต้อง ให้ทำทั้งสองอย่าง:

  1. เก็บ metadata ที่ต้องการ
  2. ลงนามผลลัพธ์ใหม่ พร้อมบันทึกการแปลงเป็น action assertion เช่น c2pa.resized

ไลบรารี c2pa สำหรับ Rust, Python, JavaScript และ C รองรับแนวทางนี้

2. การแปลงรูปแบบ

การแปลง PNG เป็น WebP หรือ JPEG เป็น AVIF หมายถึงการสร้างคอนเทนเนอร์ใหม่

ทางเลือกมี 2 แบบ:

  • เก็บข้อมูลที่จำเป็นและลงนามไฟล์ผลลัพธ์ใหม่
  • ยอมรับว่าห่วงโซ่ provenance สิ้นสุดที่ขั้นตอนนี้ และแสดงสถานะให้ชัดเจน

3. Image CDN

Image CDN จำนวนมากเขียนไฟล์ใหม่ตอนส่งมอบ เช่น ปรับคุณภาพ ปรับขนาด หรือแปลง format อัตโนมัติ

ต้องทดสอบผ่าน delivery URL ที่ผู้ใช้เข้าถึงจริง ไม่ใช่ origin URL มิฉะนั้นผลทดสอบอาจผ่านทั้งที่ไฟล์จริงหน้าเว็บสูญเสีย manifest ไปแล้ว

4. Upload normalization

บริการบางตัวเข้ารหัสรูปใหม่ทันทีหลังอัปโหลดเพื่อทำให้ไฟล์เป็นมาตรฐาน ขั้นตอนนี้มักซ่อนอยู่ใน infrastructure repository หรือ worker ที่ไม่ค่อยถูกตรวจสอบ

เพิ่มการตรวจสอบ c2patool ก่อนและหลัง normalization เพื่อยืนยันผลลัพธ์

ทำให้เป็นการทดสอบถาวร

การรัน curl ครั้งเดียวบอกได้เพียงสถานะปัจจุบัน แต่ไม่ได้ป้องกัน regression เมื่อมีคนเพิ่ม resize step ใน sprint ถัดไป

ให้แยกการทดสอบเป็น 2 เลเยอร์:

  1. Apidog ตรวจสอบ API round-trip และ HTTP response
  2. c2patool ตรวจสอบ manifest และลายเซ็นระดับไบต์

เลเยอร์แรก: การตรวจสอบแบบ round-trip ใน Apidog

สร้าง scenario ที่มี 2 ขั้นตอน:

  1. อัปโหลด fixture ที่ลงนามแล้ว
  2. ดาวน์โหลด asset จาก delivery URL ที่ API ส่งกลับ

ขั้นตอนที่ 1: POST /v1/assets

  • ตั้งค่า Body เป็น multipart/form-data
  • แนบ signed fixture
  • ตรวจสอบว่า response status เป็น 201
  • ตรวจสอบ response schema
  • เก็บ URL จาก response ไว้ใช้ในขั้นตอนถัดไป

แนวทางการตั้งค่า multipart เหมือนกับบทความ การทดสอบ API อัปโหลดไฟล์

เพิ่ม post-response script:

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

ขั้นตอนที่ 2: GET {{ASSET_URL}}

ตรวจสอบว่า:

  • status เป็น 200
  • Content-Type ตรงกับรูปแบบที่คาดหวัง
  • ขนาด response ไม่ลดลงอย่างผิดปกติ
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

การเทียบขนาดไฟล์เป็นเพียง heuristic ไม่ใช่ข้อพิสูจน์ว่าลายเซ็นยังใช้ได้ แต่ช่วยตรวจจับการ re-encode ที่ชัดเจนได้เร็วใน test suite เดียวกัน

ดูแนวทาง assertion เพิ่มเติมได้ที่ API assertions

เลเยอร์สอง: การตรวจสอบระดับไบต์ใน CI

Apidog ตรวจสอบ flow ของ HTTP ได้ แต่การ parse และตรวจสอบลายเซ็น C2PA ต้องใช้ c2patool

ตัวอย่าง GitHub Actions:

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

on: [pull_request]

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

    steps:
      - uses: actions/checkout@v4

      - name: Install c2patool
        run: cargo install c2patool

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

      - name: Run the round-trip scenario
        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: Verify the manifest survived
        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 สำคัญมาก เพราะหาก c2patool ล้มเหลวแต่ shell ไม่ส่งผลให้ job ล้มเหลว คุณจะได้ build สีเขียวทั้งที่ manifest ถูกลบออกไปแล้ว

หากเพิ่งเริ่มรัน Apidog scenario ใน pipeline ดูการตั้งค่าได้ใน การทำให้การทดสอบ API เป็นอัตโนมัติใน GitHub Actions

เลเยอร์สาม: verification endpoint

หาก provenance เป็น feature ของผลิตภัณฑ์ ไม่ใช่แค่ internal check ให้สร้าง endpoint สำหรับตรวจสอบโดยเฉพาะ

endpoint นี้ควรรันไลบรารี c2pa และส่งคืนผลแบบมีโครงสร้าง เช่น:

{
  "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

อย่าใช้เพียง boolean เดียว ให้เก็บอย่างน้อย 3 สถานะ:

  • verified — พบ manifest และลายเซ็นถูกต้อง
  • absent — ไม่พบ manifest
  • invalid — พบ manifest แต่ลายเซ็นไม่ตรงกับไฟล์

และควรเพิ่ม:

  • unchecked — ยังไม่ได้ตรวจสอบ เช่น verifier ไม่พร้อมใช้งาน

absent และ invalid มีความหมายต่างกัน การรวมทั้งสองเป็น false จะทำให้คุณสูญเสียสัญญาณสำคัญ

กำหนด schema นี้ใน OpenAPI และตรวจสอบใน CI เพื่อป้องกัน field หายระหว่าง refactor ดูแนวทางได้ที่ วิธีการตรวจสอบ OpenAPI specs

สี่ fixtures ที่ควรเก็บไว้

ชุดทดสอบ provenance ไม่ควรมีเฉพาะ happy path ให้เก็บ fixture ที่ครอบคลุม failure mode ด้วย

  1. ไฟล์ที่ลงนามถูกต้อง

    คาดหวัง verified ใช้ตรวจจับการลบ manifest โดยไม่ตั้งใจ

  2. ไฟล์ที่ถูกลบ manifest แล้ว

    ใช้รูปเดียวกัน แต่ลบ metadata ด้วย exiftool -all=

    คาดหวัง absent ไม่ใช่ verified และไม่ควรเป็น server error

  3. ไฟล์ที่ถูกแก้ไขหลังลงนาม

    เปลี่ยนไบต์บางส่วนหลังจากลงนาม

    คาดหวัง invalid เพื่อพิสูจน์ว่าระบบตรวจลายเซ็นจริง ไม่ใช่แค่ตรวจว่ามี metadata block

  4. รูปแบบที่ไม่รองรับ

    ใช้ไฟล์ที่ไม่มีการรองรับ manifest

    คาดหวัง absent อย่างชัดเจน แทนการตอบ 500

คอมมิต fixture ทั้ง 4 ไฟล์ไว้ใน repository ถัดจาก scenario ทดสอบ ไฟล์เหล่านี้ควรมีขนาดเล็ก คงที่ และใช้ซ้ำได้ในทุก pull request

ทำไมต้องสนใจ

มี 3 เหตุผลหลัก

1. ความถูกต้องของ product claim

หาก UI แสดงป้าย provenance แต่ pipeline ลบ manifest เมื่อสร้าง thumbnail หรือ responsive image ป้ายนั้นจะผิดทันทีสำหรับไฟล์ที่ผ่านการแปลง

2. การปฏิบัติตามข้อกำหนด

หากคุณใช้ C2PA ใน flow ที่เกี่ยวข้องกับ Article 50 การลบ manifest คือ control ที่ใช้งานไม่ได้ ดูรายละเอียดการแบ่งหน้าที่ของ provider และ deployer ได้ใน EU AI Act Article 50 สำหรับนักพัฒนา API

3. ความน่าเชื่อถือของสัญญาณ provenance

Provenance มีประโยชน์ก็ต่อเมื่อห่วงโซ่ยังอยู่ครบตั้งแต่ต้นทางถึงปลายทาง ทุก pipeline ที่ลบ manifest แบบเงียบ ๆ ทำให้ระบบนิเวศตรวจสอบเนื้อหาได้ยากขึ้น รวมถึงเมื่อคุณต้องตรวจสอบไฟล์จากผู้อื่น

ดาวน์โหลด Apidog เพื่อสร้าง scenario แบบ round-trip กับ endpoint ของคุณ แล้วต่อด้วยขั้นตอน c2patool ใน CI

คำถามที่พบบ่อย

การปรับขนาดรูปภาพจะลบเมตาดาต้า C2PA หรือไม่?

ใช่ โดยค่าเริ่มต้นในไลบรารีทั่วไป การเก็บ metadata ต้องเปิด flag อย่างชัดเจน และหากพิกเซลเปลี่ยน ต้องลงนามผลลัพธ์ใหม่เพื่อให้ลายเซ็นยังถูกต้อง

ฉันจะตรวจสอบได้อย่างไรว่าไฟล์มีเมตาดาต้า C2PA หรือไม่?

รันคำสั่ง:

c2patool <file>
Enter fullscreen mode Exit fullscreen mode

หรืออัปโหลดไฟล์ไปที่ หน้าตรวจสอบ Content Credentials

ฉันสามารถเก็บ C2PA เมื่อปรับขนาดภาพได้หรือไม่?

ได้ แต่ต้องมากกว่าการเก็บ metadata block เดิม ให้เก็บข้อมูลที่จำเป็น แล้วลงนามไฟล์ผลลัพธ์ใหม่พร้อม action assertion เช่น c2pa.resized มิฉะนั้นลายเซ็นเดิมจะไม่ตรงกับไบต์ใหม่

CDN ลบ Content Credentials หรือไม่?

หลาย CDN ลบออกเมื่อมีการปรับแต่งภาพอัตโนมัติ บางระบบสามารถเก็บและลงนามใหม่ได้ ต้องทดสอบผ่าน delivery URL ที่ผู้ใช้ใช้งานจริง ไม่ใช่ origin

ความแตกต่างระหว่าง stripped กับ invalid คืออะไร?

  • stripped หรือ absent: ไม่พบ manifest
  • invalid: พบ manifest แต่ลายเซ็นไม่ตรงกับไบต์ของไฟล์

ให้เก็บสองสถานะนี้แยกกัน เพราะบ่งชี้ปัญหาคนละแบบ

Apidog ตรวจสอบลายเซ็น C2PA ได้โดยตรงหรือไม่?

Apidog เหมาะกับการตรวจสอบ round-trip, HTTP response และ JSON จาก verification endpoint ส่วนการ parse และตรวจสอบลายเซ็นเป็นหน้าที่ของ c2patool หรือไลบรารี c2pa ในบริการของคุณเอง

ควรลบ EXIF เพื่อความเป็นส่วนตัว แต่เก็บ C2PA ไว้หรือไม่?

ควรทำ หากต้องการลบข้อมูลส่วนตัว เช่น GPS ให้ลบเฉพาะบล็อก EXIF ที่เกี่ยวข้อง หลีกเลี่ยงการใช้ -strip แบบครอบคลุม เพราะจะลบ C2PA manifest ออกด้วย

บทสรุป

เมตาดาต้า provenance อาจเข้ามาถึง API ของคุณอย่างสมบูรณ์ แต่ถูกทำลายระหว่าง resize, re-encode หรือ CDN delivery โดยไม่มีการแจ้งเตือน

แนวทางที่ใช้งานได้จริงคือ:

  1. เตรียม signed fixture
  2. ทดสอบ upload และ download ผ่าน delivery path จริง
  3. ใช้ Apidog ตรวจสอบ API flow
  4. ใช้ c2patool ตรวจสอบ manifest ใน CI
  5. ทำให้ build ล้มเหลวเมื่อ manifest หายหรือสถานะลายเซ็นไม่ถูกต้อง

ใช้เวลาเซ็ตอัปไม่นาน แต่ช่วยเปลี่ยนป้าย provenance ใน UI จากคำกล่าวอ้าง ให้กลายเป็นสิ่งที่ pipeline ของคุณบังคับใช้ได้จริง

Top comments (0)