← Back to Feed CACHED · 2026-06-30 01:53:10 · CACHE_KEY CVE-2025-3155
CVE-2025-3155 · CWE-601 · Disclosed 2025-04-03

A flaw was found in Yelp

ASSESSED — NOISGATE V0.5
Vendor
Reassessed
Verdict:
Do you agree?
01 · The Real Story

A booby-trapped help file that turns the GNOME helper into a quiet file-exfil drone

Yelp is the GNOME desktop's built-in help viewer. It renders Mallard XML .page documents, and the renderer happily honors XInclude directives plus inline SVG with JavaScript. An attacker who can convince a user to open a crafted ghelp:// URL or a .page file gets the helper to pull arbitrary local files (anything the user's UID can read — ~/.ssh/id_rsa, ~/.config, /etc/passwd) into the rendered DOM, then ship them off via embedded JS to an attacker-controlled endpoint. Affected: Yelp ≤ 42.1 and corresponding yelp-xsl ≤ 42.1, shipped by default on Ubuntu 22.04/24.04, Fedora, Debian, RHEL 9, openSUSE, and other GNOME-based distros. Fixed in Yelp 42.3 / yelp-xsl 42.3 (June 12, 2025); distros have backports (RHSA-2025:4505, Fedora FEDORA-2025-e788608959, USN updates).

Vendor labeled this HIGH (7.4) based on CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:N/A:N — confidentiality high, scope changed, user interaction required. The label is *defensible* for a Linux desktop where ssh keys, GPG keyring, and cloud credential files sit in $HOME. But for an enterprise fleet, the population that matters is narrow: only Linux desktops/workstations with GNOME and Yelp installed, where a human clicks a .page payload. Most enterprise Linux is headless server, where Yelp isn't installed or invoked. Net: vendor severity overstates the *fleet* risk for a typical defender; for a developer-heavy Linux-desktop shop it's about right.

"Vendor calls it HIGH; in reality it's a UI-required help-file phish that leaks files on Linux desktops only. Patch on the desktop track."
02 · The Attack Path

5 steps from start to impact.

STEP 01

Craft a malicious Mallard .page help file

Attacker writes a Mallard XML document containing an <xi:include parse="text" href="file:///home/victim/.ssh/id_rsa"/> directive and an inline SVG with a <script> block. The PoC by parrot409 (GitHub gist) is the canonical weaponization. Payload is a single self-contained .page file.
Conditions required:
  • Attacker has authoring capability for the target's help-file delivery vector
Where this breaks in practice:
  • Trivial — public PoC available
Detection/coverage: AV/EDR signatures for Mallard .page with embedded <script> are minimal; YARA rules would have to be hand-written
STEP 02

Deliver via ghelp:// URI or attachment

Attacker hosts the .page file or wraps it in a ghelp:///help: URI delivered via phishing email, IM, or a malicious web page. On GNOME, clicking a ghelp:// link launches Yelp. Alternatively, the file is dropped to disk and a .desktop file or filemanager double-click invokes Yelp.
Conditions required:
  • Target uses a GNOME desktop with default URI handlers
  • Email/IM/browser delivers the link or attachment without stripping
Where this breaks in practice:
  • Most enterprise email gateways do not block .page or ghelp:// because they're obscure — this is friction *for the defender*, not the attacker
  • Modern browsers prompt before handing off custom schemes
Detection/coverage: Proofpoint/Mimecast/Microsoft Defender for O365 do not have default rules for ghelp://; you'll need a custom block
STEP 03

User opens the help file

Victim double-clicks or accepts the URI handoff. Yelp launches and begins parsing the Mallard XML. UI:R is satisfied here — no zero-click path.
Conditions required:
  • User is logged into a GNOME session
  • User opts to open the file
Where this breaks in practice:
  • Requires social engineering — .page is not a file type most users recognize as a help document, which paradoxically makes phishing pretexts harder
Detection/coverage: Process creation telemetry (sysmon-for-Linux, auditd, Falco) will show yelp spawning with a suspicious argv
STEP 04

XInclude reads sensitive local files

Yelp's XSLT pipeline (yelp-xsl) honors the XInclude directive and pulls the target file's contents into the rendered output as text. There is no sandbox — the read happens with the user's UID. Any file readable by that UID is in scope: SSH keys, browser cookie DBs, kube configs, AWS creds, GPG keyrings.
Conditions required:
  • Sensitive files exist in paths readable by the user
  • AppArmor/SELinux confinement for yelp is not enforced (default on most distros)
