This is less a burglar with a skeleton key and more a pothole that only matters if your traffic is routed over it
CVE-2026-28691 is an uninitialized pointer dereference in ImageMagick's JBIG decoder caused by a missing check. Upstream affected ranges are ImageMagick >=7.0.0-0, <7.1.2-16 and all 6.x <6.9.13-41; the vendor fix landed in 7.1.2-16 and 6.9.13-41, while major Linux distros also shipped backported fixes under their own package versions.
The vendor's 7.5 HIGH rating is technically understandable because a crafted file can crash a reachable service with no auth, but it overstates enterprise urgency. In practice this is a *file parsing DoS*, not a straight network daemon takeover: the attacker still needs a real path that feeds malicious JBIG content into ImageMagick, and the observed impact is availability-only with no confirmed in-the-wild exploitation, no KEV listing, and extremely low EPSS.
4 steps from start to impact.
Find an image ingestion path
curl or Burp to hit avatar uploaders, document converters, CMS thumbnailers, or internal media pipelines that call magick/convert.- A reachable application or batch workflow uses ImageMagick
- That workflow accepts attacker-controlled image content
- JBIG support is enabled in the installed build
- Many enterprises do not expose raw ImageMagick directly; it sits behind another app
- Not every upload stack accepts JBIG or preserves the file to the decoder
- Some deployments disable uncommon coders in
policy.xmlor strip formats at the edge
Deliver a malformed JBIG sample
- Attacker can upload, submit, or otherwise cause processing of a JBIG file
- The application does not normalize away the malicious structure before ImageMagick sees it
- No public, mature exploit kit was found in the reviewed sources
- JBIG is a niche format compared with JPEG/PNG, so many apps never encounter it
- Content validation, re-encoding, or alternate libraries may break the trigger path
Reach the vulnerable decoder
magick/convert invocation, as documented by the vendor advisory and distro trackers.- Installed version is vulnerable or not backported
- The process reaches the JBIG decoder code path
- Containerized workers may restart quickly and hide impact
- Many modern pipelines isolate converters in short-lived pods, jails, or worker queues
- Distro backports mean an apparently old package may already contain the fix
Cause service degradation or crash loops
- The vulnerable process is in a critical request path or shared worker pool
- Supervisors keep restarting the crashing process or queue retries pile up
- Impact is availability-only in the published scoring
- Well-designed retry controls, worker isolation, and autoscaling limit damage
- This does not by itself provide persistence, credential access, or lateral movement
The supporting signals.
| In-the-wild status | No current evidence of exploitation in the sources reviewed. CISA ADP marks Exploitation: none, Automatable: no, Technical Impact: partial in the CVE record surfaced by OpenCVE. |
|---|---|
| KEV status | Not listed in CISA KEV as of the reviewed catalog; no KEV date or due date applies. |
| PoC availability | No widely referenced public PoC located for CVE-2026-28691 in the reviewed sources. That raises attacker effort versus commodity web bugs, though a malformed-file reproducer is very plausible for a determined researcher. |
| EPSS | 0.00063 from your intel block — effectively floor-level exploit probability. Secondary databases reviewed place it in a low percentile band rather than a breakout risk. |
| CVSS vector meaning | CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H means the CNA modeled this as remote, unauthenticated, availability-only. The weak spot in that model is that it treats *content delivery into a decoder* like direct network reachability, which inflates real-world urgency for many enterprises. |
| Affected versions | Upstream affected versions are all 6.x < 6.9.13-41 and 7.0.0-0 through 7.1.2-15. |
| Fixed versions | Upstream fixes are 6.9.13-41 and 7.1.2-16. Debian lists backported fixes at 8:6.9.11.60+dfsg-1.3+deb11u11 (bullseye), 8:6.9.11.60+dfsg-1.6+deb12u8 (bookworm), and 8:7.1.1.43+dfsg1-1+deb13u7 (trixie); Oracle Linux 7 ELS fixed it in 6.9.10.68-7.0.9.el7_9. |
| Exposure/scanning reality | Internet exposure is indirect. This is usually a library inside apps, workers, or containers, so Shodan-style sweeping is not the right mental model. The meaningful exposure question is: *which upload/rendering services feed untrusted images into ImageMagick with JBIG enabled?* |
| Disclosure timeline | GitHub advisory published 2026-03-09; NVD published 2026-03-10 and updated 2026-03-11. |
| Reporter / source | Reported in the GitHub advisory by zerojackyi; CNA source is GitHub, Inc. |
noisgate verdict.
The decisive downward pressure is that this is not a direct edge-service bug; it requires a reachable workflow that ingests attacker-controlled JBIG content and hands it to ImageMagick. That prerequisite sharply narrows the exposed population compared with a true unauthenticated network service flaw, and the published impact is availability-only.
Why this verdict
- Downgrade from vendor 7.5: the CNA scored
AV:N/UI:N, but in practice the attacker usually needs a pre-existing upload, render, or conversion path that routes untrusted content into ImageMagick. That is a *reachability dependency*, not universal network exposure. - Availability-only impact: the published vector is
C:N/I:N/A:H. Crashing an image worker matters, but it does not carry the same enterprise blast radius as auth bypass, RCE, or credential exposure. - Very weak threat telemetry: no KEV listing, no verified in-the-wild exploitation in the reviewed sources, and EPSS
0.00063all push this down. The market is not signaling urgent attacker demand. - Niche trigger surface: JBIG is not a common consumer upload format in many estates. Requiring both ImageMagick *and* the JBIG decoder path *and* attacker-controlled content compounds friction.
- Modern controls trim impact: file-type restrictions, disabled coders, worker isolation, crash-only container jobs, and queue boundaries often stop this from becoming a broad enterprise event even when a vulnerable version exists.
Why not higher?
It is not higher because the attack chain is conditional: internal library presence alone is not enough. You need a real ingestion path for malicious JBIG content, and the observed consequence is denial of service rather than code execution or data theft. Absent exploit activity or a public turnkey PoC, this does not deserve the same urgency bucket as remotely exploitable foothold bugs.
Why not lower?
It is not lower because ImageMagick is common in web stacks, CI pipelines, and content-processing services, and malformed-file bugs *do* get triggered in production. If you run shared thumbnailing or document-rendering infrastructure exposed to untrusted uploads, repeated crashes can create a real customer-facing availability incident even without deeper compromise.
What to do — in priority order.
- Disable JBIG if you do not need it — Block the decoder in ImageMagick
policy.xmlor remove the delegate/build support where practical. This is the cleanest exposure reduction because it removes the trigger path entirely; for a MEDIUM noisgate verdict there is no mitigation SLA, so deploy during the next normal change window and complete permanent remediation within the 365-day remediation window. - Isolate conversion workers — Run ImageMagick in dedicated containers, sandboxes, or tightly scoped worker pools with memory/CPU limits and restart controls. That contains crash impact to one worker rather than your whole app tier; again, no mitigation SLA — go straight to the 365-day remediation window if you choose to rely on architecture controls before patching.
- Restrict accepted formats at the edge — Reject or transcode rare formats like JBIG at upload gateways, API validators, or message brokers before they reach the converter. This meaningfully cuts reachable population and is often easier than emergency package work in large estates; implement in normal operations and still patch within 365 days.
- Prioritize untrusted-content pipelines for patching — Inventory hosts and containers where external users, email attachments, or automated fetchers can feed content into ImageMagick. Patch those first because they are the only places this CVE is likely to matter in practice; for MEDIUM, there is no mitigation SLA, but the vendor fix should still land within the 365-day remediation window.
- MFA does nothing here because the issue is in content parsing, not authentication.
- WAF signatures alone are weak coverage because the dangerous bytes are inside an uploaded image and the crash happens in backend decoding.
- Generic antivirus scanning is not a dependable control for malformed parser inputs; many crafted crash files are not malware samples and will not match signatures.
- Version-only dashboards without distro context can create false positives because Debian/Oracle/SUSE backports may be fixed while still reporting older-looking package baselines.
Crowdsourced verification payload.
Run this on the target Linux host or container image that has ImageMagick installed. Invoke it as bash check-cve-2026-28691.sh; no root is required, though package-manager metadata access improves accuracy. The script checks upstream magick/convert versions first, then Debian package backports, then RPM changelog/package evidence, and prints VULNERABLE, PATCHED, or UNKNOWN.
#!/usr/bin/env bash
# check-cve-2026-28691.sh
# Detect likely exposure to CVE-2026-28691 in ImageMagick.
# Exit codes: 0=PATCHED, 1=VULNERABLE, 2=UNKNOWN
set -u
CVE="CVE-2026-28691"
UPSTREAM_FIXED_7="7.1.2-16"
UPSTREAM_FIXED_6="6.9.13-41"
# Debian backport fixed versions from Debian security tracker
DEB_FIXED_BULLSEYE="8:6.9.11.60+dfsg-1.3+deb11u11"
DEB_FIXED_BOOKWORM="8:6.9.11.60+dfsg-1.6+deb12u8"
DEB_FIXED_TRIXIE="8:7.1.1.43+dfsg1-1+deb13u7"
DEB_FIXED_UNSTABLE="8:7.1.2.16+dfsg1-1"
# Oracle Linux 7 ELS fixed package seen in vendor errata
OL7_FIXED="6.9.10.68-7.0.9.el7_9"
say() { printf '%s\n' "$*"; }
have_cmd() { command -v "$1" >/dev/null 2>&1; }
ver_ge() {
# generic version compare using sort -V
[ "$(printf '%s\n%s\n' "$2" "$1" | sort -V | head -n1)" = "$2" ]
}
check_upstream_binary() {
local bin ver major
for bin in magick convert; do
if have_cmd "$bin"; then
ver=$("$bin" -version 2>/dev/null | awk '/^Version: ImageMagick /{print $3; exit}')
if [ -n "${ver:-}" ]; then
say "Found ImageMagick binary: $bin version $ver"
major=${ver%%.*}
if [ "$major" = "7" ]; then
if ver_ge "$ver" "$UPSTREAM_FIXED_7"; then
say "PATCHED: upstream 7.x version is >= $UPSTREAM_FIXED_7"
exit 0
else
say "VULNERABLE: upstream 7.x version is < $UPSTREAM_FIXED_7"
exit 1
fi
elif [ "$major" = "6" ]; then
if ver_ge "$ver" "$UPSTREAM_FIXED_6"; then
say "PATCHED: upstream 6.x version is >= $UPSTREAM_FIXED_6"
exit 0
else
# Old distro packages may be backported; do not hard-fail yet if package manager exists
if ! have_cmd dpkg-query && ! have_cmd rpm; then
say "VULNERABLE: upstream 6.x version is < $UPSTREAM_FIXED_6 and no package metadata is available"
exit 1
fi
say "Upstream 6.x version appears old; checking distro package metadata for backports..."
fi
fi
fi
fi
done
}
check_dpkg() {
local pkg ver codename
if ! have_cmd dpkg-query; then
return 1
fi
pkg=""
for p in imagemagick imagemagick-6.q16 imagemagick-6-common imagemagick-7-common; do
if dpkg-query -W -f='${Status}\n' "$p" 2>/dev/null | grep -q 'install ok installed'; then
pkg="$p"
break
fi
done
[ -n "$pkg" ] || return 1
ver=$(dpkg-query -W -f='${Version}\n' "$pkg" 2>/dev/null)
codename=$( . /etc/os-release 2>/dev/null; printf '%s' "${VERSION_CODENAME:-}" )
say "Found Debian package: $pkg version $ver${codename:+ ($codename)}"
if have_cmd dpkg --compare-versions; then
case "$codename" in
bullseye)
if dpkg --compare-versions "$ver" ge "$DEB_FIXED_BULLSEYE"; then
say "PATCHED: Debian bullseye package is >= $DEB_FIXED_BULLSEYE"
exit 0
else
say "VULNERABLE: Debian bullseye package is < $DEB_FIXED_BULLSEYE"
exit 1
fi
;;
bookworm)
if dpkg --compare-versions "$ver" ge "$DEB_FIXED_BOOKWORM"; then
say "PATCHED: Debian bookworm package is >= $DEB_FIXED_BOOKWORM"
exit 0
else
say "VULNERABLE: Debian bookworm package is < $DEB_FIXED_BOOKWORM"
exit 1
fi
;;
trixie)
if dpkg --compare-versions "$ver" ge "$DEB_FIXED_TRIXIE"; then
say "PATCHED: Debian trixie package is >= $DEB_FIXED_TRIXIE"
exit 0
else
say "VULNERABLE: Debian trixie package is < $DEB_FIXED_TRIXIE"
exit 1
fi
;;
sid|forky|unstable)
if dpkg --compare-versions "$ver" ge "$DEB_FIXED_UNSTABLE"; then
say "PATCHED: Debian unstable/forky package is >= $DEB_FIXED_UNSTABLE"
exit 0
else
say "VULNERABLE: Debian unstable/forky package is < $DEB_FIXED_UNSTABLE"
exit 1
fi
;;
*)
# Unknown Debian-family release; use changelog if available, otherwise unknown
if zgrep -R "$CVE" /usr/share/doc/imagemagick*/changelog* 2>/dev/null | grep -q "$CVE"; then
say "PATCHED: local Debian changelog references $CVE"
exit 0
fi
say "UNKNOWN: Debian-family package found, but release-specific backport baseline is not coded here"
exit 2
;;
esac
fi
return 1
}
check_rpm() {
local pkg nvr osid osver
if ! have_cmd rpm; then
return 1
fi
pkg=""
for p in ImageMagick ImageMagick7 imagemagick; do
if rpm -q "$p" >/dev/null 2>&1; then
pkg="$p"
break
fi
done
[ -n "$pkg" ] || return 1
nvr=$(rpm -q --qf '%{VERSION}-%{RELEASE}\n' "$pkg" 2>/dev/null)
osid=$( . /etc/os-release 2>/dev/null; printf '%s' "${ID:-}" )
osver=$( . /etc/os-release 2>/dev/null; printf '%s' "${VERSION_ID:-}" )
say "Found RPM package: $pkg $nvr${osid:+ on $osid $osver}"
if rpm -q --changelog "$pkg" 2>/dev/null | grep -q "$CVE"; then
say "PATCHED: RPM changelog explicitly references $CVE"
exit 0
fi
if [ "$osid" = "ol" ] && [ "$osver" = "7" ]; then
if ver_ge "$nvr" "$OL7_FIXED"; then
say "PATCHED: Oracle Linux 7 package is >= $OL7_FIXED"
exit 0
else
say "VULNERABLE: Oracle Linux 7 package is < $OL7_FIXED"
exit 1
fi
fi
# For other RPM distros, err on the side of unknown unless upstream binary clearly says fixed.
say "UNKNOWN: RPM package present, but no explicit local evidence of the backport for $CVE was found"
exit 2
}
main() {
check_upstream_binary
check_dpkg
check_rpm
say "UNKNOWN: could not determine whether ImageMagick is installed and fixed for $CVE"
exit 2
}
main "$@"
If you remember one thing.
Sources
What defenders are saying.
Crowdsourced verification outputs.
Results submitted by users who ran the verification payload against their environment.