per2jensen/scrubexif

GitHub: per2jensen/scrubexif

基于 Docker 的 JPEG 照片 EXIF 元数据清理工具,在移除敏感位置和设备信息的同时保留摄影技术参数。

Stars: 1 | Forks: 0

# scrubexif
Tag CI License Docker Pulls Base OS # clones Milestone 🎯 Stats powered by ClonePulse
**GitHub**: [per2jensen/scrubexif](https://github.com/per2jensen/scrubexif) **Docker Hub**: [per2jensen/scrubexif](https://hub.docker.com/r/per2jensen/scrubexif) **高可信度 JPEG 清理。** 移除位置、序列号和私有相机标签,同时保留摄影上下文。使用最优秀的 [Exiftool](https://exiftool.org/) 来处理 JPEG。 **完整文档已移至** → [`DETAILS.md`](https://github.com/per2jensen/scrubexif/blob/main/doc/DETAILS.md) 本 README 为便于 Docker Hub 展示而有意保持简短。 ## 快速开始 ### 最简单的单行命令(默认安全模式,非破坏性) 清理 **当前目录**(`$PWD`)中的所有 JPEG,并将清理后的副本写入 `$PWD/output/`: ``` docker run --rm -v "$PWD:/photos" per2jensen/scrubexif:0.7.14 ``` 若要将清理后的文件写入其他目录(如不存在则会创建): ``` docker run --rm -v "$PWD:/photos" per2jensen/scrubexif:0.7.14 -o /photos/scrubbed ``` 此操作将: - 扫描 **您的当前目录**(`$PWD`)中的 `*.jpg` / `*.jpeg`(包括大写扩展名) - 将清理后的副本写入 **$PWD/output/**(或自定义的 `--output` 目录) - 原始文件在 **$PWD/** 中保持不变 - 若 `$PWD/output` 目录已存在,则拒绝运行 - 默认打印主机路径(使用 `--show-container-paths` 可包含 `/photos/...` 路径) ### 故障处理(重要) scrubexif 的设计原则是 **绝不将未清理的 JPEG 放入输出目录**。 如果因任何原因导致清理失败,**该 JPEG 不会创建输出文件**,程序将继续处理其余文件。 清理失败时的处理方式取决于 `scrubexif` 的运行模式: - **默认安全模式**(单行命令):失败的文件保留在原始目录中,且 **不会为这些失败文件写入任何文件到输出目录**。 - **自动模式**(`--from-input`):失败的文件被移动到 `processed/` 以供检查,且 **不会为这些失败文件写入 `output/`**。 - **手动(破坏性)原地清理**(`--clean-inline`):失败时原始文件保持不变;此模式不涉及输出目录。 ### 加固(破坏性)原地清理(当前目录) 思路相同,但启用了容器加固和原地(破坏性)覆盖: ``` docker run -it --rm \ --read-only --security-opt no-new-privileges \ --tmpfs /tmp \ -v "$PWD:/photos" \ per2jensen/scrubexif:0.7.14 --clean-inline ``` ### 批量工作流(PhotoPrism / 导入风格) 使用自动模式,并显式指定 input/output/processed 目录: ``` mkdir input scrubbed processed errors docker run -it --rm \ --read-only --security-opt no-new-privileges \ --tmpfs /tmp \ -v "$PWD/input:/photos/input" \ -v "$PWD/scrubbed:/photos/output" \ -v "$PWD/processed:/photos/processed" \ -v "$PWD/errors:/photos/errors" \ per2jensen/scrubexif:0.7.14 --from-input ``` 以下是您文件系统上使用的物理目录: 上传 → `$PWD/input/` 已清理 → `$PWD/scrubbed/` 原始文件 → `$PWD/processed/`(或使用 `--delete-original` 删除) 重复文件 → 默认删除;使用 `--on-duplicate move` 将其移动到 `$PWD/errors/` 清理失败(例如损坏的文件)→ 记录为失败;原始文件被移动到 `$PWD/processed/` 以供检查 `errors/` 此名称目前并不准确;它仅在设置 `--on-duplicate move` 时用于存放重复文件。将在后续版本中修复。 ### 数据流概览(自动模式:`--from-input`) 此流程图描述 **仅在自动模式**(`--from-input`)下发生的情况, 该模式使用四个目录(`input/`、`output/`、`processed/`、`errors/`)。 请注意,这些是 **容器内部** 的目录名称。您文件系统上的物理目录是在运行 `docker run ...` 命令时映射的。请参见上方示例中的 `-v ....` 选项。 ``` [input/] --> runs --> [output/] | +--> [processed/] (original JPEGs moved here after successful scrub, unless --delete-original is used) | +--> [errors/] (duplicates only — only used when --on-duplicate move) ``` 含义: - `input/` 新 JPEG 到达此处(例如来自上传,如 PhotoSync)。 - `output/` 带有安全 EXIF 元数据的已清理 JPEG。 - `processed/` 清理后移动到此处的原始 JPEG(或根据请求删除)。 - `errors/` 仅在启用 `--on-duplicate move` 时创建/使用。 ### 本地构建与运行 ``` # 从本仓库中的 Dockerfile 构建镜像 docker build -t scrubexif:local . # 显示 CLI 用法 (ENTRYPOINT 运行 python -m scrubexif.scrub) docker run --rm scrubexif:local --help # 使用 hardened defaults 清理当前目录 docker run -it --rm \ --read-only --security-opt no-new-privileges \ --tmpfs /tmp \ -v "$PWD:/photos" \ scrubexif:local ``` 任何追加到 `docker run … scrubexif:*` 的参数都会传递给底层的 `python3 -m scrubexif.scrub` 入口点。 ## 主要特性 - 基于允许列表的清理:保留少量技术标签(曝光、ISO、焦距、方向、图像尺寸) - 移除 GPS、序列号和其他私有元数据 - 默认保留色彩配置文件(使用 `--paranoia` 移除 ICC 数据) - 自动模式支持重复文件处理(`--on-duplicate delete|move`) - 针对热上传目录的可选稳定性检测(`--stable-seconds`、`--state-file`) - 元数据检查和 dry-run 支持(`--show-tags`、`--preview`、`--dry-run`) - 可选将版权和注释写入 EXIF/XMP(`--copyright`、`--comment`) - 示例中默认启用加固容器配置(只读 + no-new-privileges) ## 供应链透明度 - 版本由公开的 **Release** GitHub Actions workflow(`.github/workflows/release.yml`)生成,该流程构建 Docker 镜像、运行 Syft 生成 SPDX SBOM,并使用 Grype 扫描镜像(遇到高/严重级别 CVE 时失败)。CI(`.github/workflows/CI.yml`)仅运行测试。 - Release 资产包括 SBOM(`sbom-v.spdx.json`)和 Grype SARIF 报告(`grype-results-.sarif`)。SARIF 也会上传到 GitHub Security 标签页并作为 Actions artifact 保留 → 请参阅 **[Releases 标签页](https://github.com/per2jensen/scrubexif/releases)** 查看 release 资产。 - `doc/build-history.json` 跟踪每个 tag 及其 Git commit、镜像摘要以及(可获取时的)Grype 严重级别统计,为下游用户提供可验证的审计追踪。 ## 常用选项 ``` --from-input auto mode --clean-inline in-place scrub (destructive) --show-container-paths include container paths in output -q, --quiet no output on success --preview no write, view only --paranoia maximum scrub, removes ICC --comment stamp comment into EXIF/XMP --copyright stamp copyright into EXIF/XMP --on-duplicate delete | move --stable-seconds N intake stability window --state-file PATH override queue DB -o, --output DIR write scrubbed files to DIR (default safe mode) ``` 完整 CLI 参考 → 见 [`DETAILS.md`](https://github.com/per2jensen/scrubexif/blob/main/doc/DETAILS.md) ## 示例设置 这是我快速将 JPEG 文件上传到 PhotoPrism 的工作流示例。 一个用例是在展览现场快速向狗主人展示照片。 | 主机文件系统路径 | 容器路径 | 用途 | | ------------------------ | -------------------- | ------------------------------------------------ | | `/some/directory/` | `/photos/input/` | 服务器上用于新 JPEG 上传的位置 | | `/photoprism/sooc/` | `/photos/output/` | 清理后的 JPEG 版本的目标位置,用于 PhotoPrism 导入| | `/photoprism/processed/` | `/photos/processed/` | 已导入文件的暂存区。 | ### Systemd `/etc/systemd/system/scrubexif.service`: ``` [Service] ExecStart=/usr/bin/docker run --rm \ --read-only --security-opt no-new-privileges \ --tmpfs /tmp \ -v /some/directory:/photos/input \ -v /photoprism/sooc:/photos/output \ -v /photoprism/processed:/photos/processed \ per2jensen/scrubexif:0.7.14 --from-input --stable-seconds 10 ``` `/etc/systemd/system/scrubexif.timer`: ``` [Unit] Description=Run scrubexif every 5 minutes [Timer] OnBootSec=1min OnUnitActiveSec=5min Persistent=true [Install] WantedBy=timers.target ``` ### Photoprism systemd 脚本 我使用 `scrubexif` 来清理我在犬展上的 JPEG 照片。我使用 rclone 将文件上传到服务器,systemd timer 每 5 分钟运行一次下面的脚本。 您可以在 [Github scrubexif 仓库](https://github.com/per2jensen/scrubexif/blob/main/scripts/run_scrubexif_photoprism.sh) 中查看我的(已匿名化)脚本。 ## 开发 ``` make dev-clean # remove dev image make test # make dev image and run full test suite pytest -m soak # optional 10 min run or try scripts/soak.sh ``` ## 许可证 GPL-3.0-or-later 根据 GNU GENERAL PUBLIC LICENSE v3 授权,详情见提供的 "LICENSE" 文件。 在适用法律允许的范围内,本程序不提供任何担保,即使是针对特定用途的适销性或适用性也不提供担保。 请参阅提供的 "LICENSE" 文件中的第 15 节和第 16 节。 **GitHub**: [per2jensen/scrubexif](https://github.com/per2jensen/scrubexif) **Docker Hub**: [per2jensen/scrubexif](https://hub.docker.com/r/per2jensen/scrubexif) 完整文档 → [`DETAILS.md`](https://github.com/per2jensen/scrubexif/blob/main/doc/DETAILS.md)
标签:Docker, ExifTool, EXIF清洗, JPEG, NIDS, 元数据移除, 图片处理, 地理定位移除, 安全防御评估, 容器化, 开源安全工具, 敏感信息清理, 数据脱敏, 照片发布, 网络安全, 自动化处理, 请求拦截, 逆向工具, 逆向工程平台, 隐私保护