S3Scanner is an open-source reconnaissance tool, originally created by Dan Salmon (sa7mon), purpose-built for discovering and auditing Amazon S3 buckets (and S3-API-compatible storage such as DigitalOcean Spaces, Wasabi, and Backblaze B2). It is one of the most widely used tools in the bug bounty and penetration testing community specifically for identifying misconfigured, publicly accessible cloud storage — a vulnerability class responsible for numerous high-profile data breaches over the years (exposed customer PII, source code, credentials, backups, and internal documents).
Unlike CloudBrute, which enumerates across many cloud providers and resource types, S3Scanner is laser-focused on S3 buckets, and offers deeper bucket-level inspection once a bucket name is known or guessed:
- Bucket existence check — determines whether a given bucket name exists at all.
- Permission enumeration — checks specific ACL permissions:
READ(list objects),WRITE(upload objects),READ_ACP(read bucket ACL),WRITE_ACP(modify bucket ACL), andFULL_CONTROL. - Bucket dumping — downloads the full contents of a bucket if
READaccess is available. - Multi-region support — automatically detects the correct AWS region a bucket lives in.
- Compatible storage providers — can also test buckets hosted on DigitalOcean Spaces, Google Cloud Storage (S3-compatible endpoints), and other S3-API-compatible services.
S3Scanner is typically used as a follow-up tool after a bucket name has been discovered — either through a wordlist-based brute-force scan (its own built-in scan mode), OSINT (e.g., found in JavaScript source code, GitHub commits, or DNS records), or the output of a tool like CloudBrute.
Installation
Method 1: Go install (recommended, S3Scanner v3+ is written in Go)
sudo apt install golang-go -y
go install github.com/sa7mon/s3scanner@latest
export PATH=$PATH:$(go env GOPATH)/bin
Method 2: Download pre-compiled binary from GitHub Releases
wget https://github.com/sa7mon/S3Scanner/releases/latest/download/s3scanner_linux_amd64.tar.gz
tar -xzf s3scanner_linux_amd64.tar.gz
chmod +x s3scanner
sudo mv s3scanner /usr/local/bin/
Method 3: Build from source
git clone https://github.com/sa7mon/S3Scanner.git
cd S3Scanner
go build .
sudo mv s3scanner /usr/local/bin/
Method 4 (legacy Python version, for older references):
git clone https://github.com/sa7mon/S3Scanner.git
cd S3Scanner
pip install -r requirements.txt
python3 s3scanner.py --help
Verify installation:
s3scanner version
Expected output:
s3scanner version 3.1.0
Syntax
s3scanner [command] [flags]
Main subcommands:
s3scanner scan -f <bucket_list_file> # Scan a list of bucket names
s3scanner dump -b <bucket_name> # Dump contents of a specific bucket
Complete Command-Line Options Reference
Global Commands
s3scanner scan Scan one or more bucket names for existence and permissions
s3scanner dump Download ("dump") the contents of an accessible bucket
s3scanner version Print version information
s3scanner help Display help menu
scan Subcommand Flags
-f, --bucket-file FILE File containing a list of bucket names to check (one per line)
-b, --bucket NAME Scan a single bucket name directly
--json Output results in JSON format
--include-closed Include non-existent/closed buckets in output (default: only report found buckets)
--threads N Number of concurrent scanning threads (default: 10)
--endpoint-url URL Use a custom S3-compatible endpoint (e.g., DigitalOcean Spaces)
--provider {aws,digitalocean,gcp,dreamhost,linode} Target a specific S3-compatible provider
--enumerate-ips Attempt to resolve and display associated IP addresses
--out FILE Save results to a specified output file
-v, --verbose Enable verbose logging
dump Subcommand Flags
-b, --bucket NAME Name of the bucket to dump
-o, --dump-dir DIR Local directory to save downloaded objects (default: ./buckets/)
--threads N Number of concurrent download threads (default: 10)
--endpoint-url URL Custom S3-compatible endpoint for the dump operation
--max-size SIZE Skip files larger than this size (e.g., 100MB)
--dry-run List objects that would be downloaded without actually downloading them
Miscellaneous
-h, --help Show help for the given command
--version Show version and exit
Basic Usage
s3scanner scan -f bucket_names.txt
Expected console output:
$ s3scanner scan -f bucket_names.txt
s3scanner v3.1.0 - Scanning 250 candidate bucket names...
[bucket_exists] acme-uploads | region: us-east-1 | perms: [READ, LIST]
[bucket_exists] acme-backups-2025 | region: eu-west-1 | perms: [READ, WRITE, LIST] <-- Critical!
[bucket_not_exist] acme-test-storage
[bucket_exists] acme-static-assets | region: us-east-1 | perms: [] (exists but no permissions)
Scan complete: 3 buckets found (1 with WRITE access), 247 not found, in 38 seconds
Practical Examples with Output
Example 1: Scan a wordlist of candidate bucket names
s3scanner scan -f candidates.txt
Scanning 500 bucket names...
[bucket_exists] acme-logs | region: us-east-1 | perms: [READ]
Scan complete: 1 bucket found, 499 not found
Example 2: Scan a single known/guessed bucket name
s3scanner scan -b acme-prod-backups
[bucket_exists] acme-prod-backups | region: us-west-2 | perms: [READ, READ_ACP]
Scan complete: bucket exists and is partially accessible
Example 3: Output results in JSON for downstream processing
s3scanner scan -f candidates.txt --json --out results.json
Scan complete: results written in JSON format to results.json
{"bucket":"acme-logs","exists":true,"region":"us-east-1","permissions":["READ"]}
Example 4: Increase thread count for faster scanning of a large wordlist
s3scanner scan -f big_wordlist.txt --threads 50
Scanning 10,000 bucket names with 50 threads...
Scan complete: 12 buckets found in 2m14s (vs ~11m at default 10 threads)
Example 5: Dump the contents of a bucket with READ access
s3scanner dump -b acme-prod-backups -o /home/kali/loot/acme-prod-backups
[dump] Bucket: acme-prod-backups
[dump] Listing objects... 342 objects found (1.2 GB total)
[dump] Downloading to /home/kali/loot/acme-prod-backups/
[dump] Progress: 342/342 objects downloaded
[dump] Dump complete.
Example 6: Dry-run a dump to preview what would be downloaded
s3scanner dump -b acme-prod-backups --dry-run
[dump] DRY RUN - no files will be downloaded
[dump] Would download 342 objects (1.2 GB total):
backups/2026-06-01/database.sql.gz (450 MB)
backups/2026-06-01/config.yaml (2 KB)
...
Example 7: Skip large files during a dump to save disk space
s3scanner dump -b acme-prod-backups --max-size 50MB -o /home/kali/loot/
[dump] Skipping 4 files larger than 50MB
[dump] Downloading 338 objects (89 MB total)
[dump] Dump complete.
Example 8: Scan against DigitalOcean Spaces instead of AWS S3
s3scanner scan -f candidates.txt --provider digitalocean --endpoint-url https://nyc3.digitaloceanspaces.com
Provider: digitalocean
Endpoint: https://nyc3.digitaloceanspaces.com
[bucket_exists] acme-cdn-assets | perms: [READ]
Scan complete: 1 Space found
Example 9: Include closed/non-existent buckets in the output for a full audit trail
s3scanner scan -f candidates.txt --include-closed --out full-audit.txt
Scan complete: 500 total results written (3 found, 497 not found) to full-audit.txt
Example 10: Verbose mode for debugging a scan
s3scanner scan -b acme-test -v
[VERBOSE] Resolving DNS for acme-test.s3.amazonaws.com...
[VERBOSE] DNS resolved to 52.216.x.x
[VERBOSE] Sending HEAD request...
[VERBOSE] Response: 403 Forbidden (bucket exists, access denied)
[bucket_exists] acme-test | region: unknown | perms: []
Example 11: Chain CloudBrute output directly into S3Scanner
cloudbrute -d acme.com -k acme -w storage_small.txt -m storage -C aws -o cloudbrute-out.txt
grep "s3.amazonaws.com" cloudbrute-out.txt | cut -d'-' -f1 > s3-candidates.txt
s3scanner scan -f s3-candidates.txt
[+] Extracted 6 candidate bucket names from CloudBrute output
Scan complete: 4 buckets confirmed to exist, 2 with READ access
Example 12: Enumerate associated IP addresses for discovered buckets
s3scanner scan -f candidates.txt --enumerate-ips
[bucket_exists] acme-cdn | region: us-east-1 | IPs: [52.216.128.45, 52.216.129.10] | perms: [READ]
Scan complete: 1 bucket found with IP resolution data
16.5.7 Common Use Cases
- Bug bounty hunting: Discovering exposed S3 buckets that leak sensitive data, often a high-value, easy-to-report finding.
- Penetration testing: Confirming and demonstrating impact of publicly writable or readable buckets identified during reconnaissance.
- Data breach investigation: Quickly determining the scope of exposure once a leaked bucket name is identified in the wild (e.g., referenced in a paste site or leaked source code).
- Continuous cloud storage monitoring: Scheduling regular scans of known company-related bucket name patterns to catch new exposures early.
- Incident response: Confirming whether a specific bucket suspected of being involved in an incident is (or was) publicly accessible.
16.5.8 Automation with Bash
Automated bucket-name generation and scan pipeline:
#!/bin/bash
# s3scanner-auto.sh
# Generates permutations of a company name and scans them all
COMPANY="acme"
SUFFIXES=("backup" "backups" "dev" "prod" "staging" "assets" "static" "uploads" "logs" "data" "files" "media" "cdn" "internal" "public" "private" "test" "archive")
CANDIDATES_FILE="/tmp/acme-s3-candidates.txt"
> "$CANDIDATES_FILE"
for suffix in "${SUFFIXES[@]}"; do
echo "${COMPANY}-${suffix}" >> "$CANDIDATES_FILE"
echo "${COMPANY}${suffix}" >> "$CANDIDATES_FILE"
echo "${suffix}-${COMPANY}" >> "$CANDIDATES_FILE"
done
echo "[+] Generated $(wc -l < "$CANDIDATES_FILE") candidate bucket names"
s3scanner scan -f "$CANDIDATES_FILE" --json --out "/home/kali/reports/s3scan-$(date +%F).json"
echo "[+] Scan complete. Results saved."
Automated dump of all discovered READ-accessible buckets:
#!/bin/bash
# s3scanner-auto-dump.sh
# Parses a JSON scan result and dumps every bucket with READ access
RESULTS_FILE="$1"
DUMP_BASE="/home/kali/loot/s3-dumps-$(date +%F)"
if [ -z "$RESULTS_FILE" ]; then
echo "Usage: $0 <s3scanner_results.json>"
exit 1
fi
mkdir -p "$DUMP_BASE"
jq -r 'select(.permissions[] == "READ") | .bucket' "$RESULTS_FILE" | while read -r bucket; do
echo "[+] Dumping bucket: $bucket"
s3scanner dump -b "$bucket" -o "$DUMP_BASE/$bucket" --max-size 200MB
done
echo "[+] All READ-accessible buckets dumped to $DUMP_BASE"
16.5.9 Tips and Best Practices
- Always confirm scope authorization before dumping bucket contents — even publicly accessible buckets may contain data outside the agreed engagement scope, and downloading data has legal implications distinct from merely confirming exposure.
- Use
--dry-runbefore everydumpoperation to preview size and object count, avoiding accidental multi-gigabyte downloads on limited storage/bandwidth. - Combine S3Scanner with CloudBrute for name generation, and with OSINT sources (GitHub, JS source maps, Wayback Machine) for additional candidate bucket names.
- Use
--max-sizeduring dumps to prioritize smaller configuration/credential files over large binary backups, then follow up selectively on large files if needed. - When reporting a finding, capture screenshots or logs of the
permsoutput (READ/WRITE/READ_ACP) — the specific permission set materially changes the severity rating of the finding. - Rotate/randomize scan timing and thread counts (
--threads) when testing against providers known to have aggressive rate-limiting or bot-detection on their storage endpoints.
Troubleshooting
| Issue | Cause | Resolution |
|---|---|---|
All buckets report bucket_not_exist | Incorrect bucket naming convention or region issue | Verify naming pattern against target’s known convention; try --enumerate-ips for extra detail |
dump command fails with AccessDenied | Bucket permissions changed since scan, or scan misreported READ access | Re-run s3scanner scan -b <bucket> to confirm current permissions before retrying dump |
| Scan is very slow on large wordlists | Thread count too low | Increase --threads (e.g., --threads 50 or higher, balanced against network limits) |
| JSON output file is empty | --include-closed not set and no buckets were found | Confirm candidate list quality, or add --include-closed to verify the scan actually ran |
| DigitalOcean/Spaces scan returns no results | Wrong --endpoint-url region subdomain | Verify the correct regional endpoint (e.g., nyc3, sgp1, ams3) for the target Space |
dump stalls on specific large files | Network timeout on large objects | Use --max-size to skip oversized objects, or increase client-side timeout settings |
References
- Official GitHub Repository: https://github.com/sa7mon/S3Scanner
- AWS S3 ACL Permissions Documentation: https://docs.aws.amazon.com/AmazonS3/latest/userguide/acl-overview.html
- OWASP Testing Guide – Cloud Storage: https://owasp.org/www-project-web-security-testing-guide/
- Kali Linux Tool Listing: https://www.kali.org/tools/s3scanner/