jsColorEngine is a colour management library: it parses ICC profiles and transforms pixel data. It runs in Node and in the browser, in-process, on data the host application hands it.
The repository also contains benchmark harnesses (bench/), a comparison
testbed (testbed/), and samples (samples/). None of these are published to
npm — the package is src/ only, 64 files — but they are not all the same
kind of thing, and reports are treated differently for each. See below.
Parsing an ICC profile you did not create. src/decodeICC.js and
src/Profile.js read a binary format with self-describing tag tables, offsets
and lengths. A profile is data from wherever the host got it: an uploaded
image, a downloaded asset, a document. That is the boundary worth defending,
and reports there are genuinely welcome:
- out-of-bounds reads from malformed tag offsets or lengths
- unbounded allocation driven by header-declared sizes
- infinite loops or pathological runtimes on crafted input
- prototype pollution through parsed profile metadata
- anything that turns a malformed profile into a crash, a hang, or memory disclosure in the host process
Transform code reachable from a parsed profile counts too — a crafted CLUT or curve that drives an out-of-range index, for instance.
samples/ is different from the rest of the tooling. It exists for other
developers to run, read and copy into their own projects — the LUT builder, the
TIFF CLI, the ICCImage wrapper. Code that people paste into their own
applications is worth getting right, so issues against samples are welcome.
They are triaged as low severity, because nothing there runs as part of the
engine: a sample is not reachable from require('jscolorengine'), is not in
the published package, and only executes when a developer deliberately runs it
on their own machine. Fixes land in ordinary maintenance rather than urgently.
If a sample demonstrates a pattern that would be unsafe when copied — building a path from unvalidated input, say, or a parser that trusts its input shape — that is worth reporting even though the sample itself is harmless where it sits. That is the case where a sample bug can become somebody else's real bug.
bench/ and testbed/ are not a security boundary. They are programs a
developer compiles and invokes with arguments they type, against corpora they
generate on their own machine. Reports that assume an attacker controls a
benchmark's command line, its pixel counts, or its input files describe a
situation where the attacker is already running code as the developer, and will
be closed.
Concretely, and to save anyone the trouble of re-reporting:
- unchecked arithmetic before allocation in
bench/lcms_c/*.c, where the sizes come from a--sizesflag the developer types strtokrather thanstrtok_rin single-threaded argument parsing- CVEs in transitive devDependencies or in the private, unpublished
proof-of-concept packages under
bench/
Dependency advisories against build and benchmark tooling are not a
priority and will not be treated as urgent. The published package is src/
only; a CVE in a package that exists solely to compile a bundle, run the test
suite, or drive a local benchmark cannot reach anyone who installs
jsColorEngine. Such advisories get picked up during ordinary maintenance,
alongside whatever else is being done — not on the clock a security report
would otherwise imply. Advisories affecting a runtime dependency, or anything
reachable from the published files, are a different matter and are treated as
in scope.
Please also note that changes to benchmark code are held to an unusual
standard: these harnesses produce the published throughput figures, so a change
that alters timing — pre-faulting buffers by swapping malloc for calloc
inside a measurement loop, for example — is a correctness regression in this
repository even when it would be harmless anywhere else. See
bench/baseline/README.md.
Scanner-generated pull requests are welcome if the finding is in scope, but please:
- state the threat model in your own words, not just a CWE number and a severity label — "an attacker who can supply an ICC profile can …" is a report we can act on; "likely exploitable" against a local benchmark is not
- open an issue before a pull request for anything touching
bench/ - do not bundle unrelated refactors with a fix
Severity assigned by a scanner is treated as a starting point, not a conclusion. A finding is assessed on whether the described attacker can actually reach the described code.
Open a security advisory for anything in the "real attack surface" section above, or an ordinary issue if you are unsure whether it qualifies. There is no bounty programme.
Please include the profile or input that triggers it where you can — a malformed profile is small, and it is the difference between a report we can reproduce in a minute and one we cannot.
The latest published release. This is a small project; fixes land on main and
ship in the next release rather than being backported.