A secure forensic evidence data upload web application with session-based authentication, IP binding, activity tracking, and Chain of Custody PDF generation.
- Secure Upload: HMAC-signed session tokens with IP binding
- Resumable Uploads: Chunked upload support for large files (10GB+)
- Drag & Drop: Modern upload interface with progress bars
- Session Management: Create, monitor, and revoke upload sessions
- Activity Tracking: Full audit trail of all session activities
- Chain of Custody PDF: Automatic forensic documentation on session revocation/expiration
- Triage Collection Package: Upload and share triage packages with remote parties
- IP Detection: Browser-based IP detection with upload for forensic documentation
- Auto-open Browser: Admin interface opens automatically on startup
- Config File Support: Persistent configuration via
~/.evidence-upload.conf - Multi-channel Alerts: Desktop, email, webhook, and log file notifications
- Tunnel Support: Built-in bore and Cloudflare Tunnel for internet access
- Cross-platform: Works on Windows, Linux, and macOS
# Linux/macOS
go build -o evidence-upload .
# Windows
go build -o evidence-upload.exe .# Start server on default port 8443
./evidence-upload
# Start with custom storage path
./evidence-upload -storage /path/to/evidence
# Start with bore tunnel for internet access
./evidence-upload -tunnel bore
# Start without auto-opening browser
./evidence-upload -no-browser
# Show version
./evidence-upload -version| Flag | Default | Description |
|---|---|---|
-port |
8443 |
Server port |
-storage |
./evidence |
Local storage path for uploaded files |
-backup |
"" |
Network share backup path (optional) |
-expire |
24h |
Default session expiration duration |
-secret |
auto-generated | HMAC secret key |
-max-size |
10737418240 (10GB) |
Maximum upload size in bytes |
-alert-email |
"" |
Email address for security alerts |
-alert-webhook |
"" |
Webhook URL for alerts (Slack/Discord/etc) |
-alert-desktop |
true |
Enable desktop notifications |
-alert-log |
./alerts.log |
Log file for security alerts |
-external-ip |
auto-detected | External/public IP for internet access |
-base-url |
auto-detected | Base URL for generated links |
-tunnel |
"" |
Tunnel provider: bore, cloudflare, or external |
-bore-path |
auto-detected | Path to bore binary |
-cloudflare-path |
auto-detected | Path to cloudflared binary |
-cloudflare-domain |
"" |
Custom domain for Cloudflare tunnel (e.g., yourdomain.com) |
-cloudflare-token |
"" |
Cloudflare tunnel token (from dashboard) |
-tunnel-name |
"" |
Named tunnel for Cloudflare (creates if missing) |
-tunnel-url |
"" |
External tunnel URL (for multi-analyst mode) |
-no-browser |
false |
Don't automatically open browser on startup |
-version |
- | Show version and exit |
Settings can be persisted in ~/.evidence-upload.conf (Linux/macOS) or %USERPROFILE%\.evidence-upload.conf (Windows).
Priority order: CLI flags > Environment variables (EVIDENCE_*) > Config file > Defaults
# Evidence Upload Configuration
# Security: Set permissions to 600 after editing: chmod 600 ~/.evidence-upload.conf
# Cloudflare Tunnel Settings
CLOUDFLARE_TOKEN=eyJ...your-token-here...
CLOUDFLARE_DOMAIN=yourdomain.com
TUNNEL_NAME=evidence-upload
# Server Settings
PORT=8443
STORAGE=./evidence
BACKUP=/nas/backup/evidence
# Session Settings
EXPIRE=24h
# Security Settings
# SECRET=your-secret-key-here
# Alert Settings
ALERT_EMAIL=security@yourdomain.com
ALERT_WEBHOOK=https://hooks.slack.com/services/xxx
# External IP (auto-detected if empty)
# EXTERNAL_IP=203.0.113.45
# Base URL (auto-detected if empty)
# BASE_URL=https://evidence.yourdomain.com./evidence-upload -port 8443 -storage /evidence -alert-email admin@corp.comThe browser will automatically open to the admin interface at http://localhost:8443/admin. Use -no-browser to disable this behavior.
Open browser to http://<server-ip>:8443/admin
- Click "Create New Session"
- Set duration (hours)
- Add description (case number, incident ID, etc.)
- Click "Generate Link"
Copy the generated link and send it to the uploading party.
The uploader opens the link and sees:
- Case reference number
- IP detection section (must send IP info first)
- Drag & drop upload area
- File selection button
- Progress bar during upload
- List of uploaded files with sizes
If you have a triage collection package to share:
- In the admin panel, click on the session token
- Click "Send Triage Package" in the session detail modal
- Select the triage package file
- A download link is generated:
http://host:8443/triage/<token> - Share this link with the remote party
In the admin panel, click on any token to see:
- Full token and secret
- Session status (locked IP)
- Uploaded files with sizes and hashes
- Complete activity history
- Triage package status and download link
When evidence collection is complete:
- Click "Revoke" on the session
- Enter analyst name for Chain of Custody document
- CoC PDF is generated in the case folder
The triage package feature allows analysts to share a collection tool with remote parties.
- Analyst: Creates a session in the admin panel
- Analyst: Clicks "Send Triage Package" and selects the file
- Analyst: Shares the generated download link with the remote party
- Remote Party: Downloads the triage package via the link
- Remote Party: Runs the triage package to collect and upload evidence
- Per-session: Each session can have its own triage package
- Public download: No authentication required to download the package
- Replaceable: Analyst can replace the package with a new version
- Auto-named: Files are stored as
TRIAGE_PACKAGE_<original_filename>
http://<host>:<port>/triage/<session-token>
The link is public and does not require the session secret.
- HMAC-signed tokens: Each session has a unique token and secret
- IP binding: First access locks the session to the uploader's IP
- IP detection: Browser uploads IP information as first evidence file
- No download capability: Uploaders can only see filenames, not download
- Session expiration: Automatic cleanup of expired sessions
- Chain of Custody PDF: Generated on revocation/expiration with full audit trail
- Alert system: Notifications for unauthorized access attempts
- File integrity: SHA-256 hash computed for every uploaded file (saved as
.sha256sidecar)
When a session is revoked or expires, a Chain of Custody PDF is automatically generated containing:
- Case information (description, token, dates, status)
- Collector IP information (from uploaded IP detection file)
- Evidence items table (filename, size, SHA-256 hash)
- Activity timeline (all actions with timestamps)
- Integrity verification details
- Certification statement with analyst signature block
The PDF is saved as CHAIN_OF_CUSTODY.pdf in the case folder with a .sha256 sidecar file.
For internet access without router configuration:
# Auto-installs bore if missing
./evidence-upload -tunnel bore
# Use custom bore binary
./evidence-upload -tunnel bore -bore-path /usr/local/bin/boreThe bore tunnel creates a public URL via bore.pub that forwards to your local server.
Note: bore.pub domains may be blocked by corporate proxies. Consider Cloudflare Tunnel for trusted domain access.
Cloudflare Tunnel provides a trusted domain that's less likely to be blocked by proxies.
-
Install cloudflared:
# Linux curl -L https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64 -o /usr/local/bin/cloudflared chmod +x /usr/local/bin/cloudflared # macOS brew install cloudflared # Windows: Download from https://github.com/cloudflare/cloudflared/releases
-
Authenticate with Cloudflare:
cloudflared tunnel login # Opens browser - select your domain (e.g., yourdomain.com)
./evidence-upload -tunnel cloudflare
# Returns URL like: https://random-name.trycloudflare.com# Create tunnel (first time only)
cloudflared tunnel create evidence-upload
# Route DNS (first time only)
cloudflared tunnel route dns evidence-upload evidence.yourdomain.com
# Run with named tunnel
./evidence-upload -tunnel cloudflare -tunnel-name evidence-upload# Use your domain for the tunnel
./evidence-upload -tunnel cloudflare -cloudflare-domain yourdomain.com -tunnel-name evidence-uploadThis creates URLs like: https://evidence.yourdomain.com
# One-time setup
cloudflared tunnel login
cloudflared tunnel create evidence-upload
cloudflared tunnel route dns evidence-upload evidence.yourdomain.com
# Start server with tunnel
./evidence-upload \
-port 8443 \
-storage /evidence \
-tunnel cloudflare \
-tunnel-name evidence-upload \
-cloudflare-domain yourdomain.comAccess at: https://evidence.yourdomain.com
- Trusted domain: Your domain (yourdomain.com) is less likely blocked
- HTTPS included: Free valid certificate
- Stable URLs: No random ports or changing addresses
- Corporate friendly: Works with proxies that trust Cloudflare
- Free: No cost for personal use
For teams where multiple forensic analysts need to use the app without accessing Cloudflare credentials.
┌─────────────────────────────────────────────────────────────┐
│ Domain Owner (yourdomain.com) │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ cloudflared tunnel --url http://COORDINATOR:PORT │ │
│ └─────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Coordinator Server │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ evidence-upload -port 8443 -tunnel external │ │
│ │ -tunnel-url https://evidence.yourdomain.com │ │
│ └─────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Analyst Machines (no Cloudflare credentials needed) │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ evidence-upload -port 8443 -tunnel external │ │
│ │ -tunnel-url https://evidence.yourdomain.com │ │
│ └─────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
Domain Owner (one-time setup):
# 1. Install and authenticate cloudflared
curl -L https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64 -o /usr/local/bin/cloudflared
chmod +x /usr/local/bin/cloudflared
cloudflared tunnel login
# 2. Create tunnel
cloudflared tunnel create evidence-ops
cloudflared tunnel route dns evidence-ops evidence.yourdomain.com
# 3. Run tunnel (as a service or long-running process)
cloudflared tunnel run evidence-opsAnalyst Setup (no credentials needed):
# Just run the app with the shared tunnel URL
./evidence-upload \
-port 8443 \
-storage /path/to/evidence \
-tunnel external \
-tunnel-url https://evidence.yourdomain.com- No credentials shared: Analysts don't need Cloudflare login
- No installation: Analysts don't need cloudflared installed
- Simple setup: Just run the binary with a URL
- Isolated storage: Each analyst has their own local storage
- Centralized access: One domain for all analysts
Option 1: Different ports
# Analyst 1
./evidence-upload -port 8443 -tunnel external -tunnel-url https://evidence.yourdomain.com
# Analyst 2
./evidence-upload -port 8444 -tunnel external -tunnel-url https://evidence.yourdomain.comOption 2: Different subdomains
# Domain owner runs multiple tunnels
cloudflared tunnel --url http://analyst1:8443 # analyst1.evidence.yourdomain.com
cloudflared tunnel --url http://analyst2:8443 # analyst2.evidence.yourdomain.com
# Analysts use their assigned subdomain
./evidence-upload -port 8443 -tunnel external -tunnel-url https://analyst1.evidence.yourdomain.com
./evidence-upload -port 8443 -tunnel external -tunnel-url https://analyst2.evidence.yourdomain.com./evidence-upload -port 8443 -storage /mnt/evidenceAccess from any device on the network: http://192.168.1.100:8443/admin
./evidence-upload -port 8443 -storage /evidence -tunnel boreThe server will output the public bore URL to share with uploaders.
./evidence-upload \
-port 8443 \
-storage /mnt/data/evidence \
-backup /nas/backup/evidence \
-expire 48h \
-alert-email ir-team@corp.com \
-alert-webhook https://hooks.slack.com/services/xxx \
-alert-log /var/log/evidence-upload.log./evidence-upload -no-browser -port 8443 -storage /evidence- Desktop notifications use Windows Toast API
- Use
-alert-desktop=truefor system tray alerts - bore.exe may trigger Windows Defender (false positive) - whitelist if needed
- Browser opens with
cmd /c start
- Desktop notifications use libnotify/D-Bus
- Install
libnotify-binfor desktop alerts:sudo apt install libnotify-bin - bore binary is installed to the current directory
- Browser opens with
xdg-open
- Desktop notifications use AppleScript
- bore binary is installed to the current directory
- Browser opens with
open
evidence-upload/
├── main.go # Entry point + browser open logic
├── version.go # Version constant
├── go.mod
├── internal/
│ ├── config/config.go # CLI flags and configuration
│ ├── models/session.go # Session management with HMAC
│ ├── storage/storage.go # Local + backup storage
│ ├── custody/custody.go # Chain of Custody PDF generation
│ ├── alerts/manager.go # Multi-channel alerts
│ ├── server/server.go # HTTP handlers + web UI
│ └── tunnel/
│ ├── bore.go # bore tunnel integration
│ └── cloudflare.go # Cloudflare Tunnel integration
└── evidence-upload # Compiled binary
MIT License