eunjjang3/IFEX

GitHub: eunjjang3/IFEX

IFEX 是一款本地优先的图像取证工具,支持在浏览器和桌面端对图像进行元数据泄露检查、来源验证和像素级篡改分析,全程无需上传文件。

Stars: 0 | Forks: 0

# IFEX ### 本地优先的图像取证,无需上传。 直接在浏览器或桌面应用中检查元数据泄露、文件来源、相机痕迹、JPEG 结构、C2PA 凭据和像素级异常。

CI Latest release MIT License Node.js 22.12 or newer GitHub stars

在线演示 · 快速开始 · 功能 · 隐私 · 桌面版 · 部署

![IFEX 证据优先检查工作区](https://static.pigsec.cn/wp-content/uploads/repos/cas/8e/8e343cf06e5b47ed289e3591dc726f2f9b1eb9f86b2fc70d9896aa331cf69df2.jpg) 由内置的非标识性本地样本生成的真实 IFEX 输出。
## 为什么选择 IFEX? 大多数在线元数据工具都是从上传开始的。而 IFEX 从边界开始:被分析的文件保留在浏览器内存中,解析在独立的 Web Workers 中运行,正常的预览路径使用在本地重新编码的、大小受限的 PNG 图片。 - **设计上的本地优先** —— 被分析的文件和元数据不会上传到 IFEX 服务器。 - **先有证据再做判断** —— 调查结果会解释观察到了什么以及该方法的局限性在哪里。 - **深度的 JPEG 检查** —— 结构、量化、子采样、质量评估和诊断叠加层。 - **具备来源意识** —— 保守地检查 C2PA Content Credentials 和 IPTC Digital Source Type 语义。 - **浏览器和桌面端** —— 在 Web、macOS 或 Windows 上使用相同的沙盒工作区。 - **English · 한국어 · 日本語** —— 即时且持久化的语言切换,并使用本地打包的字体排版。 ## 你可以检查的内容 | 维度 | IFEX 展示的内容 | | --- | --- | | **文件来源** | 二进制签名、扩展名/MIME 一致性、SHA-256 标识、JPEG 结构、处理痕迹以及 C2PA 信号 | | **泄露风险** | 可能暴露身份、设备详情、时间戳、软件、缩略图或位置的元数据字段 | | **相机规格** | 相机和镜头标识、序列号、焦距、固件、传感器信息、裁切系数以及 JPEG 质量评估 | | **GPS 地图** | 嵌入的坐标、选择启用的 OpenStreetMap 图块、选择启用的反向地理编码以及外部地图链接 | | **IPTC 和 XMP** | 结构化的编辑、版权、来源和应用元数据 | | **原始标签** | 可搜索的源级别元数据值和命名空间 | | **Pixel Lab** | 溢出、ELA、残差、梯度、复制-移动候选、CFA 相位、色度平面、JPEG Ghost 以及 8×8 DCT 能量 | ### Pixel Lab ![带有 JPEG Ghost 叠加层的 IFEX Pixel Lab](https://static.pigsec.cn/wp-content/uploads/repos/cas/de/de95886f77758bf4d84d11ac374e090605d6a22abd5956f20279ed943c52b742.jpg) Pixel Lab 直接在本地预览之上渲染诊断图: - 溢出和通道饱和度; - JPEG 错误级别分析 (ELA); - 高频噪声和中值滤波残差; - Sobel 边缘梯度; - 具有邻域位移一致性的复制-移动块匹配; - Bayer CFA 相位残差近似; - 分离的 Cb 和 Cr 色度通道; - 从 Q50 到 Q100 的多遍 JPEG Ghost 扫描; - 解码亮度的 8×8 DCT 能量。 这些只是调查线索,不能作为被篡改的证据。CFA 视图是一种轻量级的相位启发式方法,而不是完整的 Popescu–Farid EM 检测器;DCT 视图基于解码后的像素工作,而不是原始的比特流系数。 ## 快速开始 ### 在线演示 打开 **[托管的 IFEX 工作区](https://eunjjang3.github.io/IFEX/)**,选择一张图片或使用内置的本地样本。图像分析保留在浏览器内存中;GitHub Pages 提供应用程序文件,但不会接收正在被检查的图像。外部地图、地理编码、地图链接和反向搜索行为仍然如[隐私模型](#privacy-model)中所述保持选择性启用状态。 ### 浏览器开发 需要 **Node.js 22.12 或更高版本**。 ``` git clone https://github.com/eunjjang3/IFEX.git cd IFEX npm ci npm run dev ``` 打开 Vite 打印的本地 URL,然后选择一张图片或点击 **使用本地样本** 进行安全的产品体验。 ### Docker ``` git clone https://github.com/eunjjang3/IFEX.git cd IFEX docker compose up --build ``` 打开 。需要时,可以在本地 `.env` 文件中使用 `IFEX_PORT` 覆盖主机端口。 ### 全面验证 ``` npm run verify ``` 验证套件会检查许可证、单元测试、lint、桌面端入口点、TypeScript、生产构建以及构建环境白名单。可以使用以下命令单独检查容器行为和加固响应头: ``` ./scripts/verify-container.sh ``` 该脚本将一个唯一命名的测试容器绑定到 Docker 分配的 `127.0.0.1` 端口,并在完成时删除其容器和镜像。 ## 支持的文件 IFEX 通过有界的签名检查识别 **JPEG、PNG、WebP、AVIF、HEIC/HEIF、TIFF、DNG、Nikon NEF 和 Canon CR2**。默认启用严格模式,拒绝扩展名或 MIME 不匹配、未知签名、空文件以及没有可识别支持格式的通用 `.raw` 文件。 当浏览器无法安全解码嵌入的图像时,RAW 文件可能会在没有预览的情况下生成元数据和结构结果。 ### 浏览器要求 安全分析需要 Web Workers、`OffscreenCanvas.convertToBlob` 和 `createImageBitmap`。当这些 API 不可用时,IFEX 会进入失败关闭状态,除非操作员明确启用 `IFEX_ALLOW_UNSAFE_PREVIEW`。 支持基于功能而非 User-Agent。请在部署所需的每个浏览器中测试生产构建,特别是对于 HEIC/HEIF 和 RAW 预览,因为解码器的可用性因浏览器和操作系统而异。 ## 隐私模型 ``` flowchart LR A[Your image] --> B[Browser memory] B --> C[Disposable workers] C --> D[Local evidence report] B -. explicit user action only .-> E[Map / geocoding / search copy] ``` 打开 IFEX 并分析图像不会将图像或其元数据上传到 IFEX 服务器。UI 字体、相机数据、IPTC 词汇、WASM 和分析代码均与应用程序打包在一起。 只有在匹配的用户操作之后才会发生外部网络访问: - **加载外部地图** 请求 OpenStreetMap 图块。提供商接收浏览器 IP、通过标准 Referer 获得的站点来源,以及接近嵌入位置(而非图像文件)的图块坐标。 - **获取地址** 将确切的嵌入坐标和站点来源发送给 Nominatim。请求全局串行化,两次启动之间至少间隔一秒。 - **地图链接** 打开时将坐标发送给 Google Maps、Apple Maps 或 OpenStreetMap。 - **反向图像搜索** 在本地创建并下载一个无元数据的 JPEG。只有当用户随后将该副本上传到所选服务时,像素才会离开浏览器。 一旦用户选择联系,所选提供商的隐私政策即适用。 ## 桌面应用 IFEX 还可以作为沙盒化的 Electron 应用程序在 macOS 和 Windows 上运行。渲染器没有 Node.js 集成或直接的文件系统权限;其预加载桥接仅公开桌面平台标识符。权限和 webview 被拒绝,只有明确列入白名单的 HTTPS 源才能在系统浏览器中打开。 同时启动 Vite 和 Electron: ``` npm run desktop:dev ``` 为当前主机构建一个解压缩的应用程序包: ``` npm run desktop:package ``` macOS arm64、macOS x64 和 Windows x64 提供了明确的目标: ``` npm run desktop:package:mac:arm64 npm run desktop:package:mac:x64 npm run desktop:package:win:x64 ``` 打包文件位于 `release/` 中。开发包未签名、未公证,且未封装在 DMG/MSI 安装程序中。生产环境的分发应在目标操作系统上构建,并在发布前添加平台签名。 ## 部署 生产环境的 Docker 镜像构建 Vite 应用程序并通过 Nginx 提供静态输出。Docker 和 Coolify 部署在容器启动时读取 `IFEX_*` 值,因此无需重新构建镜像即可更改限制。 将 [`.env.example`](.env.example) 复制到 `.env` 以进行 Docker/Compose 覆盖。静态 Vite 部署可以在构建时使用已记录的 `VITE_IFEX_*` 等效配置;运行时值具有优先权。无效或超出范围的值将回退到加固的默认值。
运行时配置参考 | 运行时变量 | 默认值 | 允许范围 | | --- | ---: | ---: | | `IFEX_STRICT_FILE_TYPES` | `true` | `true` / `false` | | `IFEX_MAX_FILE_MIB` | `25` | 1–512 | | `IFEX_MAX_ACTIVE_FILES` | `4` | 1–50 | | `IFEX_MAX_ACTIVE_MIB` | `64` | 1–2048 | | `IFEX_MAX_IMAGE_MEGAPIXELS` | `40` | 1–200 | | `IFEX_MAX_PREVIEW_DIMENSION` | `2048` | 256–8192 | | `IFEX_STATISTICS_SAMPLE_DIMENSION` | `400` | 64–1024 | | `IFEX_MAX_EMBEDDED_THUMBNAIL_DIMENSION` | `1024` | 128–4096 | | `IFEX_MAX_PIXEL_DIMENSION` | `2048` | 256–4096 | | `IFEX_MAX_SEARCH_COPY_DIMENSION` | `1600` | 256–4096 | | `IFEX_SEARCH_COPY_JPEG_QUALITY_PERCENT` | `90` | 50–100 | | `IFEX_PARSE_CONCURRENCY` | `1` | 1–4 | | `IFEX_PARSE_TIMEOUT_MS` | `15000` | 1000–120000 | | `IFEX_PIXEL_TIMEOUT_MS` | `20000` | 1000–120000 | | `IFEX_MAX_METADATA_TAGS` | `2000` | 100–10000 | | `IFEX_MAX_METADATA_VALUE_CHARS` | `16384` | 256–1048576 | | `IFEX_MAX_METADATA_TOTAL_CHARS` | `1048576` | 65536–16777216 | | `IFEX_ALLOW_UNSAFE_PREVIEW` | `false` | `true` / `false` | 有关本地 Vite 开发,请参阅 [`.env.local.example`](.env.local.example)。Docker 构建上下文会排除 `.env` 和 `.env.*` 文件。
### 自动化发布 推送与 `package.json` 匹配的版本标签会启动发布工作流。例如,包版本 `0.2.0` 需要标签 `v0.2.0`。 ``` npm version patch git push origin main --follow-tags ``` 在验证和容器检查通过后,工作流将: - 打包未签名的 macOS arm64、macOS x64 和 Windows x64 ZIP 文件; - 将多平台 `linux/amd64` 和 `linux/arm64` 镜像发布到 `ghcr.io/eunjjang3/ifex`; - 创建一个包含 SHA-256 校验和和构建来源证明的 GitHub Release。 稳定的容器标签包括确切版本、主/次版本、主版本和 `latest`。 ``` docker pull ghcr.io/eunjjang3/ifex:latest ``` GitHub Container Registry 包在首次创建时可能是私有的。为包的可见性设置一次公开以允许匿名拉取,或者为部署主机添加具备 `read:packages` 权限的身份验证。桌面归档文件仍标记为 `unsigned`;在配置平台签名和 Apple 公证之前,SmartScreen 和 Gatekeeper 可能会发出警告。 ## 分析和安全说明
加固的分析边界 - 文件摄取最多读取 4,100 字节用于签名检测。`file-type` 提供仅限于现有白名单的独立第二意见。 - 如果 JPEG、PNG 和 WebP 的标准头信息可用,则在解码前检查其编码尺寸,并在解码后再次检查。 - 原始文件在独立的工作线程中进行分析。常规预览是在浏览器中重新编码的、大小受限的 PNG。 - JPEG 结构输出上限为 4,096 个分段和 16 个量化表。 - C2PA 集合、元数据计数、元数据文本、并发数、活动字节数和执行时间在越过工作线程边界之前均受到限制。 - 哈希、元数据、C2PA、文件结构和 Pixel Lab 计算仍然使用原始本地文件;显示的预览不是逐字节相同的。 这些控制措施减少了暴露于解析器漏洞和资源耗尽型图像的风险。它们不是防病毒软件的判决结果,也不能证明文件是无害的。
分析参考资料和本地数据集 - 运行时 EXIF 解析使用 `exifr`;代表性测试使用仅用于开发的 `ExifReader` 进行独立检查。 - JPEG 遍历、量化提取、图像结束处理和子采样检测共享一个有界的解析器。 - C2PA Digital Source Type 值是根据官方 IPTC 词汇固定的本地转换进行解释的。 IPTC 定义的生成式 AI 概念才会产生 AI 来源信号。 - 相机传感器和裁切系数解释使用本地打包的派生自 Lensfun 的数据集,并带有明确的归属说明。 数据集刷新是明确的开发行为,需要网络访问: ``` npm run update:lensfun npm run update:iptc-source-types ``` 正常的图像分析仅使用已提交的本地数据集。
## 项目链接 - 发现漏洞?请阅读[安全策略](SECURITY.md)并私下报告。 - 想要帮忙?请从[贡献指南](CONTRIBUTING.md)和[行为准则](CODE_OF_CONDUCT.md)开始。 - 想了解变更?请查看[更新日志](CHANGELOG.md)和[最新发布](https://github.com/eunjjang3/IFEX/releases/latest)。 - 审查依赖项或资产?请参阅[第三方声明](THIRD_PARTY_NOTICES.md)。 ## 许可证 IFEX 源代码在 [MIT 许可证](LICENSE)下提供。第三方依赖项、字体、数据集和资产仍受其各自许可证的约束。 相机裁切系数数据集改编自 Lensfun,遵循 CC BY-SA 3.0 许可证。内置的 IPTC Digital Source Type 词汇是在 CC BY 4.0 许可下的带有归属说明的转换。完整的生产环境依赖许可证文本和仅供开发的声明记录在[第三方声明](THIRD_PARTY_NOTICES.md)中。
**在本地进行检查。谨慎进行解读。负责任地分享证据。**
标签:C2PA, EXIF, WebAssembly, 元数据分析, 图像取证, 桌面应用, 网络安全, 自动化攻击, 请求拦截, 隐私保护