Where this breaks in practice:
  • Ubuntu's stock AppArmor profile for yelp is *not* enforced
  • On hardened distros (Qubes, Tails) the helper runs in a constrained context
Detection/coverage: auditd EXECVE/PATH watch on ~/.ssh/id_* opened by yelp is a high-fidelity signal
STEP 05

SVG JavaScript exfiltrates over HTTPS

The inline SVG <script> reads the now-included DOM text and POSTs it to an attacker server via fetch() or by setting img.src to a logging endpoint. WebKitGTK (Yelp's renderer) honors outbound network requests by default; there is no CSP applied to local Mallard content.
Conditions required:
  • Outbound HTTPS from the workstation to attacker infra is permitted
Where this breaks in practice:
  • Egress-filtered networks with a default-deny proxy block the POST
  • Zscaler/Netskope SWG with TLS inspection can flag the unusual outbound from WebKitWebProcess
Detection/coverage: SWG/EDR network telemetry tying WebKitWebProcess (child of yelp) to an unknown destination is the cleanest IOC
03 · Intelligence Metadata

The supporting signals.

In-the-wild statusNo confirmed campaigns. Not on CISA KEV. No exploitation telemetry from Mandiant, CrowdStrike, or Red Canary as of June 2026.
Proof-of-conceptPublic PoC by parrot409 at gist.github.com/parrot409; writeup by Michael Catanzaro (GNOME/Red Hat) on the GNOME blog.
EPSS0.10598 (~10.6%) — elevated for a desktop bug but reflects PoC availability, not active exploitation
KEVNot listed as of 2026-06-30
CVSS vectorCVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:N/A:NUI:R is the load-bearing constraint; no integrity/availability impact
Affected versionsYelp ≤ 42.1 and yelp-xsl ≤ 42.1 on GNOME desktops (Ubuntu 22.04/24.04, Fedora 41/42, RHEL 9/10, Debian 12, openSUSE Leap/Tumbleweed)
Fixed versionsYelp 42.3 / yelp-xsl 42.3 (upstream, 2025-06-12). Backports: RHEL 9 via RHSA-2025:4505, Fedora 42 FEDORA-2025-e788608959, Ubuntu USN, Debian DSA
Exposure dataNot externally scannable — Yelp is a desktop binary, not a network service. Shodan/Censys/GreyNoise data is not applicable. Use internal MDM/Intune/JAMF/SCCM/Ansible inventory.
Disclosed2025-04-03 (NVD); originally surfaced 2025-03-18; fix landed 2025-06-12
Reporterparrot409 (research credit); coordinated with GNOME security via Michael Catanzaro
04 · The Call

noisgate verdict.

Final Verdict
DOWNGRADED to MEDIUM (5.4/10)

Downgraded from HIGH to MEDIUM because the *single most decisive factor* is affected-population scope: Yelp ships only on GNOME-based Linux desktops and requires a user to click a .page or ghelp:// payload, so the at-risk fleet for a typical enterprise is the Linux-workstation subset, not servers. The blast radius is single-user file exfiltration with no code execution or lateral movement, which keeps it below the HIGH bucket despite the public PoC.

HIGH technical mechanics and fixed versions
HIGH absence of in-the-wild exploitation
MEDIUM fleet exposure estimate (depends on your Linux-desktop share)

Why this verdict

  • User interaction required (UI:R) — no zero-click vector. The chain dies at the inbox if your secure email gateway flags unknown attachments or your browser blocks custom-scheme handoff.
  • Affected population is narrow — Yelp is a desktop-only package; headless Linux servers (the bulk of most enterprise Linux estates) don't install it. EPSS 0.106 reflects PoC presence, not active campaigns.
  • Blast radius is single-user, single-host — confidentiality only, no integrity or availability impact, no code-execution primitive beyond reading what the user's UID already can. No privilege escalation, no persistence primitive included.
  • Role multiplier: developer/SRE workstation — chain succeeds, blast radius is *significant* (SSH keys, kubeconfigs, ~/.aws/credentials, GPG signing keys → potential pivot to production). For shops where Linux devs hold prod credentials in $HOME, this floats to the top of the MEDIUM bucket.
  • Role multiplier: general office workstation (Linux) — chain succeeds, blast radius is the user's documents and browser cookies. Local nuisance, not a fleet event.
  • Role multiplier: server / headless host — Yelp typically not installed; chain does not run. Zero impact for the dominant Linux deployment role.
  • No KEV listing, no observed campaigns — 14 months post-disclosure with a public PoC and no exploitation telemetry argues against a crash patch cycle.

Why not higher?

HIGH would require either active exploitation (none), a wider attack surface (server-side or zero-click — neither applies), or a credible chain to code execution and lateral movement (this is read-only file exfil within one UID). For Linux-developer-heavy shops where stolen SSH/cloud keys mean prod compromise, treat this as the *top* of MEDIUM and accelerate, but it does not meet the HIGH floor.

Why not lower?

LOW is wrong because the file-read primitive trivially captures secrets-in-home-directory (~/.ssh, ~/.aws, ~/.kube) on developer hosts, and PoC weaponization is public. The role multiplier on a dev workstation is too high to relegate to backlog hygiene.

05 · Compensating Control

What to do — in priority order.

  1. Disable the ghelp:// and help: URI handlers on managed Linux desktops — Remove or override /usr/share/applications/yelp.desktop's MimeType entries that register Yelp as the handler for x-scheme-handler/ghelp and x-scheme-handler/help, and unregister Yelp from application/vnd.gnome.mallard+xml. Ship via Ansible/Puppet/Salt within the MEDIUM mitigation window — there is no formal SLA for MEDIUM, so align with your next desktop config push (target ≤ 30 days for the developer cohort).
  2. Block .page attachments and ghelp:// URIs at the email gateway — Add .page to the disallowed-attachment list in Proofpoint/Mimecast/Defender for O365, and have your SWG (Zscaler/Netskope/Cloudflare Gateway) refuse rewrites of ghelp: schemes. Roll out within the next mail-policy cycle.
  3. Apply the distro backport immediately on developer/SRE workstations — RHEL: dnf update yelp yelp-xsl (RHSA-2025:4505). Ubuntu/Debian: apt-get install --only-upgrade yelp yelp-xsl. Fedora: dnf update --advisory FEDORA-2025-e788608959. Prioritize hosts where users hold cloud or SSH credentials in $HOME.
  4. Enforce AppArmor/SELinux confinement on yelp — Ubuntu ships an unenforced AppArmor profile for yelp; set it to enforce (aa-enforce /etc/apparmor.d/usr.bin.yelp) and extend it to deny reads of ~/.ssh/, ~/.aws/, ~/.kube/, ~/.gnupg/. Reduces blast radius even if patch is missed.
  5. Hunt for retroactive exploitation — auditd query: any yelp process that open()ed files under ~/.ssh, ~/.aws, ~/.kube, or ~/.config/gcloud in the last 90 days. Pair with EDR network telemetry on WebKitWebProcess child of yelp.
What doesn't work
  • Network segmentation — Yelp runs locally on the user's workstation; the exfil is outbound HTTPS from a trusted host, not lateral traffic.
  • Disabling JavaScript browser-wide — Yelp uses WebKitGTK as a library, not the browser; browser settings don't affect it.
  • Removing Yelp entirely — packagers often pull it back in as a dependency of gnome-control-center or gnome-shell. Mark/hold instead, or replace the binary with a stub.
  • MFA on the workstation login — does nothing once the user is logged in and clicks the help file.
06 · Verification

Crowdsourced verification payload.

Run on each Linux desktop/workstation as a non-root user (root not required to read package versions). Invoke as bash check-cve-2025-3155.sh; exits 0=PATCHED, 1=VULNERABLE, 2=UNKNOWN/NOT_INSTALLED. Push via Ansible/Salt and aggregate exit codes.

noisgate-verify.sh
BASHREAD-ONLYSAFE
#!/usr/bin/env bash
# noisgate verification: CVE-2025-3155 (Yelp arbitrary file read)
# Patched in upstream yelp 42.3 / yelp-xsl 42.3 (or distro-backported equivalents).
set -u

VULN=1; PATCHED=0; UNKNOWN=2

# Step 1: is Yelp even installed?
if ! command -v yelp >/dev/null 2>&1; then
  # Could still be installed without being on PATH; check pkg DB
  if ! (dpkg -s yelp >/dev/null 2>&1 || rpm -q yelp >/dev/null 2>&1); then
    echo "NOT_INSTALLED (yelp absent — not vulnerable)"
    exit $PATCHED
  fi
fi

# Step 2: read installed version per package manager
get_ver() {
  local pkg="$1"
  if command -v dpkg-query >/dev/null 2>&1; then
    dpkg-query -W -f='${Version}\n' "$pkg" 2>/dev/null | head -n1
  elif command -v rpm >/dev/null 2>&1; then
    rpm -q --qf '%{VERSION}-%{RELEASE}\n' "$pkg" 2>/dev/null | head -n1
  fi
}

YELP_VER=$(get_ver yelp)
XSL_VER=$(get_ver yelp-xsl)

if [ -z "$YELP_VER" ] && [ -z "$XSL_VER" ]; then
  echo "UNKNOWN (could not determine yelp / yelp-xsl version)"
  exit $UNKNOWN
fi

# Step 3: compare. Upstream fix is 42.3. Distro backports advertise the same
# upstream version OR carry a patched suffix (e.g. RHEL: 42.1-2.el9_5).
# Strategy: if upstream >= 42.3, PATCHED. If upstream < 42.3, check for known
# backport release markers from RHEL/Ubuntu/Fedora advisories.

ver_ge() {
  # returns 0 if $1 >= $2 (semver-ish)
  [ "$(printf '%s\n%s\n' "$2" "$1" | sort -V | head -n1)" = "$2" ]
}

check_one() {
  local name="$1" ver="$2"
  [ -z "$ver" ] && return 0   # not installed, skip
  local base=${ver%%-*}
  if ver_ge "$base" "42.3"; then
    echo "  $name $ver  -> upstream patched"
    return 0
  fi
  # Backport detection: distro advisories
  case "$ver" in
    *el9_5*|*el9_6*|*el10*) echo "  $name $ver  -> RHEL backport (RHSA-2025:4505)"; return 0;;
    *ubuntu*22.04*|*ubuntu*24.04*) 
      # Ubuntu USN-published versions carry +deb/ubuntu suffix; manual sub-check needed.
      echo "  $name $ver  -> AMBIGUOUS Ubuntu version, verify against USN"; return 2;;
    *fc42*|*fc41*) echo "  $name $ver  -> Fedora backport (FEDORA-2025-e788608959)"; return 0;;
  esac
  echo "  $name $ver  -> < 42.3 and no backport marker"
  return 1
}

