grokbot-linux-port

LOW
maintainer Nichokas 0 votes scanned 2026-08-20 09:10:51.385725
View on AUR
Why flagged

The package builds from a legitimate GitHub source, uses standard build tools, and does not execute untrusted remote code; the low severity is due to few votes and recent upload, not inherent risk.

Triggered rules

Low Few votes, recently uploaded zero_votes_recent

Uploaded within the last 14 days with 2 or fewer community votes — little peer review so far.

Low AI review llm_review

An AI model (qwen/qwen3-235b-a22b-2507) reviewed this and agrees it is LOW (confidence 95%): The package builds from a legitimate GitHub source, uses standard build tools, and does not execute untrusted remote code; the low severity is due to few votes and recent upload, not inherent risk.

PKGBUILD

1# Maintainer: Nichokas <https://github.com/Nichokas>
2# Co-maintained via https://github.com/Nichokas/grokbot-linux-port
3pkgname=grokbot-linux-port
4pkgver=0.23.0
5pkgrel=1
6pkgdesc="Grok Bot desktop — wine-less Linux port (fuses win32 NSIS payload with Electron 42.1.0)"
7arch=('x86_64')
8url="https://github.com/Nichokas/grokbot-linux-port"
9license=('custom')
10depends=(
11 'alsa-lib' 'gtk3' 'nss' 'libxss' 'libxtst' 'libxrandr'
12 'libxdamage' 'libxcomposite' 'libxfixes' 'libdrm' 'mesa'
13 'libxkbcommon' 'at-spi2-core' 'cairo' 'pango'
14 'expat' 'hicolor-icon-theme'
15)
16makedepends=('p7zip' 'curl' 'unzip' 'nodejs' 'npm' 'python' 'git')
17optdepends=('libnotify: desktop notifications')
18provides=('grok-bot' 'grokbot')
19conflicts=('grokbot-linux-port-bin' 'grok-bot')
20source=("${pkgname}-${pkgver}.tar.gz::https://github.com/Nichokas/grokbot-linux-port/archive/v${pkgver}.tar.gz")
21sha256sums=('71aed194ba885cd282c263bfe03724ae6054e437fc1572c77717eb086bf415da')
22
23prepare() {
24 cd "${srcdir}/${pkgname}-${pkgver}"
25 rm -rf dist
26 # Prevent stale extraction from previous makepkg run shadowing the new build
27 rm -rf "${srcdir}/Grok_Bot_${pkgver}_linux_x64"
28}
29
30build() {
31 cd "${srcdir}/${pkgname}-${pkgver}"
32 # port.sh is intentionally best-effort for @electron/rebuild (still emits
33 # the tarball on failure for CI/local debugging). For AUR packaging the
34 # native modules must be Linux-rebuilt — fail the build if any .node
35 # remains Windows-built. Allow opt-out via GROKBOT_ALLOW_BROKEN_NATIVE=1.
36 bash scripts/port.sh "${pkgver}"
37 if [[ "${GROKBOT_ALLOW_BROKEN_NATIVE:-}" != "1" ]]; then
38 local tarball="dist/Grok_Bot_${pkgver}_linux_x64.tar.gz"
39 if [[ -f "${tarball}" ]]; then
40 # Heuristic: warn if the staged tree still contains win32 .node markers
41 # (port.sh logs the rebuild outcome; this catches the silent-still-tarball case)
42 local probe_dir
43 probe_dir="$(mktemp -d)"
44 tar -xzf "${tarball}" -C "${probe_dir}" 2>/dev/null || true
45 # Fail if any Linux-loadable .node is still a Windows PE. Exemptions
46 # match port.sh: win32 prebuild dirs and napi-rs *.win32-*.node files
47 # are dead code on Linux (loaders filter them by platform).
48 local mz_live
49 mz_live="$(find "${probe_dir}" -name '*.node' -type f -exec sh -c \
50 'head -c 2 "$1" | grep -q MZ && printf "%s\n" "$1"' _ {} \; 2>/dev/null \
51 | grep -v -e '/prebuilds/win32-' -e '\.win32-[^/]*\.node$' || true)"
52 if [[ -n "${mz_live}" ]]; then
53 echo "error: loadable native .node modules appear to be win32 binaries — @electron/rebuild likely failed:" >&2
54 printf '%s\n' "${mz_live}" | head -n 10 >&2
55 echo "hint: re-run with GROKBOT_ALLOW_BROKEN_NATIVE=1 makepkg -si to bypass, or fix the rebuild toolchain" >&2
56 rm -rf "${probe_dir}"
57 exit 1
58 fi
59 rm -rf "${probe_dir}"
60 fi
61 fi
62}
63
64package() {
65 cd "${srcdir}/${pkgname}-${pkgver}"
66
67 # Always prefer the just-built tarball; never reuse a stale sibling dir
68 local tarball="dist/Grok_Bot_${pkgver}_linux_x64.tar.gz"
69 if [[ ! -f "${tarball}" ]]; then
70 echo "error: expected tarball ${tarball} not found after build" >&2
71 exit 1
72 fi
73 rm -rf "${srcdir}/Grok_Bot_${pkgver}_linux_x64"
74 tar -xzf "${tarball}" -C "${srcdir}"
75 local staged="${srcdir}/Grok_Bot_${pkgver}_linux_x64"
76 if [[ ! -d "${staged}" ]]; then
77 staged="$(find "${srcdir}" -maxdepth 1 -type d -name "Grok_Bot_${pkgver}_linux_x64" -print -quit 2>/dev/null || true)"
78 fi
79 if [[ -z "${staged}" || ! -d "${staged}" ]]; then
80 echo "error: staged app dir not found after build" >&2
81 exit 1
82 fi
83
84 # Tarballs produced by older port.sh kept NSIS restrictive modes
85 # (drwx------ on app.asar.unpacked). cp -a preserves them; normalise so the
86 # installed tree is readable by the invoking user, not only root.
87 chmod -R u+rwX,go+rX,go-w "${staged}"
88
89 install -dm755 "${pkgdir}/opt/${pkgname}" "${pkgdir}/usr/bin" \
90 "${pkgdir}/usr/share/applications" \
91 "${pkgdir}/usr/share/icons/hicolor/256x256/apps" \
92 "${pkgdir}/usr/share/licenses/${pkgname}"
93
94 cp -a "${staged}/." "${pkgdir}/opt/${pkgname}/"
95 chmod +x "${pkgdir}/opt/${pkgname}/grok-bot"
96
97 # Symlink for PATH
98 ln -s "/opt/${pkgname}/grok-bot" "${pkgdir}/usr/bin/grok-bot"
99 ln -s "/opt/${pkgname}/grok-bot" "${pkgdir}/usr/bin/grokbot"
100
101 # Desktop entry — use --no-sandbox only as fallback; the wrapper prefers sandbox when available
102 cat > "${pkgdir}/usr/share/applications/grok-bot.desktop" <<DESKTOP
103[Desktop Entry]
104Name=Grok Bot
105GenericName=Grok Bot
106Comment=Grok Bot desktop agent (Linux port)
107Exec=/opt/${pkgname}/grok-bot %U
108Icon=grok-bot
109Type=Application
110Categories=Utility;Development;
111StartupWMClass=grok-bot
112MimeType=x-scheme-handler/grokbot;
113Terminal=false
114DESKTOP
115
116 # Icon — best-effort hunt (packaged tarball may embed it inside app.asar)
117 local icon=""
118 for cand in \
119 "${staged}/resources/app.asar.unpacked/dist/renderer/assets/app-icon-"*.png \
120 "${staged}/resources/app.asar.unpacked/"*.png \
121 "${staged}/grok-bot.png" \
122 ; do
123 [[ -f "${cand}" ]] && { icon="${cand}"; break; }
124 done
125 if [[ -z "${icon}" ]]; then
126 icon="$(find "${staged}" -name 'app-icon*.png' -print -quit 2>/dev/null || true)"
127 fi
128 if [[ -n "${icon}" && -f "${icon}" ]]; then
129 install -Dm644 "${icon}" "${pkgdir}/usr/share/icons/hicolor/256x256/apps/grok-bot.png"
130 fi
131
132 # License placeholder — upstream EULA is inside app.asar; point there
133 cat > "${pkgdir}/usr/share/licenses/${pkgname}/LICENSE" <<LICENSE
134Grok Bot is proprietary software. This AUR package redistributes no upstream
135binary itself in the -bin variant it fetches the official Windows distribution
136at build time (non-bin) or the prebuilt Linux tarball produced by
137https://github.com/Nichokas/grokbot-linux-port. See upstream terms at
138https://grok.com and inside resources/app.asar.
139LICENSE
140
141 # chrome-sandbox: makepkg strips setuid by default. Keep 4755 and instruct
142 # namcap override via !strip where needed. Use install -m4755 explicitly.
143 if [[ -f "${pkgdir}/opt/${pkgname}/chrome-sandbox" ]]; then
144 chmod 4755 "${pkgdir}/opt/${pkgname}/chrome-sandbox"
145 fi
146}
147

