Repository navigation
Expand file tree
/
Copy pathDockerfile
More file actions
243 lines (212 loc) · 11.6 KB
/
Copy pathDockerfile
File metadata and controls
243 lines (212 loc) · 11.6 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
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
# syntax=docker/dockerfile:1.7
#
# Pentest Swarm AI — single-image distribution.
#
# Three-stage build:
# 1. swarm-build — compiles the pentestswarm binary
# 2. tools-build — installs the Go-based security tools (subfinder, nuclei,
# httpx, naabu, etc.) into a single bin directory
# 3. runtime — slim Debian with apt + binary security tools, plus
# the artefacts copied from stages 1 and 2
#
# Why this shape:
# - Stages 1 + 2 keep the Go toolchain (~150 MB) out of the final image.
# - The runtime layer holds only the binaries the operator actually invokes.
# - Final image is ~700 MB — large by web-app standards, normal for a
# pentesting toolbox image (Kali base is ~3 GB for comparison).
#
# Usage:
# docker build -t pentest-swarm-ai .
# docker run --rm -e PENTESTSWARM_ORCHESTRATOR_API_KEY=$KEY \
# -v "$PWD/reports:/reports" \
# pentest-swarm-ai scan example.com
# ───────────────────────────────────────────────────────────────────────────
# Stage 1: build the swarm binary
# ───────────────────────────────────────────────────────────────────────────
FROM golang:1.27-bookworm AS swarm-build
WORKDIR /src
# GOTOOLCHAIN=auto lets Go fetch the toolchain go.mod asks for (>= 1.26) when
# the base image is older, so a go.mod bump never needs a matching base re-tag.
ENV GOTOOLCHAIN=auto
# Layer the build so dependency downloads are cached separately from the
# source tree — incremental rebuilds only repay the compile step.
COPY go.mod go.sum ./
RUN go mod download
COPY . .
# CGO is on because some adapters (e.g. naabu's libpcap link) need it.
# -s -w strips debug info to keep the binary small (~30 MB).
RUN CGO_ENABLED=1 go build \
-trimpath \
-ldflags="-s -w -X main.version=docker -X main.commit=$(git rev-parse --short HEAD 2>/dev/null || echo unknown) -X main.date=$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
-o /out/pentestswarm \
./cmd/pentestswarm
# ───────────────────────────────────────────────────────────────────────────
# Stage 2: build the Go-based security tools
# ───────────────────────────────────────────────────────────────────────────
# A separate stage so we can throw away the Go toolchain at the end. Each
# `go install` writes to /out/bin; the runtime stage scoops up that whole
# directory into /usr/local/bin.
FROM golang:1.27-bookworm AS tools-build
# libpcap-dev is required at COMPILE time for naabu's raw-socket port scan.
# The runtime stage installs libpcap0.8 for the runtime ABI.
RUN apt-get update && apt-get install -y --no-install-recommends \
libpcap-dev \
git \
&& rm -rf /var/lib/apt/lists/*
# GOTOOLCHAIN=auto lets Go fetch a newer toolchain on-demand when a tool's
# go.mod requires it. Without this, a single upstream bump (e.g. gowitness
# requiring Go 1.26) would force us to re-tag the base image. Auto handles
# the whole class of "tool X now needs Go Y.Z" failures transparently.
ENV GOTOOLCHAIN=auto
ENV GOBIN=/out/bin
RUN mkdir -p /out/bin
# ProjectDiscovery toolchain (8 tools)
RUN go install github.com/projectdiscovery/subfinder/v2/cmd/subfinder@latest \
&& go install github.com/projectdiscovery/dnsx/cmd/dnsx@latest \
&& go install github.com/projectdiscovery/httpx/cmd/httpx@latest \
&& go install github.com/projectdiscovery/naabu/v2/cmd/naabu@latest \
&& go install github.com/projectdiscovery/katana/cmd/katana@latest \
&& go install github.com/lc/gau/v2/cmd/gau@latest \
&& go install github.com/projectdiscovery/nuclei/v3/cmd/nuclei@latest \
&& go install github.com/ffuf/ffuf/v2@latest
# Evidence + reporting helpers
RUN go install github.com/sensepost/gowitness@latest
# Dalfox — reflected/DOM XSS finder (Go module). Adapter at
# internal/tools/dalfox.go (2.1.9); registered in NewCoordinator.
RUN go install github.com/hahwul/dalfox/v2@latest
# Interactsh-client — out-of-band callback listener (Go module). Adapter
# at internal/tools/interactsh.go (2.1.26); enables blind injection
# detection across XSS/SSRF/RCE/SQLi by capturing DNS/HTTP/SMTP/LDAP
# interactions from server-controlled subdomains.
RUN go install github.com/projectdiscovery/interactsh/cmd/interactsh-client@latest
# crlfuzz — CRLF injection fuzzer (Go module). Adapter at
# internal/tools/crlfuzz.go (2.1.14).
RUN go install github.com/dwisiswant0/crlfuzz/cmd/crlfuzz@latest
# Gxss — fast reflected-XSS pre-screener (Go module). Adapter at
# internal/tools/gxss.go (2.1.27); pairs with dalfox for confirmation.
RUN go install github.com/KathanP19/Gxss@latest
# Amass is no longer in Debian's main repo — install from upstream Go module.
RUN go install -v github.com/owasp-amass/amass/v4/...@master
# ───────────────────────────────────────────────────────────────────────────
# Stage 3: runtime
# ───────────────────────────────────────────────────────────────────────────
FROM debian:bookworm-slim AS runtime
ENV DEBIAN_FRONTEND=noninteractive
# System security tools (apt-installable):
# nmap — port + service scanner
# sqlmap — SQL-injection exploitation
# gobuster — content discovery (alternative to ffuf)
# dnsutils — dig/nslookup, used by some adapters
# libpcap0.8 — naabu runtime dependency
# ca-certificates, curl, git — basic networking + tool downloads
# chromium — gowitness needs a headless browser; without it screenshot
# capture silently no-ops (we want it to work out of the box)
#
# Note: amass AND nikto were dropped from Debian's main repo as of Bookworm;
# amass installs via `go install` in the tools-build stage, nikto from
# upstream git below (see the nikto block).
RUN apt-get update && apt-get install -y --no-install-recommends \
nmap \
sqlmap \
gobuster \
whatweb \
dnsutils \
libpcap0.8 \
testssl.sh \
ca-certificates \
curl \
git \
python3 \
python3-pip \
python3-venv \
chromium \
&& rm -rf /var/lib/apt/lists/*
# Semgrep + arjun via pip in a venv (Debian's PEP 668 forbids
# system-wide pip). Arjun (2.1.13, internal/tools/arjun.go) needs a
# Python runtime; bundling it in the same venv keeps the layer small.
# Drop the venv's `httpx` script — semgrep pulls in the python-httpx
# library which installs a CLI of the same name, shadowing the
# ProjectDiscovery `httpx` we want on PATH (the recon tool, not the
# HTTP client). Reported in #13.
RUN python3 -m venv /opt/venv \
&& /opt/venv/bin/pip install --no-cache-dir \
semgrep arjun checkov \
prowler pacu scoutsuite cloudsplaining \
kube-hunter droopescan \
wafw00f \
bloodhound \
&& rm -f /opt/venv/bin/httpx
ENV PATH="/opt/venv/bin:${PATH}"
# crackmapexec (2.1.18) is EOL upstream; its maintained successor NetExec
# (nxc) is NOT published to PyPI (`pip install netexec` 404s), so install it
# from upstream git into its OWN venv — its pinned deps (impacket, etc.)
# conflict with the shared venv above — and symlink the CLI onto PATH. The
# adapter (internal/tools/crackmapexec.go) resolves to `nxc` at run time.
# bloodhound-python (2.1.19) — the Linux AD collector — comes from the
# `bloodhound` pip package above; internal/tools/bloodhound.go drives it.
RUN python3 -m venv /opt/nxc \
&& /opt/nxc/bin/pip install --no-cache-dir \
git+https://github.com/Pennyw0rth/NetExec.git \
&& ln -s /opt/nxc/bin/nxc /usr/local/bin/nxc
# dotdotpwn (2.1.28) — path-traversal fuzzer, a Perl tool not packaged in
# Debian main. Clone the release and its CPAN deps, then symlink onto PATH.
# Adapter at internal/tools/dotdotpwn.go.
RUN apt-get update && apt-get install -y --no-install-recommends \
perl \
libswitch-perl \
libwww-perl \
libnet-tftp-perl \
libterm-readkey-perl \
libio-socket-ssl-perl \
&& git clone --depth 1 https://github.com/wireghoul/dotdotpwn.git /opt/dotdotpwn \
&& chmod +x /opt/dotdotpwn/dotdotpwn.pl \
&& ln -s /opt/dotdotpwn/dotdotpwn.pl /usr/local/bin/dotdotpwn \
&& rm -rf /var/lib/apt/lists/*
# nikto (2.1.x) — web-server misconfig / signature scanner. Dropped from
# Debian bookworm's main repo, so install from upstream git — another Perl
# tool, same shape as dotdotpwn. A wrapper (not a bare symlink) is used so
# nikto.pl resolves its plugins/config relative to its real /opt path.
# Adapter at internal/tools/nikto.go.
RUN apt-get update && apt-get install -y --no-install-recommends \
perl \
libnet-ssleay-perl \
&& git clone --depth 1 https://github.com/sullo/nikto.git /opt/nikto \
&& printf '#!/bin/sh\nexec perl /opt/nikto/program/nikto.pl "$@"\n' > /usr/local/bin/nikto \
&& chmod +x /usr/local/bin/nikto \
&& rm -rf /var/lib/apt/lists/*
# Trufflehog: pinned release binary (not the curl|sh installer — auditability).
ARG TRUFFLEHOG_VERSION=3.83.7
RUN curl -sSfL "https://github.com/trufflesecurity/trufflehog/releases/download/v${TRUFFLEHOG_VERSION}/trufflehog_${TRUFFLEHOG_VERSION}_linux_amd64.tar.gz" \
| tar -xz -C /usr/local/bin trufflehog
# Gitleaks: pinned release binary.
ARG GITLEAKS_VERSION=8.21.2
RUN curl -sSfL "https://github.com/gitleaks/gitleaks/releases/download/v${GITLEAKS_VERSION}/gitleaks_${GITLEAKS_VERSION}_linux_x64.tar.gz" \
| tar -xz -C /usr/local/bin gitleaks
# Feroxbuster: pinned release binary. Fast recursive content discovery
# (Rust). Adapter at internal/tools/feroxbuster.go; registered in
# NewCoordinator.
ARG FEROXBUSTER_VERSION=2.13.1
RUN curl -sSfL "https://github.com/epi052/feroxbuster/releases/download/v${FEROXBUSTER_VERSION}/x86_64-linux-feroxbuster.tar.gz" \
| tar -xz -C /usr/local/bin feroxbuster \
&& chmod +x /usr/local/bin/feroxbuster
# Pull in the Go-based tools from stage 2 + the swarm binary from stage 1.
COPY --from=tools-build /out/bin/. /usr/local/bin/
COPY --from=swarm-build /out/pentestswarm /usr/local/bin/pentestswarm
# Pre-cache nuclei templates so the first scan doesn't pay the download cost.
# `|| true` because template fetch occasionally rate-limits on the
# unauthenticated GitHub API and we don't want that to break the build.
RUN nuclei -update-templates -silent 2>/dev/null || true
# Non-root user for the actual scan. Naabu's raw-socket scan needs CAP_NET_RAW
# which docker grants by default to root inside the container; if you run as
# non-root and need raw sockets, pass --cap-add=NET_RAW.
RUN useradd -ms /bin/bash pentester \
&& mkdir -p /reports /home/pentester/.pentestswarm \
&& chown -R pentester:pentester /reports /home/pentester
USER pentester
# Reports land here; mount a host directory at /reports to persist them.
WORKDIR /reports
# `pentestswarm` as the entrypoint means `docker run <image> scan <target>`
# works just like the host install. Default to --help so a bare `docker run`
# is informative rather than failing.
ENTRYPOINT ["pentestswarm"]
CMD ["--help"]