agenshield 0.11.4 → 0.11.5-beta.542
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/agenshield +171 -13
- package/package.json +1 -1
package/bin/agenshield
CHANGED
|
@@ -87,6 +87,16 @@ find_installed() {
|
|
|
87
87
|
return 0
|
|
88
88
|
done
|
|
89
89
|
IFS="$OLDIFS"
|
|
90
|
+
# The macOS .pkg installs the real CLI at /Library/AgenShield/bin and only
|
|
91
|
+
# symlinks it onto PATH as /usr/local/bin/agenshield. A half-finished uninstall
|
|
92
|
+
# can delete that symlink while the binary itself survives — the PATH scan
|
|
93
|
+
# above then misses a perfectly runnable uninstaller. Check the canonical .pkg
|
|
94
|
+
# location directly so `uninstall` (and every other command) delegates to the
|
|
95
|
+
# real CLI instead of falling back to residue cleanup / bootstrap.
|
|
96
|
+
if [ -x "/Library/AgenShield/bin/agenshield" ]; then
|
|
97
|
+
echo "/Library/AgenShield/bin/agenshield"
|
|
98
|
+
return 0
|
|
99
|
+
fi
|
|
90
100
|
return 1
|
|
91
101
|
}
|
|
92
102
|
|
|
@@ -122,11 +132,143 @@ print_manual_cleanup_hint() {
|
|
|
122
132
|
echo " sudo rm -rf /Library/AgenShield /opt/agenshield /Applications/AgenShield.app" >&2
|
|
123
133
|
echo " rm -rf \"\$HOME/.agenshield\"" >&2
|
|
124
134
|
echo " rm -f \"\$HOME/Library/LaunchAgents/com.frontegg.AgenShield.\"*.plist" >&2
|
|
135
|
+
echo " sudo security delete-certificate -c \"AgenShield CA\" /Library/Keychains/System.keychain" >&2
|
|
125
136
|
echo " launchctl unsetenv NODE_EXTRA_CA_CERTS; unset NODE_EXTRA_CA_CERTS" >&2
|
|
126
137
|
echo " Then fully quit & reopen your terminal and GUI apps (Cursor, Claude Desktop, VS Code)" >&2
|
|
127
138
|
echo " so they drop the stale NODE_EXTRA_CA_CERTS value." >&2
|
|
128
139
|
}
|
|
129
140
|
|
|
141
|
+
# ── macOS: remove AgenShield residue in-process (no reinstall) ──────────────
|
|
142
|
+
# Reached by `uninstall` when no runnable CLI binary remains but artifacts do.
|
|
143
|
+
# The thorough uninstaller lives in the CLI binary, but on macOS the only
|
|
144
|
+
# published artifact is the full signed .pkg — there is no CLI-only download to
|
|
145
|
+
# bootstrap, and installing the .pkg would REINSTALL the whole product (daemon +
|
|
146
|
+
# ES/NE system extensions + LaunchDaemons) just to tear it down, via a GUI
|
|
147
|
+
# installer that lays nothing down synchronously. So we reproduce the residue
|
|
148
|
+
# cleanup the CLI uninstaller performs, in-process. This mirrors
|
|
149
|
+
# tools/build/test-uninstall.sh and ADDS the System-keychain CA removal a plain
|
|
150
|
+
# `rm` skips (a leftover trusted root is a MITM risk). Best-effort throughout:
|
|
151
|
+
# every step is guarded so one failure never aborts the rest. It mutates
|
|
152
|
+
# privileged system state, so we confirm first (skip with -f/--force; a
|
|
153
|
+
# non-interactive pipe prints the manual hint instead of destroying silently).
|
|
154
|
+
macos_residue_uninstall() {
|
|
155
|
+
_force=0
|
|
156
|
+
for _a in "$@"; do
|
|
157
|
+
case "$_a" in -f|--force) _force=1 ;; esac
|
|
158
|
+
done
|
|
159
|
+
|
|
160
|
+
echo "agenshield: no runnable binary found, but AgenShield artifacts remain on this Mac." >&2
|
|
161
|
+
echo " This removes AgenShield: app, daemon, system extensions, CA trust, config, and data." >&2
|
|
162
|
+
if [ "$_force" != "1" ]; then
|
|
163
|
+
if [ -t 0 ] && [ -t 1 ]; then
|
|
164
|
+
printf " Continue? [y/N] " >&2
|
|
165
|
+
read -r _ans || _ans=""
|
|
166
|
+
case "$_ans" in
|
|
167
|
+
y | Y | yes | YES) : ;;
|
|
168
|
+
*)
|
|
169
|
+
echo " Cancelled — nothing was removed." >&2
|
|
170
|
+
return 0
|
|
171
|
+
;;
|
|
172
|
+
esac
|
|
173
|
+
else
|
|
174
|
+
# Non-interactive and not --force: never destroy silently.
|
|
175
|
+
print_manual_cleanup_hint
|
|
176
|
+
return 0
|
|
177
|
+
fi
|
|
178
|
+
fi
|
|
179
|
+
|
|
180
|
+
# Privileged paths (/Library, /opt, the /usr/local symlink, the System
|
|
181
|
+
# keychain, system-domain launchd) need root; user-session paths do not.
|
|
182
|
+
SUDO=""
|
|
183
|
+
if [ "$(id -u)" -ne 0 ]; then SUDO="sudo"; fi
|
|
184
|
+
if [ -n "$SUDO" ] && ! sudo -v 2>/dev/null; then
|
|
185
|
+
echo "agenshield: administrator access is required to finish removing AgenShield." >&2
|
|
186
|
+
print_manual_cleanup_hint
|
|
187
|
+
return 0
|
|
188
|
+
fi
|
|
189
|
+
|
|
190
|
+
# The GUI console user owns the menubar app + the launchd session env vars.
|
|
191
|
+
_cuser="$(stat -f %Su /dev/console 2>/dev/null || echo '')"
|
|
192
|
+
_cuid=""
|
|
193
|
+
if [ -n "$_cuser" ] && [ "$_cuser" != "root" ]; then
|
|
194
|
+
_cuid="$(id -u "$_cuser" 2>/dev/null || echo '')"
|
|
195
|
+
fi
|
|
196
|
+
|
|
197
|
+
echo "agenshield: removing AgenShield…" >&2
|
|
198
|
+
|
|
199
|
+
# 1. Stop the daemon/helper + the menubar and dashboard apps.
|
|
200
|
+
$SUDO launchctl bootout system/com.frontegg.AgenShield.daemon 2>/dev/null || true
|
|
201
|
+
$SUDO launchctl bootout system/com.frontegg.AgenShield.privilege-helper 2>/dev/null || true
|
|
202
|
+
if [ -n "$_cuid" ]; then
|
|
203
|
+
$SUDO launchctl bootout "gui/$_cuid/com.frontegg.AgenShield.menubar" 2>/dev/null || true
|
|
204
|
+
fi
|
|
205
|
+
killall AgenShield 2>/dev/null || true
|
|
206
|
+
killall "AgenShield Dashboard" 2>/dev/null || true
|
|
207
|
+
|
|
208
|
+
# 2. Ask the app (while it still exists) to deactivate the ES + NE system
|
|
209
|
+
# extensions — the only non-developer-mode path. Bounded so a pending
|
|
210
|
+
# approval prompt can't hang the uninstall (macOS /bin/sh has no `timeout`);
|
|
211
|
+
# if it can't finish, deleting the app schedules removal on next reboot.
|
|
212
|
+
if [ -x "/Applications/AgenShield.app/Contents/MacOS/AgenShield" ] && [ -n "$_cuid" ]; then
|
|
213
|
+
($SUDO launchctl asuser "$_cuid" sudo -u "$_cuser" \
|
|
214
|
+
/Applications/AgenShield.app/Contents/MacOS/AgenShield --uninstall-all >/dev/null 2>&1) &
|
|
215
|
+
_deact=$!
|
|
216
|
+
_i=0
|
|
217
|
+
while [ "$_i" -lt 20 ]; do
|
|
218
|
+
kill -0 "$_deact" 2>/dev/null || break
|
|
219
|
+
sleep 1
|
|
220
|
+
_i=$((_i + 1))
|
|
221
|
+
done
|
|
222
|
+
kill -9 "$_deact" 2>/dev/null || true
|
|
223
|
+
fi
|
|
224
|
+
|
|
225
|
+
# 3. Remove the AgenShield CA from the System keychain (sweep by CN, delete by
|
|
226
|
+
# SHA-1) — mirrors the CLI's removeInstalledCaTrust.
|
|
227
|
+
$SUDO /usr/bin/security find-certificate -a -Z -c "AgenShield" /Library/Keychains/System.keychain 2>/dev/null |
|
|
228
|
+
while IFS= read -r _line; do
|
|
229
|
+
case "$_line" in
|
|
230
|
+
"SHA-1 hash: "*)
|
|
231
|
+
_sha1="${_line#SHA-1 hash: }"
|
|
232
|
+
$SUDO /usr/bin/security delete-certificate -Z "$_sha1" /Library/Keychains/System.keychain >/dev/null 2>&1 || true
|
|
233
|
+
;;
|
|
234
|
+
esac
|
|
235
|
+
done
|
|
236
|
+
|
|
237
|
+
# 4. Clear the node-ca-trust LaunchAgent + the NODE_EXTRA_CA_CERTS it sets in
|
|
238
|
+
# the user's launchd session (it points at the CA we just removed).
|
|
239
|
+
if [ -n "$_cuid" ]; then
|
|
240
|
+
$SUDO launchctl bootout "gui/$_cuid/com.frontegg.AgenShield.node-ca-trust" 2>/dev/null || true
|
|
241
|
+
if [ "$(id -u)" -eq 0 ]; then
|
|
242
|
+
launchctl asuser "$_cuid" /bin/launchctl unsetenv NODE_EXTRA_CA_CERTS 2>/dev/null || true
|
|
243
|
+
else
|
|
244
|
+
/bin/launchctl unsetenv NODE_EXTRA_CA_CERTS 2>/dev/null || true
|
|
245
|
+
fi
|
|
246
|
+
fi
|
|
247
|
+
|
|
248
|
+
# 5. Remove LaunchDaemon plists + every AgenShield user LaunchAgent.
|
|
249
|
+
$SUDO rm -f /Library/LaunchDaemons/com.frontegg.AgenShield.daemon.plist \
|
|
250
|
+
/Library/LaunchDaemons/com.frontegg.AgenShield.privilege-helper.plist 2>/dev/null || true
|
|
251
|
+
rm -f "$HOME/Library/LaunchAgents/com.frontegg.AgenShield."*.plist 2>/dev/null || true
|
|
252
|
+
|
|
253
|
+
# 6. Remove binaries, the app, root config, and per-user data.
|
|
254
|
+
$SUDO rm -f /usr/local/bin/agenshield 2>/dev/null || true
|
|
255
|
+
$SUDO rm -rf /Library/AgenShield /opt/agenshield /Applications/AgenShield.app 2>/dev/null || true
|
|
256
|
+
rm -rf "$HOME/.agenshield" 2>/dev/null || true
|
|
257
|
+
|
|
258
|
+
echo "" >&2
|
|
259
|
+
echo "agenshield: AgenShield removed." >&2
|
|
260
|
+
# `launchctl unsetenv` only affects future launches; already-running processes
|
|
261
|
+
# keep the stale value until restarted.
|
|
262
|
+
if [ -n "${NODE_EXTRA_CA_CERTS:-}" ]; then
|
|
263
|
+
echo " This shell still has NODE_EXTRA_CA_CERTS set — run: unset NODE_EXTRA_CA_CERTS" >&2
|
|
264
|
+
fi
|
|
265
|
+
echo " Fully quit & reopen your terminal and GUI apps (Cursor, Claude Desktop, VS Code)" >&2
|
|
266
|
+
echo " so they drop the stale NODE_EXTRA_CA_CERTS value." >&2
|
|
267
|
+
if /usr/bin/systemextensionsctl list 2>/dev/null | grep -q "com.frontegg.AgenShield"; then
|
|
268
|
+
echo " Reboot to finish removing the AgenShield system extensions." >&2
|
|
269
|
+
fi
|
|
270
|
+
}
|
|
271
|
+
|
|
130
272
|
# ── `install` → run the full installer with the user's args ─────────────────
|
|
131
273
|
# install.sh handles the macOS .pkg / Linux tarball download + checksum verify
|
|
132
274
|
# + enrollment (--token/--cloud-url/--org) + service setup.
|
|
@@ -147,27 +289,43 @@ if [ "${1:-}" = "install" ]; then
|
|
|
147
289
|
exec env AGENSHIELD_VERSION="$WRAPPER_VERSION" sh "$INSTALLER" "$@"
|
|
148
290
|
fi
|
|
149
291
|
|
|
150
|
-
# ── `uninstall` → delegate if installed, else
|
|
292
|
+
# ── `uninstall` → delegate if installed, else clean up residue ──────────────
|
|
151
293
|
# `npx agenshield uninstall` must remove AgenShield even after the binary itself
|
|
152
|
-
# is gone but system residue remains.
|
|
294
|
+
# is gone but system residue remains. Cases:
|
|
153
295
|
# 1. A runnable binary exists → delegate to it (the real, thorough uninstaller).
|
|
154
|
-
# 2. No binary, but residue
|
|
155
|
-
#
|
|
156
|
-
#
|
|
157
|
-
#
|
|
158
|
-
#
|
|
159
|
-
#
|
|
160
|
-
#
|
|
161
|
-
#
|
|
162
|
-
#
|
|
163
|
-
#
|
|
164
|
-
#
|
|
296
|
+
# 2. No binary, but residue, on macOS → remove the residue IN-PROCESS
|
|
297
|
+
# (macos_residue_uninstall). macOS publishes only the full signed .pkg, so
|
|
298
|
+
# there is no CLI-only artifact to bootstrap, and installing the .pkg would
|
|
299
|
+
# REINSTALL the entire product (daemon + ES/NE system extensions +
|
|
300
|
+
# LaunchDaemons) — via a GUI installer that lays nothing down synchronously —
|
|
301
|
+
# just to tear it down. Bootstrapping was the original design here; it
|
|
302
|
+
# surfaced the macOS "uninstall opened the installer GUI, then reported
|
|
303
|
+
# 'could not bootstrap the uninstaller'" bug. macos_residue_uninstall covers
|
|
304
|
+
# the keychain CA, system extensions, the node-ca-trust LaunchAgent + its
|
|
305
|
+
# NODE_EXTRA_CA_CERTS env, LaunchDaemons, dirs, and the dangling symlink.
|
|
306
|
+
# 3. No binary, but residue, on other platforms → bootstrap the CLI-only
|
|
307
|
+
# tarball (--skip-services) and run the REAL uninstaller; on a download
|
|
308
|
+
# failure (offline / no published release), print manual cleanup steps.
|
|
309
|
+
# 4. No binary, no residue → genuinely nothing to do; report and exit 0.
|
|
310
|
+
# Acting only when residue is present means a successful uninstall removes the
|
|
311
|
+
# residue, so a second run lands in case 4 and exits cleanly — no churn.
|
|
165
312
|
if [ "${1:-}" = "uninstall" ]; then
|
|
166
313
|
BIN="$(find_installed || true)"
|
|
167
314
|
if [ -n "$BIN" ]; then
|
|
168
315
|
exec "$BIN" "$@"
|
|
169
316
|
fi
|
|
170
317
|
if agenshield_residue_present; then
|
|
318
|
+
# No runnable CLI binary, but AgenShield residue remains. macOS cannot
|
|
319
|
+
# bootstrap the thorough uninstaller — the only published artifact is the
|
|
320
|
+
# full signed .pkg, and installing it would REINSTALL the whole product (via
|
|
321
|
+
# an interactive GUI installer that lays nothing down synchronously) just to
|
|
322
|
+
# remove it. So remove the residue in-process here. Other platforms publish a
|
|
323
|
+
# CLI-only tarball, so they can lay the binary down and run the real
|
|
324
|
+
# uninstaller below.
|
|
325
|
+
if [ "$OS" = "darwin" ]; then
|
|
326
|
+
macos_residue_uninstall "$@"
|
|
327
|
+
exit 0
|
|
328
|
+
fi
|
|
171
329
|
if [ ! -f "$INSTALLER" ]; then
|
|
172
330
|
echo "agenshield: leftover AgenShield artifacts detected, but the bundled installer is missing." >&2
|
|
173
331
|
print_manual_cleanup_hint
|