From d8e53cf7dc12d0b60de9c3022edb36d28fc9e4b3 Mon Sep 17 00:00:00 2001 From: Prospector <6166773+Prospector@users.noreply.github.com> Date: Fri, 7 Aug 2026 17:30:58 -0700 Subject: [PATCH] add AI metadata checking to block image uploads with notice --- apps/frontend/package.json | 1 + .../src/components/ui/AiImageWarningModal.vue | 52 +++++++++++++++++++ apps/frontend/src/helpers/c2pa.ts | 41 +++++++++++++++ apps/frontend/src/locales/en-US/index.json | 6 +++ .../src/pages/[type]/[project]/gallery.vue | 36 ++++++++++--- .../[type]/[project]/settings/description.vue | 10 +++- .../[type]/[project]/settings/gallery.vue | 36 ++++++++++--- .../pages/[type]/[project]/settings/index.vue | 16 +++++- .../modal/PhotosensitivityWarningModal.vue | 7 +-- packages/ui/src/locales/en-US/index.json | 6 +-- packages/ui/src/utils/common-messages.ts | 4 ++ pnpm-lock.yaml | 42 +++++++++++++-- 12 files changed, 226 insertions(+), 31 deletions(-) create mode 100644 apps/frontend/src/components/ui/AiImageWarningModal.vue create mode 100644 apps/frontend/src/helpers/c2pa.ts diff --git a/apps/frontend/package.json b/apps/frontend/package.json index 8852cd5123..d143b5699e 100644 --- a/apps/frontend/package.json +++ b/apps/frontend/package.json @@ -38,6 +38,7 @@ "wrangler": "^4.115.0" }, "dependencies": { + "@contentauth/c2pa-web": "^0.13.1", "@formatjs/intl-localematcher": "^0.5.4", "@ltd/j-toml": "^1.38.0", "@modrinth/api-client": "workspace:*", diff --git a/apps/frontend/src/components/ui/AiImageWarningModal.vue b/apps/frontend/src/components/ui/AiImageWarningModal.vue new file mode 100644 index 0000000000..70f0acc92a --- /dev/null +++ b/apps/frontend/src/components/ui/AiImageWarningModal.vue @@ -0,0 +1,52 @@ + + + diff --git a/apps/frontend/src/helpers/c2pa.ts b/apps/frontend/src/helpers/c2pa.ts new file mode 100644 index 0000000000..59c524176a --- /dev/null +++ b/apps/frontend/src/helpers/c2pa.ts @@ -0,0 +1,41 @@ +import type { C2paSdk } from '@contentauth/c2pa-web' +import { createC2pa, isSupportedReaderFormat } from '@contentauth/c2pa-web/inline' + +// https://cv.iptc.org/newscodes/digitalsourcetype/ +// only detecting generative AI types +const AI_DIGITAL_SOURCE_TYPES = [ + 'http://cv.iptc.org/newscodes/digitalsourcetype/trainedAlgorithmicMedia', + 'http://cv.iptc.org/newscodes/digitalsourcetype/trainedAlgorithmicData', + 'http://cv.iptc.org/newscodes/digitalsourcetype/compositeWithTrainedAlgorithmicMedia', + 'http://cv.iptc.org/newscodes/digitalsourcetype/compositeSynthetic', +] + +let c2paInstance: Promise | null = null + +function getC2pa() { + if (!c2paInstance) { + c2paInstance = createC2pa() + } + return c2paInstance +} + +// reference: https://github.com/contentauth/c2pa-js/blob/main/packages/c2pa-web/README.md +export async function fileDeclaresAi(file: File): Promise { + try { + if (!isSupportedReaderFormat(file.type)) { + return false + } + + const c2pa = await getC2pa() + + const reader = await c2pa.reader.fromBlob(file.type, file) + const manifestStore = await reader.manifestStore() + + await reader.free() + + const manifestJson = JSON.stringify(manifestStore) + return AI_DIGITAL_SOURCE_TYPES.some((type) => manifestJson.includes(type)) + } catch { + return false + } +} diff --git a/apps/frontend/src/locales/en-US/index.json b/apps/frontend/src/locales/en-US/index.json index 59ebe60622..65de00e4e8 100644 --- a/apps/frontend/src/locales/en-US/index.json +++ b/apps/frontend/src/locales/en-US/index.json @@ -3485,6 +3485,12 @@ "project.actions.servers-promo.title": { "message": "Create a server" }, + "project.ai-image-warning-modal.body": { + "message": "Using AI-generated images to represent your project is not allowed. Attempting to work around detection may lead to your Modrinth account being suspended." + }, + "project.ai-image-warning-modal.title": { + "message": "AI-generated images not allowed" + }, "project.collections.create-new": { "message": "Create new collection" }, diff --git a/apps/frontend/src/pages/[type]/[project]/gallery.vue b/apps/frontend/src/pages/[type]/[project]/gallery.vue index d6b539e2da..c4e3f0c677 100644 --- a/apps/frontend/src/pages/[type]/[project]/gallery.vue +++ b/apps/frontend/src/pages/[type]/[project]/gallery.vue @@ -1,5 +1,6 @@