Releases: colourbill-ctrl/profiletool
v1.3.2 — iccDEV memory-leak, bounds & XML-parser rebuild
Maintenance release — rebuilds all five WASM modules against a clean iccDEV master, picking up the upstream memory-leak, bounds-checking and XML-parser fixes merged since the previous core-WASM build. No frontend or behaviour change — the validator produces the same output on a hardened IccProfLib/IccXML underneath.
IccXML (XML ↔ ICC converter):
- Signed
atoi()→ unsigned wrap acrossIccTagXmlParseXml handlers (#1346 / #1349) - Signed→unsigned
SeamlessIndicatorconversion in image ParseXml (#1342 / #1343 / #1344) - Leak on duplicate tag signatures in XML tag parsing (#1306 / #1307)
IccProfLib (validate / dump / PAWG report):
- CIccXform::Create overload leak / double-free via
bOwnsProfile(#1308 / #1347) - CIccCmm::CheckPCSConnections CIccPcsXform leak on Connect failure (#1337 / #1338)
- Spectral-profile transform-creation fixes (#1335)
- CIccCmmSearch::AddXform NamedColor profile leak (#1332 / #1333)
- AddXform ownership / delete-on-error contract (#1327)
- Tag size/offset overflow & bounds checks (#1296–#1300)
- Decode
icStatusCMMnames in CMM error messages (#1322 / #1323 / #1324)
v1.3.1 — PAWG gzip false-positive fix
Fixes
- PAWG report: eliminate gzip/short-magic false positives. Rebuilt the iccpawg WASM against the updated iccDEV PAWG detector. Short magic-byte signatures (gzip `1F 8B 08`, ELF, shebang) are now corroborated with surrounding printable context before being flagged, so legitimate profiles (e.g. Fogra51_CF.icc) no longer trip a spurious S8 malware finding.
Security hardening (carried from prior work)
- Hardened the `#url=` launch path and analytics: `page_location` is stripped of query/fragment so a `#url=` target is never shipped to GA, and cross-origin `#url=` fetches stay behind the `url_confirm` gate.
- Removed `innerHTML` sinks for i18n dictionary strings — placeholder/help markup now renders via inert React nodes (`lib/richText.jsx`).
CI
- Bumped deploy GitHub Actions (checkout, setup-node, ssh-agent) to their latest SHA-pinned, Node 24-compatible releases ahead of the June 16 Node 20 cutover.
v1.1.6 — Security hardening
Follow-up hardening from the 1.1.5 security review. No user-facing feature changes.
URL-launch (#url=)
- Streamed, capped download. The response is now read through a running 256 MB cap that aborts the download mid-stream, and an over-cap
Content-Lengthis rejected up front — a crafted launch link can no longer OOM the tab by buffering a multi-GB body before the loader's size check. - Scheme tightened.
url=is restricted tohttps:or same-origin; cross-originhttp:(already blocked by the CSPconnect-src) is now rejected early with a clear message.
WASM validator boundary
- Every WASM entry point is now independently size-capped (
kMaxIccBytes= 256 MB, mirroring the JS loader). Previously only the text→ICC conversions enforced their own cap;validateProfile,describeTag,iccToJson,iccToXmlandpawgReportnow do too, so none trusts the JS caller to have bounded the input. - The XML entity-bomb guard additionally rejects non-UTF-8 input (any NUL byte), closing a theoretical path where a wide-char
<!DOCTYPEcould slip past the byte scan while libxml2 auto-detects the encoding underXML_PARSE_HUGE.
CI / supply chain
actions/checkout,actions/setup-nodeandwebfactory/ssh-agentare pinned to commit SHAs (the deploy job holds the SSH key; mutable tags are a supply-chain risk).- The host-key step prefers a pinned
SSH_KNOWN_HOSTSsecret over per-runssh-keyscan(trust-on-first-use), with a keyscan fallback so deploys keep working until the secret is added.
Review also confirmed: no XSS (profile-derived strings render as escaped JSX/textContent), npm audit clean, pdfjs patched, and xlsx only ever writes (never parses untrusted input). WASM rebuilt; the validator test corpus passes unchanged.
Manual follow-up to fully close L5: add an
SSH_KNOWN_HOSTSrepo secret (set it to the verified output ofssh-keyscan <host>); until then CI falls back to TOFU keyscan.
v1.1.5 — Launch by URL
URL-fragment launch
profiletool can now be opened by a link that names the profile to load and the tab to land on, using a URL fragment:
https://chardata.colourbill.com/profiletool#url=<profile-url>&tab=<tab>
Both parts are optional.
-
url=— the ICC profile is fetched in your browser and run through the same path as a local file:acspheader check, fullValidateIccProfile, the 256 MB size cap, and the best-effort fallback for unparseable profiles. The fetched bytes only feed the validator and are never re-sent. -
tab=— which view to open. Two interchangeable, case-insensitive schemes:View Short Long Header HEADERHeaderTags TAGSTagsValidation VALValidationProfile Assessment WG PAWGProfileAssessmentWGRaw Output RAWRawOutputXML XMLXMLJSON JSONJSONAliases stay stable even if the on-screen labels are renamed, so links keep working. An unrecognised
tab=is ignored and Header opens.
Example: …/profiletool#url=https://example.org/sRGB.icc&tab=PAWG
Notes
- Using a fragment (not a query string) keeps the profile URL on the client — it is never sent to a web server.
- The profile must be served over HTTPS from a host that permits cross-origin reads (CORS). To enable this, the CSP
connect-srcis widened tohttps:;script-srcis unchanged. - If the profile URL carries its own
&/#, percent-encode the wholeurl=value.
Manual updated (§6 "Launching with a URL") and translation spreadsheets synced.
v1.1.4 — Profile Assessment WG Report tab with interactive verdict filters
Profile Assessment WG Report tab
Adds a Profile Assessment WG Report tab that runs the ICC Profile Assessment Working Group checklist against the loaded profile, backed by the iccPawgReport tool from iccDEV and shipped as a lazy-loaded WASM module (fetched only when the tab is opened).
Interactive verdict filters
The summary pills — Pass / Warn / Fail / Gap / N/A / Not Run — are interactive:
- Click a pill to toggle visibility of that verdict category in the report below.
- A blue halo marks the categories currently shown; filtered-out pills dim.
- Categories with zero items stay inert (not clickable).
Validation, header/tag inspection, and XML/JSON round-trip editing are unchanged. Everything still runs client-side — profile bytes never leave the browser.
v1.1.2 — Synced to merged iccDEV + localized status line
What's changed
- Synced the bundled IccProfLib (iccDEV) to merged upstream. The expanded validation from v1.1.1 was merged upstream; this rebuilds the WASM against merged
master, picking up the post-review refinements (tag-layout frontier tracking, bounded padding scan, asize_trange guard) and slightly cleaner messages. No change to which conditions are flagged or their severity. - Localized the validation status line. The status headline ("Profile is valid", "Profile has warning(s)", "Profile is non-compliant", "Critical validation error", and the best-effort "Critical — shown for inspection only") now follows the selected UI language across all 12 locales.
Note: individual validation message bodies are produced by IccProfLib at runtime and remain in their source form (English), as documented; the UI chrome and status line around them are localized.
v1.1.1 — Best-effort inspection + expanded validation
What's new
-
Best-effort inspection for unparseable profiles. When a profile fails strict validation (e.g. a tag whose data runs past the end of the file — a classic malformed/payload shape), profiletool no longer dead-ends on "Failed to parse." It now shows a read-only inspection view of the header and tag directory, clearly flagged as a critical, do-not-apply profile, with the specific structural reason (e.g. "Tag 'bXYZ' data extends 1 byte beyond the end of the file").
-
Expanded validation. The validator now flags more malformed-profile conditions:
- malformed tag-table layout — non-minimal/non-zero padding between tags, overlapping tag data, and trailing data after the last tag;
- degenerate gamma tone-response curves (gamma of 0 or ~256);
- ICC v2-era tag types in a profile declaring v4 or later (a likely-incorrect version number).
- A non-D50 PCS illuminant is now reported as a warning rather than an error, matching ICC guidance.
The expanded validation comes from changes to the bundled IccProfLib (iccDEV); those changes are under upstream review (InternationalColorConsortium/iccDEV#1216) and are security-reviewed.
v1.1.0 — Click-to-inspect validation
What's new
- Click-to-inspect validation. Validation-tab findings are now actionable. Click a finding to open a dialog that pinpoints the offending header field or tag in context and highlights the exact problem — e.g. which header field violates a Colour-Encoding-Class zero requirement, the actual-vs-expected D50 illuminant, an unregistered CMM, plus ~25 other header checks and tag-level findings. Messages are de-noised (no more raw
NonCompliant! - -prefixes) and carry severity chips. Hardened with an error boundary so a bad interpretation can't blank the tab, with full 12-locale i18n. - Anonymous usage analytics (GA4, shared CharData property).
Note: in-app structured editing of the Header and Tags tabs is still in development and is not part of this release.