rubrika

maintainer vencejo · 0 votes · scanned 2026-08-03 00:08:14.047287
MEDIUM
View on AUR ↗
Why flagged The wrapper script installed at /usr/bin/rubrika contains a runtime `pip install pyhanko --target=...` call that fetches and executes code from PyPI at first run. While pyhanko is listed as a proper AUR dependency ('python-pyhanko'), the wrapper bypasses that dependency entirely and falls back to pip if the import fails. This means: (1) the pip install is not integrity-checked (no hash pinning), (2) it installs into a user-writable directory (~/.local/share/rubrika/vendor) which is prepended to PYTHONPATH, allowing a compromised or typosquatted PyPI package to execute arbitrary code, and (3) the version installed by pip may differ from what the AUR package declares. The redundancy with the declared AUR dependency is confusing and the fallback path is the real concern — it is a genuine supply-chain risk (unverified code execution from an external package index at runtime), not merely sloppy packaging. This matches the MEDIUM classification.

Triggered rules

MEDIUM pip install of an external package pip_install_external

`pip install <package>` fetches an unpinned package from PyPI at build time, outside source=() and makepkg's checksums.

  • PKGBUILD:59 pip install pyhanko --target="${VENDOR_DIR}" --quiet
MEDIUM AI review llm_review

An AI model (anthropic/claude-4.6-sonnet-20260217) reviewed this and agrees it is MEDIUM (confidence 82%): The wrapper script installed at /usr/bin/rubrika contains a runtime `pip install pyhanko --target=...` call that fetches and executes code from PyPI at first run. While pyhanko is listed as a proper AUR dependency ('python-pyhanko'), the wrapper bypasses that dependency entirely and falls back to pip if the import fails. This means: (1) the pip install is not integrity-checked (no hash pinning), (2) it installs into a user-writable directory (~/.local/share/rubrika/vendor) which is prepended to PYTHONPATH, allowing a compromised or typosquatted PyPI package to execute arbitrary code, and (3) the version installed by pip may differ from what the AUR package declares. The redundancy with the declared AUR dependency is confusing and the fallback path is the real concern — it is a genuine supply-chain risk (unverified code execution from an external package index at runtime), not merely sloppy packaging. This matches the MEDIUM classification.

PKGBUILD

1 offending line(s) highlighted
1# rubrika — Firma digital de PDFs con DNIe
2# https://github.com/vrieraj/rubrika
3
4pkgname=rubrika
5pkgver=1.0.1
6pkgrel=1
7pkgdesc="Firma digital de PDFs con DNIe o certificado .p12 — interfaz nativa KDE"
8arch=('any')
9url='https://github.com/vrieraj/rubrika'
10license=('GPL3')
11depends=(
12 # ── Sistema ──────────────────────────────────────────────────────────────
13 'opensc' # librería PKCS#11 para DNIe (/usr/lib/opensc-pkcs11.so)
14 'ccid' # driver para lectores de tarjeta USB
15 'pcsclite' # demonio PC/SC para comunicación con el lector
16
17 # ── Certificados (nuestro paquete) ────────────────────────────────────────
18 'rubrika-certificates'
19
20 # ── Python — repos oficiales ──────────────────────────────────────────────
21 'python'
22 'python-pymupdf' # renderizado de páginas PDF como imágenes
23 'python-python-pkcs11' # interfaz PKCS#11 para el DNIe
24 'python-pillow' # procesado de imagen para la rúbrica
25 'pyside6' # interfaz gráfica nativa Qt/KDE
26 'python-asn1crypto' # extracción del nombre del certificado X.509
27 'python-numpy' # conversión de pixels en la rúbrica
28
29 # ── Python — AUR ──────────────────────────────────────────────────────────
30 'python-pyhanko' # motor de firma PDF/PAdES
31 # python-pyhanko-certvalidator se instala como dependencia de python-pyhanko
32)
33optdepends=(
34 'breeze: tema Breeze nativo de KDE'
35 'xdg-utils: abrir el PDF firmado desde la aplicación'
36)
37install=rubrika.install
38source=(
39 "rubrika-${pkgver}.tar.gz::https://github.com/vrieraj/rubrika/archive/refs/tags/v${pkgver}.tar.gz"
40)
41sha256sums=('b9638d2f39806a9926bf7f1bf8ed0d46ed8aa8b7ad8ce2ac6f47280db97e88dc')
42
43package() {
44 cd "rubrika-${pkgver}"
45
46 # ── Archivos principales ──────────────────────────────────────────────────
47 install -Dm644 main.py "${pkgdir}/usr/share/rubrika/main.py"
48 install -Dm644 utils.py "${pkgdir}/usr/share/rubrika/utils.py"
49
50 # ── Wrapper ejecutable ────────────────────────────────────────────────────
51 install -Dm755 /dev/stdin "${pkgdir}/usr/bin/rubrika" << 'EOF'
52#!/bin/bash
53VENDOR_DIR="${HOME}/.local/share/rubrika/vendor"
54mkdir -p "${VENDOR_DIR}"
55export PYTHONPATH="${VENDOR_DIR}:${PYTHONPATH}"
56
57if ! python -c "import pyhanko" 2>/dev/null; then
58 echo "Instalando pyhanko en ${VENDOR_DIR}..."
59 pip install pyhanko --target="${VENDOR_DIR}" --quiet
60fi
61
62exec python /usr/share/rubrika/main.py "$@"
63EOF
64
65 # ── Entrada en el menú de aplicaciones ───────────────────────────────────
66 install -Dm644 rubrika.desktop \
67 "${pkgdir}/usr/share/applications/rubrika.desktop"
68
69 # ── Icono ─────────────────────────────────────────────────────────────────
70 install -Dm644 rubrika.svg \
71 "${pkgdir}/usr/share/icons/hicolor/scalable/apps/rubrika.svg"
72
73 # ── Documentación ─────────────────────────────────────────────────────────
74 install -Dm644 README.md \
75 "${pkgdir}/usr/share/doc/rubrika/README.md"
76 install -Dm644 LICENSE \
77 "${pkgdir}/usr/share/licenses/rubrika/LICENSE"
78}
79

Scan history

Scanned at (UTC)SeverityRules
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

Report a package

Reports go to the AURWatch maintainer (one person) and are read by hand. No login required.

0 / 4000
Your suggestion