Changes since previous scan

--- PKGBUILD @ 2026-08-15 00:26
+++ PKGBUILD @ 2026-08-20 09:10
@@ -1,9 +1,9 @@
# Maintainer: Nichokas <https://github.com/Nichokas>
# Co-maintained via https://github.com/Nichokas/grokbot-linux-port
pkgname=grokbot-linux-port
-pkgver=0.20.0
+pkgver=0.23.0
pkgrel=1
-pkgdesc="Grok Bot desktop: wine-less Linux port"
+pkgdesc="Grok Bot desktop — wine-less Linux port (fuses win32 NSIS payload with Electron 42.1.0)"
arch=('x86_64')
url="https://github.com/Nichokas/grokbot-linux-port"
license=('custom')
@@ -18,7 +18,7 @@
provides=('grok-bot' 'grokbot')
conflicts=('grokbot-linux-port-bin' 'grok-bot')
source=("${pkgname}-${pkgver}.tar.gz::https://github.com/Nichokas/grokbot-linux-port/archive/v${pkgver}.tar.gz")
-sha256sums=('8d6c7d1a02c8be09e3ca99e7645a6f7841591d8da73d0f594ae2052f6106cc2a')
+sha256sums=('71aed194ba885cd282c263bfe03724ae6054e437fc1572c77717eb086bf415da')
prepare() {
cd "${srcdir}/${pkgname}-${pkgver}"
@@ -42,16 +42,19 @@
local probe_dir
probe_dir="$(mktemp -d)"
tar -xzf "${tarball}" -C "${probe_dir}" 2>/dev/null || true
- local nodes
- nodes="$(find "${probe_dir}" -name '*.node' -print 2>/dev/null | head -n 20)"
- if [[ -n "${nodes}" ]]; then
- # Best-effort: detect PE/MZ header leftovers from win32 build (vs ELF)
- if grep -q "MZ" <<<"$(head -c 2 "${probe_dir}"/Grok_Bot_*/resources/app.asar.unpacked/**/*.node 2>/dev/null | head -c 10 || true)"; then
- echo "error: native .node modules appear to be win32 binaries — @electron/rebuild likely failed" >&2
- echo "hint: re-run with GROKBOT_ALLOW_BROKEN_NATIVE=1 makepkg -si to bypass, or fix the rebuild toolchain" >&2
- rm -rf "${probe_dir}"
- exit 1
- fi
+ # Fail if any Linux-loadable .node is still a Windows PE. Exemptions
+ # match port.sh: win32 prebuild dirs and napi-rs *.win32-*.node files
+ # are dead code on Linux (loaders filter them by platform).
+ local mz_live
+ mz_live="$(find "${probe_dir}" -name '*.node' -type f -exec sh -c \
+ 'head -c 2 "$1" | grep -q MZ && printf "%s\n" "$1"' _ {} \; 2>/dev/null \
+ | grep -v -e '/prebuilds/win32-' -e '\.win32-[^/]*\.node$' || true)"
+ if [[ -n "${mz_live}" ]]; then
+ echo "error: loadable native .node modules appear to be win32 binaries — @electron/rebuild likely failed:" >&2
+ printf '%s\n' "${mz_live}" | head -n 10 >&2
+ echo "hint: re-run with GROKBOT_ALLOW_BROKEN_NATIVE=1 makepkg -si to bypass, or fix the rebuild toolchain" >&2
+ rm -rf "${probe_dir}"
+ exit 1
fi
rm -rf "${probe_dir}"
fi
@@ -78,10 +81,15 @@
exit 1
fi
+ # Tarballs produced by older port.sh kept NSIS restrictive modes
+ # (drwx------ on app.asar.unpacked). cp -a preserves them; normalise so the
+ # installed tree is readable by the invoking user, not only root.
+ chmod -R u+rwX,go+rX,go-w "${staged}"
+
install -dm755 "${pkgdir}/opt/${pkgname}" "${pkgdir}/usr/bin" \
- "${pkgdir}/usr/share/applications" \
- "${pkgdir}/usr/share/icons/hicolor/256x256/apps" \
- "${pkgdir}/usr/share/licenses/${pkgname}"
+ "${pkgdir}/usr/share/applications" \
+ "${pkgdir}/usr/share/icons/hicolor/256x256/apps" \
+ "${pkgdir}/usr/share/licenses/${pkgname}"
cp -a "${staged}/." "${pkgdir}/opt/${pkgname}/"
chmod +x "${pkgdir}/opt/${pkgname}/grok-bot"
@@ -91,7 +99,7 @@
ln -s "/opt/${pkgname}/grok-bot" "${pkgdir}/usr/bin/grokbot"
# Desktop entry — use --no-sandbox only as fallback; the wrapper prefers sandbox when available
- cat >"${pkgdir}/usr/share/applications/grok-bot.desktop" <<DESKTOP
+ cat > "${pkgdir}/usr/share/applications/grok-bot.desktop" <<DESKTOP
[Desktop Entry]
Name=Grok Bot
GenericName=Grok Bot
@@ -110,11 +118,9 @@
for cand in \
"${staged}/resources/app.asar.unpacked/dist/renderer/assets/app-icon-"*.png \
"${staged}/resources/app.asar.unpacked/"*.png \
- "${staged}/grok-bot.png"; do
- [[ -f "${cand}" ]] && {
- icon="${cand}"
- break
- }
+ "${staged}/grok-bot.png" \
+ ; do
+ [[ -f "${cand}" ]] && { icon="${cand}"; break; }
done
if [[ -z "${icon}" ]]; then
icon="$(find "${staged}" -name 'app-icon*.png' -print -quit 2>/dev/null || true)"
@@ -124,7 +130,7 @@
fi
# License placeholder — upstream EULA is inside app.asar; point there
- cat >"${pkgdir}/usr/share/licenses/${pkgname}/LICENSE" <<LICENSE
+ cat > "${pkgdir}/usr/share/licenses/${pkgname}/LICENSE" <<LICENSE
Grok Bot is proprietary software. This AUR package redistributes no upstream
binary itself in the -bin variant it fetches the official Windows distribution
at build time (non-bin) or the prebuilt Linux tarball produced by

Scan history

Scanned at (UTC)SeverityRules
2026-08-20 09:10:51 Low 2
2026-08-15 00:26:13 Clean 2
2026-08-14 23:30:04 Low 1
2026-08-14 21:29:33 Low 1

Report a package

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

0 / 4000
Your suggestion