BLA
BLA (Blind LLM Agents) is the open-source Blue Defense MCP and CLI built to protect software artifacts against automated AI reverse-engineering workflows.
翻译准备中
尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证一个小型、类型化的元数据检查和清理引擎,适用于 Node.js。
AI 翻译
A small, typed metadata inspection and sanitization engine for Node.js
取自仓库 README
正在加载完整 README。 以下为已保存的摘录。
A small, typed metadata inspection and sanitization engine for Node.js.
This project is pre-1.0 and supports WebP and PNG. It is an evidence-led experiment related to ExifCleaner issue #303, not a complete ExifTool replacement. ExifCleaner should retain ExifTool as the fallback for unsupported formats, features, and refused inputs.查看完整 README ↗A small, typed metadata inspection and sanitization engine for Node.js.
This project is pre-1.0 and supports WebP, PNG, JPEG, HEIC and AVIF. It is an evidence-led experiment related to ExifCleaner issue #303, not a complete ExifTool replacement. ExifCleaner should retain ExifTool as the fallback for unsupported formats, features, and refused inputs.
Every format is recognized from the file's leading bytes, never from its extension. The removed
namespaces are getCapabilities()'s removes list for the format. ICC is removed unless
preserveColorProfile asks to keep it.
format | Detected by | Media types | Extensions | Removes | Preserves on request |
|---|---|---|---|---|---|
webp | RIFF + WEBP | image/webp | .webp | EXIF, XMP, ICC | orientation, ICC profile, timestamps; animation payload copied |
png | the 8-byte PNG signature | image/png | .png | EXIF, XMP, ICC, PNG, C2PA | orientation, ICC profile, timestamps, resolution (pHYs) |
jpeg | FF D8 FF | image/jpeg | .jpg, .jpeg | EXIF, XMP, ICC, C2PA, JPEG | orientation, ICC profile, timestamps, resolution |
heic | an ftyp brand set with heic, heix, heim or heis, no avif, no sequence brand | image/heic, image/heif | .heic, .heif | EXIF, XMP, ICC, C2PA | orientation and resolution (minimal Exif item), ICC profile (colr), timestamps |
avif | an ftyp brand set with avif, no HEIC brand, no sequence brand | image/avif | .avif | EXIF, XMP, ICC, C2PA | orientation and resolution (minimal Exif item), ICC profile (colr), timestamps |
For HEIC and AVIF, sanitizing rebuilds the meta box. It removes the Exif and XMP items, the
top-level C2PA uuid box and top-level free/skip boxes, and copies every image item's payload
byte for byte, including thumbnails and auxiliary images such as alpha planes and gain maps.
Image sequences (moov, msf1/avis brands), external data references and layouts the engine
cannot rewrite safely are refused before any write, so the caller can fall back to ExifTool. See
the ISOBMFF spec note for the measured layout rules and decline list.
npm install exifcleaner-node
import {
classifyFallback,
getCapabilities,
inspectFile,
sanitizeFile,
} from "exifcleaner-node";
const capabilities = getCapabilities();
const controller = new AbortController();
const inspection = await inspectFile("input.webp", {
signal: controller.signal,
});
if (!inspection.ok) {
// MetadataError is a discriminated union: switch on inspection.error.code.
console.error(inspection.error);
} else {
console.log(inspection.value.entries, inspection.value.warnings);
}
const sanitized = await sanitizeFile({
sourcePath: "input.webp",
destinationPath: "output.webp",
preserveOrientation: true,
preserveColorProfile: true,
preserveTimestamps: true,
});
if (sanitized.ok) {
console.log(sanitized.value.removedNamespaces);
} else if (classifyFallback(sanitized.error) === "safe-to-fallback") {
// A caller may use one qualified substitute writer here.
console.error("Use the existing ExifTool substitute once.");
} else {
console.error(sanitized.error);
}
The public contracts are:
Inspection: { format: NativeFormat, entries, warnings }InspectOptions: { signal? }SanitizeOptions: { sourcePath, destinationPath, preserveOrientation, preserveColorProfile, preserveTimestamps, signal? }SanitizeResult: { format, destinationPath, removedNamespaces, preserved, warnings, postCommitResidue }Result<T, MetadataError>: a discriminated success/failure unionMetadataError: a discriminated expected-failure unionThe support contract is stated in format-neutral vocabulary rather than in WebP-specific fields, so a future format is additive rather than breaking:
NativeFormat: the format tag carried by Inspection.format and
SanitizeResult.format. It is currently "webp" | "png" | "jpeg" | "heic" | "avif";
read it, do not assume it.Capabilities / FormatCapabilities: what getCapabilities() returns.
formats is a non-empty list of per-format contracts, each stating
detection: "magic" — recognition is by file magic, never by extension.
WebpCapabilities, PngCapabilities, JpegCapabilities, HeicCapabilities
and AvifCapabilities are the FormatCapabilities members today. HEIC and
AVIF also state brands, the bounded ftyp brand set magic admission
recognizes.FallbackDisposition: "safe-to-fallback" | "do-not-fallback", the return of
classifyFallback.PostCommitResidue: the bounded private-stage residue reported on success.Call sanitizeFile once for one semantic request. A returned successful
SanitizeResult is the only completion signal; do not treat a destination
pathname observed during the call as a completed output. On a returned error,
Call classifyFallback once. Its only results are "safe-to-fallback" and
"do-not-fallback": only the former authorizes at most one ExifTool substitute.
For every other disposition, preserve the original terminal result. Do not retry
the native operation, start a fallback loop, or run another writer after any
uncertainty.
Use getCapabilities() as the machine-readable support contract; do not infer support from a filename extension.
APP11 JUMBF/C2PA manifest and a PNG caBX chunk are removed by both
engines, since ExifTool's own -all= has deleted JUMBF since version 12.64.
A top-level C2PA uuid box in HEIC or AVIF is likewise removed by both
(measured with ExifTool 13.59 on c2patool-signed fixtures).EOI — including
a Multi-Picture Format (MPF, CIPA DC-007) container, a real Google Motion
Photo, and a Samsung SEFH/SEFT embedded-picture trailer — exactly as the
ExifTool fallback already does; a measured-unsafe MPF secondary image or
gain-map trailer declines pre-write (mpf-secondary-image) instead of
truncating silently. See format admission criteria
and docs/capabilities.md's "JPEG trailer truncation" section for the full
measured decision table.postCommitResidue. After the output is
committed the library removes its own empty private stage directory: POSIX
performs one non-recursive rmdir of the directory it still holds open,
only while the path still has that directory's identity; Windows disposes
its opened-directory capability. If that removal does not complete, the
result is still a success and postCommitResidue reports
private-empty-stage-directory-remains with the cause. That private path
is never exposed and cannot revoke the committed destination.When preserveColorProfile is requested, a WebP ICCP profile is retained only
when it matches the bounded icc-structural-v0.2 preservation policy. An absent
profile succeeds with preserved.colorProfile: false; an admitted profile is
retained byte-for-byte and verified after reopening the destination. Consumers
can switch on the typed refusal fields code: "unsupported-feature",
feature: "color-profile-preservation", and
reason: "invalid" | "unsupported" | "policy-limit". Do not parse diagnostic
detail text. This is a structural byte-preservation guarantee, not a claim
about color correctness, transform quality, or full ICC semantic conformance.
The engine fails closed on malformed or truncated containers, unknown chunks, trailing data, unsupported formats or WebP features, ambiguous preservation requests, resource-limit violations, aliased source/destination paths, existing or replaced destinations, cancellation, and I/O failures. Orientation preservation accepts only a single TIFF SHORT value from 1 through 8; malformed or unsupported representations return unsupported-feature before a destination is created.
Pre-publication cleanup never relies on pathname identity comparison: an observed stage replacement is retained untouched rather than removed.
getCapabilities() reports the enforced limits: 16 MiB per metadata chunk, 10,000 aggregate RIFF chunks including nested animation chunks, and WebP's 4 GiB-minus-2-byte size ceiling. It also states that compressed codec validation is header-only: the engine preserves VP8/VP8L bytes but is not an image decoder. Animation support means structurally validated ANIM/ANMF containers whose nested image payloads can be preserved byte-for-byte; it is not an unlimited frame-count claim. PNG buffers at most 48 MiB of raw non-IDAT metadata plus at most 48 MiB inflated per parse, and getCapabilities() reports both limits. HEIC and AVIF read at most 16 MiB of meta, 65,536 boxes, a nesting depth of 8 and 32 MiB of buffered item payload per parse, and never buffer mdat in full; getCapabilities() reports all four limits.
HEIC and AVIF report these refuses classes, each returned before any destination is created:
| Refusal | Meaning |
|---|---|
malformed-container | broken box framing, a meta that is not a FullBox, a duplicate meta, an extent outside mdat, or an invalid item graph |
resource-limits | a file over one of the four advertised limits |
image-sequence | a moov box or an msf1/avis sequence brand |
unknown-boxes | a top-level box or meta child outside the closed admitted set |
unknown-item-types | an item type outside the closed admitted set |
unsupported-features | metadata stored in idat, data-reference-indexed or external items, more than one mdat, an unsupported box version, a non-pict handler, or a brand mismatch |
unsafe-item-layout | an extent layout the writer cannot rewrite safely: overlapping or referenced removable items, a surviving item with a zero-width offset field or a zero-length extent, or an offset rewrite that would overflow |
The ISOBMFF spec note maps each internal decline class to one of these.
See the ICC structural policy and complete capability contract for the detailed rule table, fixture provenance for the evidence chain, the native prebuild policy for how prebuilds are built, attested, and verified, the CI scope and minutes budget for how CI decides what to run and what it costs, and the format admission criteria for the tiered evidence every registered format must clear.
Requires Node.js 22 or newer.
npm ci
npm run verify
npm run verify compiles the native publication addon with npm run build:native, so it also
needs a C toolchain: Xcode Command Line Tools on macOS, build-essential on Linux, or Visual Studio
Build Tools with the C++ workload on Windows. Prebuilds are not committed — see the
native prebuild policy for why and how consumers verify them.
Useful focused commands are npm run typecheck, npm test, npm run build,
npm run check:runtime, and npm run check:pack. Protected releases run the
same checks before publishing through npm trusted publishing.
MIT. See LICENSE.