Repository navigation
Expand file tree
/
Copy pathinstall.sh
More file actions
executable file
·169 lines (150 loc) · 6.36 KB
/
Copy pathinstall.sh
File metadata and controls
executable file
·169 lines (150 loc) · 6.36 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
#!/bin/sh
# pentesterflow online installer (macOS / Linux).
#
# curl -fsSL https://raw.githubusercontent.com/PentesterFlow/agent/main/install.sh | sh
#
# Downloads the standalone binary for your OS/arch from the latest GitHub
# release, verifies its SHA-256, and installs it to ~/.local/bin.
#
# Environment overrides:
# PENTESTERFLOW_VERSION=v0.1.0 pin a release tag (default: latest)
# PENTESTERFLOW_INSTALL_DIR=/path install location (default: ~/.local/bin)
# PENTESTERFLOW_SKILLS_DIR=/path shipped skills location (default: ~/.pentesterflow/builtin-skills)
# PENTESTERFLOW_SKIP_SKILLS=1 install binary only
# PENTESTERFLOW_SKIP_CHECKSUM=1 install without SHA-256 verification (unsafe)
set -eu
REPO="${PENTESTERFLOW_REPO:-PentesterFlow/agent}"
BIN="pentesterflow"
info() { printf '%s\n' "$*" >&2; }
err() {
printf 'error: %s\n' "$*" >&2
exit 1
}
# --- downloader (curl or wget) -------------------------------------------
if command -v curl >/dev/null 2>&1; then
dl() { curl -fL --proto '=https' --tlsv1.2 -sS "$1" -o "$2"; }
dl_stdout() { curl -fL --proto '=https' --tlsv1.2 -sS "$1"; }
elif command -v wget >/dev/null 2>&1; then
dl() { wget -q -O "$2" "$1"; }
dl_stdout() { wget -q -O- "$1"; }
else
err "need either curl or wget installed"
fi
# --- detect platform ------------------------------------------------------
os=$(uname -s)
case "$os" in
Darwin) os=darwin ;;
Linux) os=linux ;;
*) err "unsupported OS '$os' — on Windows use install.ps1 instead" ;;
esac
arch=$(uname -m)
case "$arch" in
arm64 | aarch64) arch=arm64 ;;
x86_64 | amd64) arch=x64 ;;
*) err "unsupported architecture '$arch'" ;;
esac
asset="${BIN}-${os}-${arch}"
ver="${PENTESTERFLOW_VERSION:-latest}"
case "$ver" in
latest | v*) ;;
[0-9]*) ver="v${ver}" ;;
esac
if [ "$ver" = "latest" ]; then
base="https://github.com/${REPO}/releases/latest/download"
else
base="https://github.com/${REPO}/releases/download/${ver}"
fi
tmp=$(mktemp -d)
trap 'rm -rf "$tmp"' EXIT INT TERM
# --- download -------------------------------------------------------------
info "downloading ${asset} (${ver})..."
dl "${base}/${asset}" "${tmp}/${asset}" || err "download failed: ${base}/${asset}"
[ -s "${tmp}/${asset}" ] || err "downloaded asset is empty: ${base}/${asset}"
# --- verify checksum (required; fail-closed) -----------------------------
# A self-updating binary must not install an unverified download. Any failure
# to verify is fatal. Set PENTESTERFLOW_SKIP_CHECKSUM=1 to override (e.g. an
# air-gapped mirror you trust by other means).
if [ "${PENTESTERFLOW_SKIP_CHECKSUM:-}" = "1" ]; then
info "warning: PENTESTERFLOW_SKIP_CHECKSUM=1 set — installing WITHOUT checksum verification"
else
dl_stdout "${base}/SHA256SUMS" >"${tmp}/SHA256SUMS" 2>/dev/null ||
err "could not download SHA256SUMS from ${base} — refusing to install an unverified binary (set PENTESTERFLOW_SKIP_CHECKSUM=1 to override)"
[ -s "${tmp}/SHA256SUMS" ] ||
err "downloaded SHA256SUMS is empty — refusing to install an unverified binary"
want=$(awk -v a="$asset" '$2==a {print $1}' "${tmp}/SHA256SUMS" | head -n1)
[ -n "$want" ] ||
err "SHA256SUMS does not list ${asset} — refusing to install an unverified binary"
if command -v sha256sum >/dev/null 2>&1; then
got=$(sha256sum "${tmp}/${asset}" | awk '{print $1}')
elif command -v shasum >/dev/null 2>&1; then
got=$(shasum -a 256 "${tmp}/${asset}" | awk '{print $1}')
else
err "no sha256sum/shasum tool found — cannot verify the download (set PENTESTERFLOW_SKIP_CHECKSUM=1 to override)"
fi
[ "$got" = "$want" ] ||
err "checksum mismatch for ${asset} (expected ${want}, got ${got})"
info "checksum ok"
fi
# --- install --------------------------------------------------------------
if [ -n "${PENTESTERFLOW_INSTALL_DIR:-}" ]; then
dir="$PENTESTERFLOW_INSTALL_DIR"
else
[ -n "${HOME:-}" ] || err "HOME is not set; set PENTESTERFLOW_INSTALL_DIR explicitly"
dir="$HOME/.local/bin"
fi
mkdir -p "$dir"
chmod 0755 "${tmp}/${asset}"
dest="${dir}/${BIN}"
staged="${dir}/.${BIN}.tmp.$$"
rm -f "$staged"
cp "${tmp}/${asset}" "$staged" || err "failed to stage binary in ${dir}"
chmod 0755 "$staged"
mv -f "$staged" "$dest" || err "failed to install binary to ${dest}"
# macOS: drop the quarantine attribute so Gatekeeper doesn't block the
# unsigned binary on first run.
if [ "$os" = darwin ] && command -v xattr >/dev/null 2>&1; then
xattr -d com.apple.quarantine "$dest" 2>/dev/null || true
fi
info "installed ${BIN} -> ${dest}"
# --- install shipped skills ----------------------------------------------
if [ "${PENTESTERFLOW_SKIP_SKILLS:-}" != "1" ]; then
if [ -n "${PENTESTERFLOW_SKILLS_DIR:-}" ]; then
skills_dir="$PENTESTERFLOW_SKILLS_DIR"
else
[ -n "${HOME:-}" ] || err "HOME is not set; set PENTESTERFLOW_SKILLS_DIR explicitly"
skills_dir="$HOME/.pentesterflow/builtin-skills"
fi
if command -v tar >/dev/null 2>&1; then
archive_ref="$ver"
[ "$archive_ref" = "latest" ] && archive_ref="latest"
archive_url="https://github.com/${REPO}/archive/refs/tags/${archive_ref}.tar.gz"
info "installing shipped skills -> ${skills_dir}..."
if ! dl "$archive_url" "${tmp}/source.tar.gz"; then
archive_url="https://github.com/${REPO}/archive/refs/heads/main.tar.gz"
dl "$archive_url" "${tmp}/source.tar.gz" || err "download failed: ${archive_url}"
fi
mkdir -p "${tmp}/source"
tar -xzf "${tmp}/source.tar.gz" -C "${tmp}/source" || err "failed to extract skills archive"
skills_src=$(find "${tmp}/source" -type d -path "*/skills" | head -n1)
if [ -n "$skills_src" ] && [ -d "$skills_src" ]; then
skills_stage="${skills_dir}.tmp.$$"
rm -rf "$skills_stage"
mkdir -p "$skills_stage"
cp -R "$skills_src"/. "$skills_stage"/ || err "failed to stage shipped skills"
rm -rf "$skills_dir"
mkdir -p "$(dirname "$skills_dir")"
mv "$skills_stage" "$skills_dir" || err "failed to install shipped skills"
info "installed shipped skills -> ${skills_dir}"
else
info "warning: skills directory not found in source archive — skipping skills install"
fi
else
info "warning: tar not found — skipping skills install"
fi
fi
case ":${PATH:-}:" in
*":${dir}:"*) : ;;
*) info "note: ${dir} is not on your PATH — add this to your shell profile:
export PATH=\"${dir}:\$PATH\"" ;;
esac
"$dest" --version 2>/dev/null || info "run '${BIN} --help' to get started"