Skip to content

Releases: colourbill-ctrl/profiletool

v1.3.2 — iccDEV memory-leak, bounds & XML-parser rebuild

15 Jun 00:50

Choose a tag to compare

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 across IccTagXml ParseXml handlers (#1346 / #1349)
  • Signed→unsigned SeamlessIndicator conversion 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 icStatusCMM names in CMM error messages (#1322 / #1323 / #1324)

v1.3.1 — PAWG gzip false-positive fix

08 Jun 21:53

Choose a tag to compare

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

06 Jun 17:56

Choose a tag to compare

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-Length is 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 to https: or same-origin; cross-origin http: (already blocked by the CSP connect-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, iccToXml and pawgReport now 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 <!DOCTYPE could slip past the byte scan while libxml2 auto-detects the encoding under XML_PARSE_HUGE.

CI / supply chain

  • actions/checkout, actions/setup-node and webfactory/ssh-agent are 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_HOSTS secret over per-run ssh-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_HOSTS repo secret (set it to the verified output of ssh-keyscan <host>); until then CI falls back to TOFU keyscan.

v1.1.5 — Launch by URL

06 Jun 01:29

Choose a tag to compare

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: acsp header check, full ValidateIccProfile, 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 HEADER Header
    Tags TAGS Tags
    Validation VAL Validation
    Profile Assessment WG PAWG ProfileAssessmentWG
    Raw Output RAW RawOutput
    XML XML XML
    JSON JSON JSON

    Aliases 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-src is widened to https:; script-src is unchanged.
  • If the profile URL carries its own &/#, percent-encode the whole url= value.

Manual updated (§6 "Launching with a URL") and translation spreadsheets synced.

v1.1.4 — Profile Assessment WG Report tab with interactive verdict filters

05 Jun 18:42

Choose a tag to compare

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

05 Jun 00:05

Choose a tag to compare

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, a size_t range 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

04 Jun 22:01

Choose a tag to compare

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

04 Jun 18:23

Choose a tag to compare

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.