zenvpn
Triggered rules
source_untrusted_domain
One or more source=() URLs point to a host outside the trusted allowlist (github.com, gitlab.com, codeberg.org, pypi.org, …).
-
PKGBUILD:15
source_x86_64=("${pkgname}-x86_64.deb::https://app.zenvpn.net/downloads/linux/amd64/latest/")
llm_review
An AI model (anthropic/claude-4.6-sonnet-20260217) reviewed this and agrees it is MEDIUM (confidence 75%): This PKGBUILD downloads a prebuilt binary .deb from app.zenvpn.net (the official ZenVPN application download endpoint) with sha256sums='SKIP', meaning no integrity verification is performed on the downloaded binary. The binary daemon 'zenvpnd' is extracted and installed to /usr/lib/zenvpn/, and node_modules native binaries are also installed. While app.zenvpn.net appears to be the legitimate vendor's own distribution host (not a personal/unofficial host), the use of 'SKIP' for the checksum means any compromise or substitution of the upstream binary would go undetected. This is a genuine supply-chain concern: a VPN client daemon running with elevated privileges (it uses iproute2, libpcap, systemd units) with no integrity verification. The pattern is common for 'latest' rolling download URLs but still represents a real risk. Not high because there is no evidence of malicious intent or actual substitution, and the host is the vendor's own infrastructure.
PKGBUILD
1 offending line(s) highlighted# Maintainer: Vitalii Kuzhdin <vitaliikuzhdin@gmail.com>
_electron=25
_Name="ZenVPN"
pkgname="${_Name,,}"
pkgver=1.2.26
pkgrel=1
pkgdesc="ZenVPN client"
arch=('x86_64')
url="https://zenvpn.net"
license=('custom:Proprietary')
depends=("electron${_electron}" 'glibc' 'iproute2' 'libpcap' 'sh')
makedepends=('dpkg')
source=("${pkgname}.sh")
source_x86_64=("${pkgname}-x86_64.deb::https://app.zenvpn.net/downloads/linux/amd64/latest/")
noextract=("${source_x86_64[@]%%::*}")
sha256sums=('f38be1d4f732d1dcf1b9705431de6f3eaae0e1616e81bc4f9cf7b566416545ca')
sha256sums_x86_64=('SKIP')
prepare() {
cd "${srcdir}"
sed -e "s/@electronversion@/${_electron}/g" \
-e "s/@appname@/${pkgname}/g" \
-e "s/@runname@/app.asar/g" \
-e "s/@cfgdirname@/${_Name}/g" \
-e "s/@options@/env ELECTRON_OZONE_PLATFORM_HINT=auto/g" \
-i "${pkgname}.sh"
local _pkgver="$(dpkg-deb --show --showformat='${Version}' "${pkgname}-${CARCH}.deb" | tr - _)"
dpkg-deb --extract "${pkgname}-${CARCH}.deb" "${pkgname}-${_pkgver}-${CARCH}"
cd "${pkgname}-${_pkgver}-${CARCH}/usr/lib/${pkgname}"
local target_electron="$(cat version)"
if [[ "${target_electron%%.*}" != "${_electron}" ]]; then
echo " ==> ERROR: Electron version mismatch! Expected: '${_electron}', actual: '${target_electron%%.*}'" >&2
exit 1
fi
patchelf --replace-needed 'libpcap.so.0.8' 'libpcap.so' "zenvpnd"
}
pkgver() {
cd "${srcdir}"
# shellcheck disable=SC2016
dpkg-deb --show --showformat='${Version}' "${pkgname}-${CARCH}.deb" | tr - _
}
package() {
cd "${srcdir}"
install -vDm755 "${pkgname}.sh" "${pkgdir}/usr/bin/${pkgname}"
cd "${srcdir}/${pkgname}-${pkgver}-${CARCH}/usr/lib"
find "systemd" -type f -exec \
install -vDm644 "{}" "${pkgdir}/usr/lib/{}" \;
cd "${pkgname}"
find "resources/app.asar.unpacked/node_modules" -type d \( -name 'darwin-*' -o -name 'win32-*' \) -exec \
rm -rf "{}" +
find . -type f -name '*.bash' -delete
install -vDm755 "zenvpnd" "${pkgdir}/usr/lib/${pkgname}/zenvpnd"
cp -vrL "resources"/* "${pkgdir}/usr/lib/${pkgname}"
# not used?
# cd "${srcdir}/${pkgname}-${pkgver}-${CARCH}/usr/local"
# find "bin" -type f -exec \
# install -vDm755 "{}" "${pkgdir}/usr/{}" \;
cd "${srcdir}/${pkgname}-${pkgver}-${CARCH}/usr/share"
rm -rf "doc" "lintian"
find . -type f -exec \
install -vDm644 "{}" "${pkgdir}/usr/share/{}" \;
cd "${pkgdir}/usr/lib/${pkgname}/assets"
ln -vsf "${_Name}.png" "${pkgname}.png"
}
Scan history
| Scanned at (UTC) | Severity | Rules |
|---|---|---|
| 2026-08-03 00:08:14 | MEDIUM | 2 |
| 2026-08-02 00:16:08 | MEDIUM | 2 |
| 2026-08-01 00:11:18 | MEDIUM | 2 |
| 2026-07-31 00:14:10 | MEDIUM | 2 |
| 2026-07-30 00:17:23 | MEDIUM | 2 |
| 2026-07-29 00:25:53 | MEDIUM | 2 |
| 2026-07-28 00:07:28 | MEDIUM | 2 |
| 2026-07-27 00:24:32 | MEDIUM | 2 |
| 2026-07-26 00:07:32 | MEDIUM | 2 |
| 2026-07-25 00:13:44 | MEDIUM | 2 |
| 2026-07-24 00:02:28 | MEDIUM | 2 |
| 2026-07-23 00:14:47 | MEDIUM | 2 |
| 2026-07-22 00:29:32 | MEDIUM | 2 |
| 2026-07-21 00:24:15 | MEDIUM | 2 |
| 2026-07-20 00:19:49 | MEDIUM | 2 |
| 2026-07-19 00:17:08 | MEDIUM | 2 |
| 2026-07-18 00:14:48 | MEDIUM | 2 |
| 2026-07-17 00:06:16 | MEDIUM | 2 |
| 2026-07-16 00:05:41 | MEDIUM | 2 |
| 2026-07-15 00:09:25 | MEDIUM | 2 |