With the rise in popularity of bug bounty hunting, there’s been a lot of great tools developed. ProjectDiscovery‘s suite of tools and contributions made by Tomnomnom certainly come to mind.
With the amount of tools, however, comes the complexity of managing them: keeping them up to date, making sure dependencies are installed, keeping your bounty tools separate from personal projects, and managing the clutter that comes with having tons of tools.
The solution: Docker. Docker is a platform for running and managing containers. You can think of a container as a light-weight VM. That light-weight comes from sharing resources with your host machine instead of virtualizing lower-level functions (the kernel for example).
With Docker, you can package all of your bug bounty tools inside of a container, which allows for:
- Portability – your tools are guaranteed to run anywhere (so long as docker is installed).
- Isolation – everything lives inside of the container. You don’t have to install/maintain unnecessary bloat on your host machine to get all of your tools working.
- Easy cleanup – once the container is removed, the tools and their dependencies go with it. Getting everything up and running again is as easy as re-building/pulling the container.
- Easy updates – If you do your setup right, updating all of your tools is as easy as removing then rebuilding the container. You don’t have to worry about anything else!
I’m sure I sold you on the idea. Let’s get into how to practically do it!
Containerizing your toolkit
1. Setting the foundation
I’m not going into how to install Docker or how to manage containers. They have their documentation I highly recommend reading if you’re new to Docker.
For now, all you need to get started is a Dockerfile in a directory like this:
$ mkdir recon-toolkit-demo
$ cd recon-toolkit-demo
$ touch DockerfileNow, we can start adding to the Dockerfile.
Every Dockerfile starts with a base layer using the FROM keyword. For my toolkit, I’m choosing to use a variant of Debian, for it’s ease of use and wide support. But, feel free to choose your favorite OS (as long as it’s unix-based 🙂 ).
FROM debian:bookworm-slimThis is all I need to build and run the container:
$ docker build . -t recon-toolkit-demo
$ docker run -it recon-toolkit-demoAnd just like that, you have your own Linux shell:
root@26e0023b58e6:/# ls
bin dev home lib64 mnt proc run srv tmp var
boot etc lib media opt root sbin sys usr
root@26e0023b58e6:/# Pretty cool!
2. Installing tools
For demo purposes, I’m only going to install one tool. Everyone’s favorite sub-domain enumeration script: subfinder.
Reading the install instructions, I first need to install go
But before I even do that, I need curl so I can download go:
root@26e0023b58e6:/# apt-get update && apt-get install curl -yNow that that’s taken care of, I can run through go’s install steps
root@26e0023b58e6:/# curl 'https://dl.google.com/go/go1.25.6.linux-amd64.tar.gz' -O
root@26e0023b58e6:/# rm -rf /usr/local/go && tar -C /usr/local -xzf go1.25.6.linux-amd64.tar.gz
root@26e0023b58e6:/# export PATH=$PATH:/usr/local/go/bin
root@26e0023b58e6:/# go version
go version go1.25.6 linux/amd64
Now we can install subfinder:
root@26e0023b58e6:/# go install -v github.com/projectdiscovery/subfinder/v2/cmd/subfinder@latest
root@26e0023b58e6:/# export PATH=$PATH:/root/go/bin/
root@26e0023b58e6:/# subfinder --version
[INF] Current Version: v2.12.0
[INF] Subfinder Config Directory: /root/.config/subfinderGreat! Now we have everything we need.
The only problem is, when I re-build the container, none of the tools we installed will be there.
To solve this, we just have to translate our manual install steps (which we verified work) into the Dockerfile:
FROM debian:bookworm-slim
RUN apt-get update && apt-get upgrade -y && apt-get install curl -y
# go install
RUN curl 'https://dl.google.com/go/go1.25.6.linux-amd64.tar.gz' -O
RUN rm -rf /usr/local/go && tar -C /usr/local -xzf go1.25.6.linux-amd64.tar.gz
ENV PATH=$PATH:/usr/local/go/bin
# subfinder install
RUN go install -v github.com/projectdiscovery/subfinder/v2/cmd/subfinder@latest
ENV PATH=$PATH:/root/go/bin/With the exception of ENV (which is pretty self-explanatory), everything looks the same as our manual setup steps.
Now we can build the container again and run it to verify everything works:
$ docker build . -t recon-toolkit-demo
$ docker run -it recon-toolkit-demo
root@d351c95c3742:/# subfinder --version
[INF] Current Version: v2.12.0
[INF] Subfinder Config Directory: /root/.config/subfinderCool!
Tip: Use docker run -it to debug and manually verify if something goes wrong.
3. Install configurations
subfinder is great out-of-box, but even better when you add API keys.
To do this, you can specify a provider-config.yaml that is stored in by default in $CONFIG/subfinder/provider-config.yaml.
To achieve this in docker we can use the COPY directive to transfer the file from our working directory to the container like so:
$ touch provider-config.yaml
$ echo 'COPY provider-config.yaml /root/.config/subfinder/provider-config.yaml' >> DockerfileOf course, passing an empty provider-config.yaml won’t get you anywhere. You would need to specify your own keys. But this is how you would transfer config files into the container.
4. Binding to a workspace
Usually when I do my bounty recon, I like to keep all of my recon files on my host machine. That way, they’re persisted and I can process them using other tools I have installed on my machine.
To do this, you can create a dedicated directory on the container for bounty recon files by adding this to the Dockerfile:
RUN mkdir /bountyThen, you can run the container (after re-building) with the --mount argument:
$ docker run -it --mount type=bind,source=/path/to/local/bounty_dir,target=/bounty recon-toolkit-demo Now, if you cd into the /bounty directory on the container, you should see your host’s system files!
From there, you can run subfinder on any of your workspace files. And, if you pipe the output to a file, it will be saved on your local. The same behavior as if you had subfinder installed and running on your host!
5. Automating
Now we can run subfinder using docker manually, but eventually, you’re going to want to automate runs. Especially as your toolkit grows.
To script this process, you can write a shell script:
#!/bin/bash
cat wildcards.txt | subfinder -o subdomains.txt
and then COPY it over as we did earlier with provider-config.yaml:
COPY recon.sh .
RUN chmod +x recon.shNow we can run the script on our bounty files:
docker run -it --mount type=bind,source=/path/to/local/bounty_dir,target=/bounty recon-toolkit-demo ./recon.shConclusion
Now you should be able to use docker package your bug bounty tools into a container.
From here, you may want to:
- Add more tools
- Publish your container to Dockerhub
- Add wrapper scripts for ease of use
You can checkout my implementation on my github.
Happy hacking!
