Fix all power-user review issues (FR-01 through FR-12)
FR-01: Fix data directory default from ~/.fieldwitness to ~/.fwmetadata
FR-02/05/07: Accept all file types for attestation (not just images)
- Web UI, CLI, and batch now accept PDFs, CSVs, audio, video, etc.
- Perceptual hashing for images, SHA-256-only for everything else
FR-03: Implement C2PA import path + CLI commands (export/verify/import/show)
FR-04: Fix GPS downsampling bias (math.floor → round)
FR-06: Add HTML/PDF evidence summaries for lawyers
- Always generates summary.html, optional summary.pdf via xhtml2pdf
FR-08: Fix CLI help text ("FieldWitness -- FieldWitness" artifact)
FR-09: Centralize stray paths (trusted_keys, carrier_history, last_backup)
FR-10: Add 67 C2PA bridge tests (vendor assertions, cert, GPS, export)
FR-12: Add Tor onion service support for source drop box
- fieldwitness serve --tor flag, persistent/transient modes
- Killswitch covers hidden service keys
Also: bonus fix for attest/api.py hardcoded path bypassing paths.py
224 tests passing (67 new).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -461,11 +461,19 @@ A malicious or compromised relay could suppress specific records. The design mit
|
||||
to use the relay only for transport, never as an authoritative source -- but no
|
||||
verification mechanism is implemented.
|
||||
|
||||
**L7: Drop box source anonymity is limited.** The drop box does not log source IP addresses
|
||||
in attestation records or require accounts, but it does not anonymize the source's network
|
||||
connection. A source's IP is visible to the Tier 2 server operator in web server access
|
||||
logs. Organizations providing source protection should use Tor for source access and may
|
||||
wish to configure the web server to not log IP addresses.
|
||||
**L7: Drop box source anonymity is limited -- Tor support available.** The drop box does
|
||||
not log source IP addresses in attestation records or require accounts. FieldWitness now
|
||||
includes built-in Tor hidden service support: starting the server with `--tor` exposes the
|
||||
drop box as a `.onion` address so that source IPs are never visible to the server operator.
|
||||
|
||||
Without `--tor`, a source's IP address is visible in web server access logs.
|
||||
Organizations with source-protection requirements should use the `--tor` flag and instruct
|
||||
sources to access the drop box only via Tor Browser. Operators should also configure any
|
||||
reverse proxy to suppress access logging for `/dropbox/upload/` paths.
|
||||
|
||||
Even with Tor, timing analysis and traffic correlation attacks are possible at the network
|
||||
level. Tor eliminates IP exposure at the server; it does not protect against a global
|
||||
adversary correlating traffic timing. See `docs/source-dropbox.md` for setup instructions.
|
||||
|
||||
**L8: Steganalysis resistance is not guaranteed.** The steganography backend includes a
|
||||
steganalysis module (`stego/steganalysis.py`) for estimating detection resistance, but
|
||||
|
||||
@@ -208,13 +208,142 @@ Expired tokens are cleaned up automatically on every admin page load.
|
||||
|
||||
### Running as a Tor hidden service
|
||||
|
||||
For maximum source protection, run FieldWitness as a Tor hidden service:
|
||||
FieldWitness has built-in support for exposing the drop box as a Tor hidden service
|
||||
(a `.onion` address). When a source accesses the drop box over Tor, the server never
|
||||
sees their real IP address -- Tor's onion routing ensures that only the Tor network knows
|
||||
both the source and the destination.
|
||||
|
||||
1. Install Tor on the server
|
||||
2. Configure a hidden service in `torrc` pointing to `127.0.0.1:5000`
|
||||
3. Share the `.onion` URL instead of a LAN address
|
||||
4. The source's real IP is never visible to the server
|
||||
#### Step 1: Install and configure Tor
|
||||
|
||||
```bash
|
||||
# Debian / Ubuntu
|
||||
sudo apt install tor
|
||||
|
||||
# macOS (Homebrew)
|
||||
brew install tor
|
||||
|
||||
# Fedora / RHEL
|
||||
sudo dnf install tor
|
||||
```
|
||||
|
||||
Enable the control port so FieldWitness can manage the hidden service. Add these lines
|
||||
to `/etc/tor/torrc`:
|
||||
|
||||
```
|
||||
ControlPort 9051
|
||||
CookieAuthentication 1
|
||||
```
|
||||
|
||||
Then restart Tor:
|
||||
|
||||
```bash
|
||||
sudo systemctl restart tor
|
||||
```
|
||||
|
||||
**Authentication note:** `CookieAuthentication 1` lets FieldWitness authenticate using the
|
||||
cookie file that Tor creates automatically. Alternatively, use a password:
|
||||
|
||||
```
|
||||
ControlPort 9051
|
||||
HashedControlPassword <hash produced by: tor --hash-password yourpassword>
|
||||
```
|
||||
|
||||
#### Step 2: Install the stem library
|
||||
|
||||
stem is an optional FieldWitness dependency. Install it alongside the fieldkit extra:
|
||||
|
||||
```bash
|
||||
pip install 'fieldwitness[tor]'
|
||||
# or, if already installed:
|
||||
pip install stem>=1.8.0
|
||||
```
|
||||
|
||||
#### Step 3: Start FieldWitness with --tor
|
||||
|
||||
```bash
|
||||
fieldwitness serve --host 127.0.0.1 --port 5000 --tor
|
||||
```
|
||||
|
||||
With a custom control port or password:
|
||||
|
||||
```bash
|
||||
fieldwitness serve --tor --tor-control-port 9051 --tor-password yourpassword
|
||||
```
|
||||
|
||||
For a one-off intake session where a fixed address is not needed:
|
||||
|
||||
```bash
|
||||
fieldwitness serve --tor --tor-transient
|
||||
```
|
||||
|
||||
On startup, FieldWitness will print the `.onion` address:
|
||||
|
||||
```
|
||||
============================================================
|
||||
TOR HIDDEN SERVICE ACTIVE
|
||||
============================================================
|
||||
.onion address : abc123def456ghi789jkl012mno345pq.onion
|
||||
Drop box URL : http://abc123def456ghi789jkl012mno345pq.onion/dropbox/upload/<token>
|
||||
Persistent : yes (key saved to ~/.fwmetadata/fieldkit/tor/)
|
||||
============================================================
|
||||
Sources must use Tor Browser to access the .onion URL.
|
||||
Share the drop box upload URL over a secure channel (Signal, in person).
|
||||
============================================================
|
||||
```
|
||||
|
||||
#### Step 4: Share the .onion drop box URL
|
||||
|
||||
Create a drop box token as usual (see Step 2 above), then construct the `.onion` upload URL:
|
||||
|
||||
```
|
||||
http://<onion-address>/dropbox/upload/<token>
|
||||
```
|
||||
|
||||
Share this URL with the source over Signal or in person. The source opens it in
|
||||
**Tor Browser** -- not in a regular browser.
|
||||
|
||||
#### Persistent vs. transient hidden services
|
||||
|
||||
| Mode | Command | Behaviour |
|
||||
|---|---|---|
|
||||
| **Persistent** (default) | `--tor` | Same `.onion` address on every restart. Key stored at `~/.fwmetadata/fieldkit/tor/hidden_service/`. |
|
||||
| **Transient** | `--tor --tor-transient` | New `.onion` address each run. No key written to disk. |
|
||||
|
||||
Use persistent mode when you want sources to bookmark the address or share it in advance.
|
||||
Use transient mode for single-session intake where address continuity does not matter.
|
||||
|
||||
#### Source instructions
|
||||
|
||||
Tell sources:
|
||||
|
||||
1. Install **Tor Browser** from [torproject.org](https://www.torproject.org/download/).
|
||||
2. Open Tor Browser and paste the full `.onion` URL into the address bar.
|
||||
3. Do not open the `.onion` URL in a regular browser -- your real IP will be visible.
|
||||
4. JavaScript must be enabled for the SHA-256 fingerprint feature to work.
|
||||
Set the Security Level to "Standard" in Tor Browser (shield icon in the toolbar).
|
||||
5. Save the SHA-256 fingerprints shown before clicking Upload.
|
||||
6. Save the receipt codes shown after upload.
|
||||
|
||||
#### Logging and access logs
|
||||
|
||||
Even with Tor, access logs on the server can record that *someone* connected -- the
|
||||
connection appears to come from a Tor exit relay (for regular Tor) or from a Tor internal
|
||||
address (for hidden services). For hidden services, the server sees no IP at all; the
|
||||
connection comes from the Tor daemon on localhost.
|
||||
|
||||
**Recommendation:** Set the web server or reverse proxy to not log access requests to
|
||||
`/dropbox/upload/` paths. If using FieldWitness directly (Waitress), access log output
|
||||
goes to stdout; redirect it to `/dev/null` or omit the log handler.
|
||||
|
||||
#### Killswitch and the hidden service key
|
||||
|
||||
The persistent hidden service key is stored under `~/.fwmetadata/fieldkit/tor/hidden_service/`
|
||||
and is treated as key material. The FieldWitness killswitch (`fieldwitness fieldkit purge`)
|
||||
destroys this directory during both `KEYS_ONLY` and `ALL` purge scopes. After a purge,
|
||||
the `.onion` address cannot be linked to the operator even if the server hardware is seized.
|
||||
|
||||
> **Warning:** Even with Tor, timing analysis and traffic correlation attacks are possible
|
||||
> at the network level. The drop box protects source identity at the application layer;
|
||||
> network-layer protection requires operational discipline beyond what software can provide.
|
||||
> Tor is not a silver bullet -- but it removes the most direct risk (IP address exposure)
|
||||
> that limitation L7 in the threat model describes.
|
||||
|
||||
Reference in New Issue
Block a user