factory-cli-bin

maintainer alex5402 · 2 votes · scanned 2026-08-03 00:08:14.047287
MEDIUM
View on AUR ↗
Why flagged This PKGBUILD downloads pre-compiled binaries at install time from downloads.factory.ai (an unofficial/vendor-controlled host) without declaring them in source=() or providing fixed sha256sums in the PKGBUILD itself. The version is dynamically fetched by curling app.factory.ai/cli at build time, meaning the version and download URLs are entirely controlled by the remote server at package() execution time. While the PKGBUILD does perform sha256 verification against checksums also fetched from the same server (making the verification trivially bypassable by the same attacker who controls the server), the binaries are installed but NOT executed during the build process itself - they are only installed to pkgdir. The flagged 'executed file' at line 149 is actually `install -Dm755 'droid' ...` which installs but does not execute the binary. The core concern is: (1) no reproducibility - the package content can change silently between builds since source=() is empty and no fixed hashes exist in the PKGBUILD; (2) the checksum oracle is the same host serving the binary, providing no real integrity guarantee against a compromised server; (3) binaries are closed-source from a commercial vendor. This is a medium supply-chain risk (unverifiable binary from a vendor host with no pinned hashes) but not clearly malicious RCE or exfiltration.

Triggered rules

MEDIUM External download from an untrusted host, not in source=() external_download_not_in_source

curl/wget fetches a URL on a non-allowlisted host that is not part of source=(), so it is not checksum-verified by makepkg.

  • PKGBUILD:30 actual_version=$(curl -fsSL "https://app.factory.ai/cli" | grep -oP 'VER="\K[0-9]+\.[0-9]+\.[0-9]+')
MEDIUM AI review downgraded a static finding llm_review

The static rules flagged this HIGH, but an AI model (anthropic/claude-4.6-sonnet-20260217) reviewed the full PKGBUILD and judged it MEDIUM (confidence 82%): This PKGBUILD downloads pre-compiled binaries at install time from downloads.factory.ai (an unofficial/vendor-controlled host) without declaring them in source=() or providing fixed sha256sums in the PKGBUILD itself. The version is dynamically fetched by curling app.factory.ai/cli at build time, meaning the version and download URLs are entirely controlled by the remote server at package() execution time. While the PKGBUILD does perform sha256 verification against checksums also fetched from the same server (making the verification trivially bypassable by the same attacker who controls the server), the binaries are installed but NOT executed during the build process itself - they are only installed to pkgdir. The flagged 'executed file' at line 149 is actually `install -Dm755 'droid' ...` which installs but does not execute the binary. The core concern is: (1) no reproducibility - the package content can change silently between builds since source=() is empty and no fixed hashes exist in the PKGBUILD; (2) the checksum oracle is the same host serving the binary, providing no real integrity guarantee against a compromised server; (3) binaries are closed-source from a commercial vendor. This is a medium supply-chain risk (unverifiable binary from a vendor host with no pinned hashes) but not clearly malicious RCE or exfiltration.

1 higher static finding superseded - not the current verdict (shown for transparency)
HIGH Downloaded file is executed download_then_exec

A file fetched with curl/wget (not part of source=(), so never checksum-verified) is later made executable or run — a fetch-and-execute pattern split across statements.

  • PKGBUILD:149 chmod 755 "$pkgdir/usr/bin/droid"

PKGBUILD

