cherry-studio-git
maintainer zxp19821005
· 0 votes
· scanned 2026-08-18 00:03:42.021799
LOW
View on AUR ↗
Why flagged
The pnpm install is part of building the project from its own source (git repo), uses locked registries (including mirrors for CN), and does not execute untrusted remote code; the installed packages are development dependencies for a legitimate build process.
Triggered rules
LOW
AI review downgraded a static finding
llm_review
The static rules flagged this MEDIUM, but an AI model (qwen/qwen3-235b-a22b-2507) reviewed the full PKGBUILD and judged it LOW (confidence 95%): The pnpm install is part of building the project from its own source (git repo), uses locked registries (including mirrors for CN), and does not execute untrusted remote code; the installed packages are development dependencies for a legitimate build process.
1 higher static finding superseded - not the current verdict (shown for transparency)
MEDIUM
npm/yarn/pnpm install of an undeclared external package
npm_install_external
Runs `npm/yarn/pnpm install <package>` for a package not in source=(), pulling unpinned, unreviewed code at build time. Severity downgraded: the package declares/looks like a Node.js consumer, where build-time installs are expected.
-
PKGBUILD:139
NODE_ENV=development pnpm add -w -D node-abi
PKGBUILD
1 offending line(s) highlighted
1
# Maintainer: zxp19821005 <zxp19821005 at 163 dot com>
2
pkgname=cherry-studio-git
3
_pkgname="Cherry Studio"
4
pkgver=2.0.5.r3.gd5c5110
5
_electronversion=41
6
_nodeversion=24.11.1
7
pkgrel=1
8
pkgdesc="🍒 Cherry Studio is a desktop client that supports for multiple LLM providers.(Use system-wide electron)"
9
arch=('any')
10
url="https://cherry-ai.com/"
11
_ghurl="https://github.com/CherryHQ/cherry-studio"
12
license=('LicenseRef-custom')
13
conflicts=("${pkgname%-git}")
14
provides=("${pkgname%-git}=${pkgver%.r*}")
15
depends=(
16
"electron${_electronversion}"
17
'libevdev'
18
'python'
19
'python-yaml'
20
'nodejs'
21
'bun'
22
'ripgrep'
23
'uv'
24
'mise'
25
)
26
makedepends=(
27
'gendesk'
28
'npm'
29
'nvm'
30
'git'
31
'curl'
32
'pnpm'
33
'jq'
34
)
35
source=(
36
"${pkgname%-git}.git::git+${_ghurl}"
37
'build-better-sqlite3.sh'
38
"${pkgname%-git}.sh"
39
)
40
sha256sums=('SKIP'
41
'4e7aa663647066f2b85226e010de351c9a24f991c6fea6621f2c6b5edd880baa'
42
'a774c2f54fbbeeaac3cefc0f7250796d30c86d27f0fd40b7eaf9c0fdb021623d')
43
pkgver() {
44
cd "${srcdir}/${pkgname%-git}.git"
45
set -o pipefail
46
git describe --long --tags --abbrev=7 | sed 's/\([^-]*-g\)/r\1/;s/-/./g;s/v//g' ||
47
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short=7 HEAD)"
48
}
49
_get_app_dir() {
50
find "${srcdir}" -type f -name "resources.pak" -exec dirname {} + | head -n 1
51
}
52
_set_build_env() {
53
export ELECTRON_DIST="/usr/lib/electron${_electronversion}"
54
export ELECTRON_SKIP_BINARY_DOWNLOAD=1
55
export SYSTEM_ELECTRON_VERSION="$(electron${_electronversion} -v | sed 's/v//g')"
56
export HOME="${srcdir}/.electron-gyp"
57
{
58
export PNPM_LINK_WORKSPACE_PACKAGES=true
59
export PNPM_FETCH_RETRY_MAXTIMEOUT=10000
60
export PNPM_CACHE_DIR="${srcdir}/.pnpm_cache"
61
export PNPM_STORE_DIR="${srcdir}/.pnpm_store"
62
export PNPM_VIRTUAL_STORE_DIR="${srcdir}/.pnpm_store"
63
export PNPM_SHAMEFULLY_HOIST=true
64
export PNPM_VIRTUAL_STORE_DIR_MAX_LENGTH=80
65
export PNPM_NODE_LINKER=isolated
66
export PNPM_NETWORK_CONCURRENCY=32
67
}
68
if [[ "$(curl -s ipinfo.io/country)" == *"CN"* ]]; then
69
{
70
export pnpm_config_registry="https://registry.npmmirror.com"
71
export npm_config_registry="https://registry.npmmirror.com"
72
export NPM_CONFIG_ELECTRON_MIRROR="https://registry.npmmirror.com/-/binary/electron/"
73
export NPM_CONFIG_ELECTRON_BUILDER_BINARIES_MIRROR="https://registry.npmmirror.com/-/binary/electron-builder-binaries/"
74
export NODEJS_ORG_MIRROR="https://npmmirror.com/mirrors/node"
75
}
76
fi
77
}
78
_ensure_local_nvm() {
79
local NVM_DIR="${srcdir}/.nvm"
80
source /usr/share/nvm/init-nvm.sh || [[ $? != 1 ]]
81
nvm install "${_nodeversion}"
82
nvm use "${_nodeversion}"
83
}
84
_get_electron_version() {
85
_elec_ver=$(find "${srcdir}" -maxdepth 5 -name "package.json" ! -path "*/node_modules/*" \
86
-exec grep -l '"electron"' {} + | xargs -I{} jq -r '(.devDependencies.electron // .dependencies.electron) // empty' {} 2>/dev/null | head -1)
87
[[ -z "${_elec_ver}" ]] && return 1
88
echo -e "The electron version is: \033[1;31m${_elec_ver%%.*}\033[0m"
89
}
90
prepare() {
91
cd "${srcdir}/${pkgname%-git}.git"
92
_get_electron_version
93
sed -i -e "
94
s/@electronversion@/${_electronversion}/g
95
s/@appname@/${pkgname%-git}/g
96
s/@runname@/app.asar/g
97
s/@cfgdirname@/${_pkgname// /}/g
98
" "${srcdir}/${pkgname%-git}.sh"
99
gendesk -q -f -n \
100
--pkgname="${pkgname%-git}" \
101
--pkgdesc="${pkgdesc}" \
102
--categories="Utility" \
103
--name="${_pkgname}" \
104
--exec="${pkgname%-git} %U"
105
106
_set_build_env
107
_ensure_local_nvm
108
sed -i "s/\"electron\": \"[^\"]*\"/\"electron\": \"${SYSTEM_ELECTRON_VERSION}\"/g" package.json
109
110
# Update better-sqlite3 release.json to match system electron version
111
sed -i "s/\"electronVersion\": \"[^\"]*\"/\"electronVersion\": \"${SYSTEM_ELECTRON_VERSION}\"/g" \
112
scripts/linux-native/release.json
113
sed -i "s/electron-v[0-9]*\.[0-9]*\.[0-9]*/electron-v${SYSTEM_ELECTRON_VERSION}/g" \
114
scripts/linux-native/release.json
115
find src -type f -exec sed -i "s/process.resourcesPath/\'\/usr\/lib\/${pkgname%-git}\'/g" {} +
116
117
# Patch download.js to disable downloading (use prebuilt from source)
118
sed -i '/const temporaryDir = /,/^}$/c\
119
const verified = verifyReleaseArtifact({ artifactPaths, assets, expected })\
120
return { ...verified, cached: true, ...artifactPaths }\
121
}' scripts/linux-native/download.js
122
123
# Patch before-pack.js to skip download-binaries.js (we use system binaries)
124
sed -i '/Downloading bundled binaries/,+2c\
125
console.log(`Using system binaries for ${platform}-${arch}...`);\
126
// Skip download - using system binaries via symlinks' scripts/before-pack.js
127
128
# Create placeholder binaries (will be replaced with symlinks in package())
129
local _arch_name
130
case "${CARCH}" in
131
x86_64) _arch_name="x64" ;;
132
aarch64) _arch_name="arm64" ;;
133
esac
134
local _binaries_dir="resources/binaries/linux-${_arch_name}"
135
mkdir -p "${_binaries_dir}"
136
# Create empty placeholder files (electron-builder needs these to exist during packaging)
137
touch "${_binaries_dir}/"{mise,bun,uv,uvx,rg}
138
NODE_ENV=development pnpm install --ignore-scripts
139
NODE_ENV=development pnpm add -w -D node-abi
140
141
# Build better-sqlite3 from source and prepare cached artifact
142
source "${srcdir}/build-better-sqlite3.sh"
143
build_better_sqlite3 "${SYSTEM_ELECTRON_VERSION}" "${CARCH}" "${srcdir}"
144
}
145
build() {
146
cd "${srcdir}/${pkgname%-git}.git"
147
_set_build_env
148
_ensure_local_nvm
149
NODE_ENV=production pnpm exec dotenv pnpm run build
150
NODE_ENV=production pnpm -c exec "electron-builder --linux dir -c.electronDist=${ELECTRON_DIST} --config electron-builder.yml"
151
local _arch_rem
152
local _app_dir=$(_get_app_dir)
153
case "${CARCH}" in
154
aarch64) _arch_rem="x64-*" ;;
155
x86_64) _arch_rem="arm64-*" ;;
156
esac
157
find "${_app_dir}/resources" -type d \( \
158
-name "*darwin*" -o \
159
-name "*win32*" -o \
160
-name "${_arch_rem}" \
161
\) -exec rm -rf {} +
162
}
163
package() {
164
install -Dm755 "${srcdir}/${pkgname%-git}.sh" "${pkgdir}/usr/bin/${pkgname%-git}"
165
install -Dm755 -d "${pkgdir}/usr/lib/${pkgname%-git}"
166
local _app_dir=$(_get_app_dir)
167
cp -a "${_app_dir}/resources/"* "${pkgdir}/usr/lib/${pkgname%-git}/"
168
rm -rf "${pkgdir}/usr/lib/${pkgname%-git}/default_app.asar"
169
# Replace placeholder binaries with symlinks to system binaries
170
local _arch_name
171
case "${CARCH}" in
172
x86_64) _arch_name="x64" ;;
173
aarch64) _arch_name="arm64" ;;
174
esac
175
local _binaries_dir="${pkgdir}/usr/lib/${pkgname%-git}/app.asar.unpacked/resources/binaries/linux-${_arch_name}"
176
mkdir -p "${_binaries_dir}"
177
rm -rf "${_binaries_dir}/"{mise,bun,uv,uvx,rg}
178
ln -sf /usr/bin/mise "${_binaries_dir}/mise"
179
ln -sf /usr/bin/bun "${_binaries_dir}/bun"
180
ln -sf /usr/bin/uv "${_binaries_dir}/uv"
181
ln -sf /usr/bin/uvx "${_binaries_dir}/uvx"
182
ln -sf /usr/bin/rg "${_binaries_dir}/rg"
183
install -Dm644 "${srcdir}/${pkgname%-git}.git/${pkgname%-git}.desktop" -t "${pkgdir}/usr/share/applications"
184
install -Dm644 "${srcdir}/${pkgname%-git}.git/build/icon.png" "${pkgdir}/usr/share/pixmaps/${pkgname%-git}.png"
185
install -Dm644 "${srcdir}/${pkgname%-git}.git/LICENSE" -t "${pkgdir}/usr/share/licenses/${pkgname}"
186
}
Changes since previous scan
--- PKGBUILD @ 2026-07-06 05:20+++ PKGBUILD @ 2026-08-18 00:03@@ -1,9 +1,9 @@ # Maintainer: zxp19821005 <zxp19821005 at 163 dot com> pkgname=cherry-studio-git _pkgname="Cherry Studio"-pkgver=1.9.7.r1376.gd9475b2+pkgver=2.0.5.r3.gd5c5110 _electronversion=41-_nodeversion=24+_nodeversion=24.11.1 pkgrel=1 pkgdesc="🍒 Cherry Studio is a desktop client that supports for multiple LLM providers.(Use system-wide electron)" arch=('any')@@ -14,9 +14,14 @@ provides=("${pkgname%-git}=${pkgver%.r*}") depends=( "electron${_electronversion}"+ 'libevdev' 'python' 'python-yaml'- 'libevdev'+ 'nodejs'+ 'bun'+ 'ripgrep'+ 'uv'+ 'mise' ) makedepends=( 'gendesk'@@ -29,9 +34,11 @@ ) source=( "${pkgname%-git}.git::git+${_ghurl}"+ 'build-better-sqlite3.sh' "${pkgname%-git}.sh" ) sha256sums=('SKIP'+ '4e7aa663647066f2b85226e010de351c9a24f991c6fea6621f2c6b5edd880baa' 'a774c2f54fbbeeaac3cefc0f7250796d30c86d27f0fd40b7eaf9c0fdb021623d') pkgver() { cd "${srcdir}/${pkgname%-git}.git"@@ -43,7 +50,7 @@ find "${srcdir}" -type f -name "resources.pak" -exec dirname {} + | head -n 1 } _set_build_env() {- export electronDist="/usr/lib/electron${_electronversion}"+ export ELECTRON_DIST="/usr/lib/electron${_electronversion}" export ELECTRON_SKIP_BINARY_DOWNLOAD=1 export SYSTEM_ELECTRON_VERSION="$(electron${_electronversion} -v | sed 's/v//g')" export HOME="${srcdir}/.electron-gyp"@@ -95,22 +102,52 @@ --categories="Utility" \ --name="${_pkgname}" \ --exec="${pkgname%-git} %U"+ _set_build_env _ensure_local_nvm sed -i "s/\"electron\": \"[^\"]*\"/\"electron\": \"${SYSTEM_ELECTRON_VERSION}\"/g" package.json- NODE_ENV=development pnpm install --ignore-scripts- sed -i 's/Napi::Buffer<char>::NewOrCopy/Napi::Buffer<char>::New/g' \- node_modules/.pnpm/sharp@0.34.5/node_modules/sharp/src/metadata.cc+ + # Update better-sqlite3 release.json to match system electron version+ sed -i "s/\"electronVersion\": \"[^\"]*\"/\"electronVersion\": \"${SYSTEM_ELECTRON_VERSION}\"/g" \+ scripts/linux-native/release.json+ sed -i "s/electron-v[0-9]*\.[0-9]*\.[0-9]*/electron-v${SYSTEM_ELECTRON_VERSION}/g" \+ scripts/linux-native/release.json+ find src -type f -exec sed -i "s/process.resourcesPath/\'\/usr\/lib\/${pkgname%-git}\'/g" {} ++ + # Patch download.js to disable downloading (use prebuilt from source)+ sed -i '/const temporaryDir = /,/^}$/c\+ const verified = verifyReleaseArtifact({ artifactPaths, assets, expected })\+ return { ...verified, cached: true, ...artifactPaths }\+}' scripts/linux-native/download.js+ + # Patch before-pack.js to skip download-binaries.js (we use system binaries)+ sed -i '/Downloading bundled binaries/,+2c\+ console.log(`Using system binaries for ${platform}-${arch}...`);\+ // Skip download - using system binaries via symlinks' scripts/before-pack.js+ + # Create placeholder binaries (will be replaced with symlinks in package())+ local _arch_name+ case "${CARCH}" in+ x86_64) _arch_name="x64" ;;+ aarch64) _arch_name="arm64" ;;+ esac+ local _binaries_dir="resources/binaries/linux-${_arch_name}"+ mkdir -p "${_binaries_dir}"+ # Create empty placeholder files (electron-builder needs these to exist during packaging)+ touch "${_binaries_dir}/"{mise,bun,uv,uvx,rg} + NODE_ENV=development pnpm install --ignore-scripts+ NODE_ENV=development pnpm add -w -D node-abi+ + # Build better-sqlite3 from source and prepare cached artifact+ source "${srcdir}/build-better-sqlite3.sh"+ build_better_sqlite3 "${SYSTEM_ELECTRON_VERSION}" "${CARCH}" "${srcdir}" } build() { cd "${srcdir}/${pkgname%-git}.git" _set_build_env- _ensure_local_nvm- NODE_ENV=production pnpm --filter @cherrystudio/ai-sdk-provider build- NODE_ENV=production pnpm --filter @cherrystudio/ai-core build- NODE_ENV=production pnpm --filter @cherrystudio/extension-table-plus build- NODE_ENV=production pnpm -c exec "electron-vite build"- NODE_ENV=production pnpm -c exec "electron-builder --linux dir -c.electronDist=${electronDist} --config electron-builder.yml"+ _ensure_local_nvm + NODE_ENV=production pnpm exec dotenv pnpm run build+ NODE_ENV=production pnpm -c exec "electron-builder --linux dir -c.electronDist=${ELECTRON_DIST} --config electron-builder.yml" local _arch_rem local _app_dir=$(_get_app_dir) case "${CARCH}" in@@ -127,9 +164,23 @@ install -Dm755 "${srcdir}/${pkgname%-git}.sh" "${pkgdir}/usr/bin/${pkgname%-git}" install -Dm755 -d "${pkgdir}/usr/lib/${pkgname%-git}" local _app_dir=$(_get_app_dir)- cp -a "${_app_dir}/resources/". "${pkgdir}/usr/lib/${pkgname%-git}/"+ cp -a "${_app_dir}/resources/"* "${pkgdir}/usr/lib/${pkgname%-git}/"+ rm -rf "${pkgdir}/usr/lib/${pkgname%-git}/default_app.asar"+ # Replace placeholder binaries with symlinks to system binaries+ local _arch_name+ case "${CARCH}" in+ x86_64) _arch_name="x64" ;;+ aarch64) _arch_name="arm64" ;;+ esac+ local _binaries_dir="${pkgdir}/usr/lib/${pkgname%-git}/app.asar.unpacked/resources/binaries/linux-${_arch_name}"+ mkdir -p "${_binaries_dir}"+ rm -rf "${_binaries_dir}/"{mise,bun,uv,uvx,rg}+ ln -sf /usr/bin/mise "${_binaries_dir}/mise"+ ln -sf /usr/bin/bun "${_binaries_dir}/bun"+ ln -sf /usr/bin/uv "${_binaries_dir}/uv"+ ln -sf /usr/bin/uvx "${_binaries_dir}/uvx"+ ln -sf /usr/bin/rg "${_binaries_dir}/rg" install -Dm644 "${srcdir}/${pkgname%-git}.git/${pkgname%-git}.desktop" -t "${pkgdir}/usr/share/applications" install -Dm644 "${srcdir}/${pkgname%-git}.git/build/icon.png" "${pkgdir}/usr/share/pixmaps/${pkgname%-git}.png" install -Dm644 "${srcdir}/${pkgname%-git}.git/LICENSE" -t "${pkgdir}/usr/share/licenses/${pkgname}" }-Scan history
| Scanned at (UTC) | Severity | Rules |
|---|---|---|
| 2026-08-18 00:03:42 | LOW | 2 |
| 2026-08-17 00:18:29 | LOW | 2 |
| 2026-08-16 00:03:42 | LOW | 2 |
| 2026-08-15 00:26:13 | LOW | 2 |
| 2026-08-14 00:03:41 | LOW | 2 |
| 2026-08-13 21:26:43 | MEDIUM | 1 |
| 2026-07-06 05:20:03 | CLEAN | 0 |
| 2026-06-18 16:11:54 | CLEAN | 0 |