rc1=0; rc2=0
check_one yelp "$YELP_VER"; rc1=$?
check_one yelp-xsl "$XSL_VER"; rc2=$?

if [ $rc1 -eq 1 ] || [ $rc2 -eq 1 ]; then
  echo "VULNERABLE (CVE-2025-3155): upgrade to yelp/yelp-xsl >= 42.3 or distro backport"
  exit $VULN
fi

if [ $rc1 -eq 2 ] || [ $rc2 -eq 2 ]; then
  echo "UNKNOWN: ambiguous version, cross-check against vendor advisory"
  exit $UNKNOWN
fi

echo "PATCHED (CVE-2025-3155)"
exit $PATCHED
07 · Bottom Line

If you remember one thing.

TL;DR
Monday morning: pull MDM/SCCM/Ansible inventory and identify your Linux desktop fleet — that's your at-risk population (servers without yelp installed are out of scope). For that cohort, push the distro-backported yelp/yelp-xsl package (RHSA-2025:4505, FEDORA-2025-e788608959, USN, DSA) via your normal desktop update channel. Per the noisgate mitigation SLA for MEDIUM: there is no formal mitigation SLA — go straight to the noisgate remediation SLA of ≤ 365 days, but front-load the developer/SRE/SecOps cohort (cloud creds and SSH keys in $HOME) within 30 days because the role-multiplier on those hosts is real and the PoC is public. In parallel, block .page attachments at the email gateway and unregister Yelp from ghelp:///help: URI handlers on managed images. Do not crash-patch the server fleet for this — your time is better spent on the next KEV-listed issue.

Sources

  1. GitHub Advisory GHSA-h7mx-548v-cr9r
  2. Michael Catanzaro (GNOME) write-up
  3. PoC by parrot409
  4. Red Hat RHSA-2025:4505
  5. Fedora 42 yelp-xsl advisory
  6. Seqrite analysis
  7. Wiz vulnerability page
  8. CVE Details
Peer Review

What defenders are saying.

Submit a review attribution: handle + country only
0 flags selected · stored anonymously
Validation Results

Crowdsourced verification outputs.

Results submitted by users who ran the verification payload against their environment.