2 offending line(s) highlighted
1# Maintainer: alex5402 <alexbhaiya@duck.com>
2pkgname=factory-cli-bin
3pkgver=1.0.2
4pkgrel=1
5pkgdesc="Factory CLI - AI-powered terminal assistant"
6arch=('x86_64' 'aarch64')
7url="https://app.factory.ai"
8license=('factory.ai')
9depends=('curl')
10optdepends=('ripgrep: Use system ripgrep instead of bundled version')
11provides=('droid')
12conflicts=('droid')
13options=('!strip')
14install="${pkgname}.install"
15
16# Sources will be downloaded dynamically in package() function
17source=()
18sha256sums=()
19
20pkgver() {
21 # Fetch the install script and extract the version
22 curl -fsSL "https://app.factory.ai/cli" | grep -oP 'VER="\K[0-9]+\.[0-9]+\.[0-9]+' || echo "1.0.0"
23}
24
25package() {
26 cd "$srcdir"
27
28 # Get the actual version from the install script
29 local actual_version
30 actual_version=$(curl -fsSL "https://app.factory.ai/cli" | grep -oP 'VER="\K[0-9]+\.[0-9]+\.[0-9]+')
31
32 if [[ -z "$actual_version" ]]; then
33 error "Failed to fetch version from install script"
34 return 1
35 fi
36
37 msg2 "Detected Factory CLI version: $actual_version"
38
39 # Detect platform (always linux for Arch)
40 local platform="linux"
41
42 # Detect architecture
43 local architecture rg_architecture arch_suffix
44 case "$CARCH" in
45 x86_64)
46 architecture="x64"
47 ;;
48 aarch64)
49 architecture="arm64"
50 ;;
51 *)
52 error "Unsupported architecture: $CARCH"
53 return 1
54 ;;
55 esac
56
57 # Detect AVX2 support for x64 (for optimized droid binary)
58 rg_architecture="$architecture"
59 arch_suffix=""
60
61 if [[ "$architecture" == "x64" ]]; then
62 if grep -qi avx2 /proc/cpuinfo 2>/dev/null; then
63 msg2 "AVX2 support detected, using optimized binary"
64 else
65 arch_suffix="-baseline"
66 msg2 "No AVX2 support detected, using baseline binary"
67 fi
68 fi
69
70 local droid_architecture="${architecture}${arch_suffix}"
71
72 # Construct download URLs using the actual version
73 local base_url="https://downloads.factory.ai"
74 local droid_url="$base_url/factory-cli/releases/$actual_version/$platform/$droid_architecture/droid"
75 local droid_sha_url="$base_url/factory-cli/releases/$actual_version/$platform/$droid_architecture/droid.sha256"
76 local rg_url="$base_url/ripgrep/$platform/$rg_architecture/rg"
77 local rg_sha_url="$base_url/ripgrep/$platform/$rg_architecture/rg.sha256"
78
79 # Download droid binary
80 msg2 "Downloading droid for $platform-$droid_architecture..."
81 curl -fsSL -o "droid" "$droid_url" || {
82 error "Failed to download droid from $droid_url"
83 return 1
84 }
85
86 # Download and verify droid checksum
87 msg2 "Verifying droid checksum..."
88 curl -fsSL -o "droid.sha256" "$droid_sha_url" || {
89 error "Failed to download droid checksum"
90 return 1
91 }
92
93 local expected_sha actual_sha
94 expected_sha=$(awk '{print $1}' "droid.sha256")
95 actual_sha=$(sha256sum "droid" | awk '{print $1}')
96
97 if [[ -n "$expected_sha" && "$expected_sha" != "$actual_sha" ]]; then
98 error "Droid checksum verification failed!"
99 error "Expected: $expected_sha"
100 error "Actual: $actual_sha"
101 return 1
102 fi
103 msg2 "Droid checksum verified successfully"
104
105 # Download ripgrep binary
106 msg2 "Downloading ripgrep for $platform-$rg_architecture..."
107 curl -fsSL -o "rg" "$rg_url" || {
108 error "Failed to download ripgrep from $rg_url"
109 return 1
110 }
111
112 # Download and verify ripgrep checksum
113 msg2 "Verifying ripgrep checksum..."
114 curl -fsSL -o "rg.sha256" "$rg_sha_url" || {
115 error "Failed to download ripgrep checksum"
116 return 1
117 }
118
119 local expected_rg_sha actual_rg_sha
120 expected_rg_sha=$(awk '{print $1}' "rg.sha256")
121 actual_rg_sha=$(sha256sum "rg" | awk '{print $1}')
122
123 if [[ -n "$expected_rg_sha" && "$expected_rg_sha" != "$actual_rg_sha" ]]; then
124 error "Ripgrep checksum verification failed!"
125 error "Expected: $expected_rg_sha"
126 error "Actual: $actual_rg_sha"
127 return 1
128 fi
129 msg2 "Ripgrep checksum verified successfully"
130
131 # Create installation directories
132 install -dm755 "$pkgdir/usr/lib/factory"
133 install -dm755 "$pkgdir/usr/bin"
134
135 # Install binaries to /usr/lib/factory
136 install -Dm755 "droid" "$pkgdir/usr/lib/factory/droid"
137 install -Dm755 "rg" "$pkgdir/usr/lib/factory/rg"
138
139 # Create wrapper script in /usr/bin
140 # This ensures the bundled ripgrep is used only for droid
141 cat > "$pkgdir/usr/bin/droid" <<'EOF'
142#!/bin/sh
143# Factory CLI wrapper
144# Ensures bundled ripgrep is preferred for this tool
145export PATH="/usr/lib/factory:$PATH"
146exec /usr/lib/factory/droid "$@"
147EOF
148
149 chmod 755 "$pkgdir/usr/bin/droid"
150
151 # Install license if available (create placeholder for now)
152 install -dm755 "$pkgdir/usr/share/licenses/$pkgname"
153 cat > "$pkgdir/usr/share/licenses/$pkgname/LICENSE" <<EOF
154Factory CLI License
155
156Please visit https://factory.ai for license information.
157EOF
158
159 msg2 "Factory CLI (droid) v$actual_version installed successfully"
160}
161

Scan history

Scanned at (UTC)SeverityRules
2026-08-03 00:08:14 MEDIUM 3
2026-08-02 00:16:08 MEDIUM 3
2026-08-01 00:11:18 MEDIUM 3
2026-07-31 00:14:10 MEDIUM 3
2026-07-30 00:17:23 MEDIUM 3
2026-07-29 00:25:53 MEDIUM 3
2026-07-28 00:07:28 MEDIUM 3
2026-07-27 00:24:32 MEDIUM 3
2026-07-26 00:07:32 MEDIUM 3
2026-07-25 00:13:44 MEDIUM 3
2026-07-24 00:02:28 MEDIUM 3
2026-07-23 00:14:47 MEDIUM 3
2026-07-22 00:29:32 MEDIUM 3
2026-07-21 00:24:15 MEDIUM 3
2026-07-20 00:19:49 MEDIUM 3
2026-07-19 00:17:08 MEDIUM 3
2026-07-18 00:14:48 MEDIUM 3
2026-07-17 00:06:16 MEDIUM 3
2026-07-16 00:05:41 MEDIUM 3
2026-07-15 00:09:25 MEDIUM 3

Report a package

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

0 / 4000
Your suggestion