ya-claude-code
The package downloads a binary and manifest from Anthropic's official domain (downloads.claude.ai), verifies the binary's checksum against a PGP-signed manifest, and uses a known signing key; the non-standard host is legitimate and the verification mitigates supply-chain risks.
Triggered rules
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 package downloads a binary and manifest from Anthropic's official domain (downloads.claude.ai), verifies the binary's checksum against a PGP-signed manifest, and uses a known signing key; the non-standard host is legitimate and the verification mitigates supply-chain risks.
1 higher static finding superseded - not the current verdict (shown for transparency)
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:35
"legal-${pkgver}.md::https://code.claude.com/docs/en/legal-and-compliance.md"
PKGBUILD
1 offending line(s) highlighted# Maintainer: Aaron Bockelie <aaronsb@gmail.com>
pkgname=ya-claude-code
pkgver=2.1.284
pkgrel=1
pkgdesc="Claude Code CLI, verified at build time against Anthropic's signed release manifest"
arch=('x86_64')
url="https://github.com/anthropics/claude-code"
license=('LicenseRef-claude-code')
depends=('bash' 'glibc')
# Same key that signs the Claude Desktop apt repository — one Anthropic release
# signing identity covers both products.
_fpr='31DDDE24DDFAB679F42D7BD2BAA929FF1A7ECACE'
_rel="https://downloads.claude.ai/claude-code-releases/${pkgver}"
optdepends=('git: let Claude use git'
'github-cli: GitHub integration'
'glab: GitLab integration'
'ripgrep: faster file search'
'tmux: agent team split panes'
'bubblewrap: sandboxing'
'socat: sandboxing')
provides=('claude-code')
conflicts=('claude-code')
# Self-contained Bun executable with an embedded runtime and resources;
# stripping corrupts it.
options=('!strip' '!debug')
source=("claude-${pkgver}::${_rel}/linux-x64/claude"
"manifest-${pkgver}.json::${_rel}/manifest.json"
"manifest-${pkgver}.json.pgpsig::${_rel}/manifest.json.sig"
"legal-${pkgver}.md::https://code.claude.com/docs/en/legal-and-compliance.md"
'anthropic-release-signing.key')
# The manifest and its detached signature authenticate each other, and the legal
# text is prose that upstream edits in place; none of the three can carry a fixed
# hash. The binary's hash is pinned and additionally re-derived from the signed
# manifest in prepare().
sha256sums=('5cd90aabd83f8a15136c35aa37bb1d92b348993573316643dc3fe4e04afbf88f'
'SKIP'
'SKIP'
'SKIP'
'bd70a5e4a268002704024ceba7f8446024114e94f3f0bdd11c23a9e592be81c6')
prepare() {
cd "$srcdir"
local keyring="$srcdir/.gnupg"
rm -rf "$keyring"
install -dm700 "$keyring"
gpg --homedir "$keyring" --batch --quiet --import anthropic-release-signing.key
local got
got=$(gpg --homedir "$keyring" --batch --with-colons --fingerprint \
| awk -F: '/^fpr:/{print $10; exit}')
if [[ $got != "$_fpr" ]]; then
echo "==> signing key is not Anthropic's: $got" >&2
return 1
fi
gpg --homedir "$keyring" --batch --verify \
"manifest-${pkgver}.json.pgpsig" "manifest-${pkgver}.json" >/dev/null 2>&1 || {
echo "==> release manifest signature did not verify" >&2
return 1
}
# The signed manifest carries the version alongside the checksums, so a
# manifest for some other release cannot be substituted for this one.
local mver
mver=$(sed -n 's/.*"version"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' \
"manifest-${pkgver}.json" | head -1)
if [[ $mver != "$pkgver" ]]; then
echo "==> signed manifest is for ${mver:-nothing}, not ${pkgver}" >&2
return 1
fi
local signed
signed=$(sed -n '/"linux-x64"[[:space:]]*:/,/}/p' "manifest-${pkgver}.json" \
| sed -n 's/.*"checksum"[[:space:]]*:[[:space:]]*"\([0-9a-f]\{64\}\)".*/\1/p' | head -1)
if [[ $signed != "${sha256sums[0]}" ]]; then
echo "==> linux-x64 checksum in the signed manifest (${signed:-none}) != pinned ${sha256sums[0]}" >&2
return 1
fi
echo "==> verified claude ${pkgver} against Anthropic's signed release manifest"
}
package() {
cd "$srcdir"
install -Dm755 "claude-${pkgver}" "$pkgdir/opt/${pkgname}/bin/claude"
# The binary self-updates and expects the native-installer layout under
# ~/.local/bin. Both are wrong for a packaged install: an in-place update
# would replace pacman-owned files, and the layout check warns on every
# start. The wrapper turns off each.
install -d "$pkgdir/usr/bin"
cat > "$pkgdir/usr/bin/claude" <<EOF
#!/bin/sh
export DISABLE_UPDATES=1
export DISABLE_INSTALLATION_CHECKS=1
exec /opt/${pkgname}/bin/claude "\$@"
EOF
chmod 755 "$pkgdir/usr/bin/claude"
install -Dm644 "legal-${pkgver}.md" "$pkgdir/usr/share/licenses/$pkgname/LICENSE"
}
Changes since previous scan
--- PKGBUILD @ 2026-09-28 00:28+++ PKGBUILD @ 2026-10-02 00:00@@ -1,7 +1,7 @@ # Maintainer: Aaron Bockelie <aaronsb@gmail.com> pkgname=ya-claude-code-pkgver=2.1.282+pkgver=2.1.284 pkgrel=1 pkgdesc="Claude Code CLI, verified at build time against Anthropic's signed release manifest" arch=('x86_64')@@ -39,7 +39,7 @@ # text is prose that upstream edits in place; none of the three can carry a fixed # hash. The binary's hash is pinned and additionally re-derived from the signed # manifest in prepare().-sha256sums=('3afe8535c0cc33f0e24f7b25dab7a1727b8b592196f8496a8bc302ba2161eed3'+sha256sums=('5cd90aabd83f8a15136c35aa37bb1d92b348993573316643dc3fe4e04afbf88f' 'SKIP' 'SKIP' 'SKIP'Scan history
| Scanned at (UTC) | Severity | Rules |
|---|---|---|
| 2026-10-02 00:00:32 | Low | 2 |
| 2026-10-01 00:02:06 | Low | 2 |
| 2026-09-30 00:20:07 | Low | 2 |
| 2026-09-29 00:07:46 | Low | 2 |
| 2026-09-28 21:21:47 | Medium | 1 |
| 2026-09-28 00:28:32 | Low | 2 |
| 2026-09-27 00:07:07 | Low | 2 |
| 2026-09-26 13:15:17 | Medium | 1 |
| 2026-09-26 00:12:15 | Low | 2 |
| 2026-09-25 13:11:58 | Medium | 1 |
| 2026-09-25 00:03:36 | Low | 2 |
| 2026-09-24 13:43:45 | Medium | 1 |
| 2026-09-24 00:24:14 | Low | 2 |
| 2026-09-23 13:40:34 | Medium | 1 |
| 2026-09-23 00:28:13 | Low | 2 |
| 2026-09-22 00:15:14 | Low | 2 |
| 2026-09-21 00:26:32 | Low | 2 |
| 2026-09-20 00:25:31 | Low | 2 |
| 2026-09-19 11:30:33 | Medium | 1 |
| 2026-09-19 00:25:36 | Low | 2 |