Complete project rebrand for better positioning in the press freedom and digital security space. FieldWitness communicates both field deployment and evidence testimony — appropriate for the target audience of journalists, NGOs, and human rights organizations. Rename mapping: - soosef → fieldwitness (package, CLI, all imports) - soosef.stegasoo → fieldwitness.stego - soosef.verisoo → fieldwitness.attest - ~/.soosef/ → ~/.fwmetadata/ (innocuous data dir name) - SOOSEF_DATA_DIR → FIELDWITNESS_DATA_DIR - SoosefConfig → FieldWitnessConfig - SoosefError → FieldWitnessError Also includes: - License switch from MIT to GPL-3.0 - C2PA bridge module (Phase 0-2 MVP): cert.py, export.py, vendor_assertions.py - README repositioned to lead with provenance/federation, stego backgrounded - Threat model skeleton at docs/security/threat-model.md - Planning docs: docs/planning/c2pa-integration.md, docs/planning/gtm-feasibility.md Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
221 lines
8.9 KiB
Markdown
221 lines
8.9 KiB
Markdown
# Source Drop Box Setup Guide
|
|
|
|
**Audience**: Administrators setting up FieldWitness's anonymous source intake feature.
|
|
|
|
**Prerequisites**: A running FieldWitness instance with web UI enabled (`fieldwitness[web]` extra),
|
|
an admin account, and HTTPS configured (self-signed is acceptable).
|
|
|
|
---
|
|
|
|
## Overview
|
|
|
|
The source drop box is a SecureDrop-style anonymous file intake built into the FieldWitness web
|
|
UI. Admins create time-limited upload tokens, sources open the token URL in a browser and
|
|
submit files without creating an account. Files are processed through the extract-then-strip
|
|
EXIF pipeline and automatically attested on receipt. Sources receive HMAC-derived receipt
|
|
codes that prove delivery.
|
|
|
|
> **Warning:** The drop box protects source identity through design -- no accounts, no
|
|
> branding, no IP logging. However, the security of the system depends on how the upload URL
|
|
> is shared. Never send drop box URLs over unencrypted email or SMS.
|
|
|
|
---
|
|
|
|
## How It Works
|
|
|
|
```
|
|
Admin Source FieldWitness Server
|
|
| | |
|
|
|-- Create token ------------->| |
|
|
| (label, expiry, max_files) | |
|
|
| | |
|
|
|-- Share URL (secure channel) | |
|
|
| | |
|
|
| |-- Open URL in browser --------->|
|
|
| | (no login required) |
|
|
| | |
|
|
| |-- Select files |
|
|
| | Browser computes SHA-256 |
|
|
| | (SubtleCrypto, client-side) |
|
|
| | |
|
|
| |-- Upload files ---------------->|
|
|
| | |-- Extract EXIF
|
|
| | |-- Strip metadata
|
|
| | |-- Attest originals
|
|
| | |-- Save stripped copy
|
|
| | |
|
|
| |<-- Receipt codes ---------------|
|
|
| | (HMAC of file hash + token) |
|
|
```
|
|
|
|
---
|
|
|
|
## Setting Up the Drop Box
|
|
|
|
### Step 1: Ensure HTTPS is enabled
|
|
|
|
The drop box should always be served over HTTPS. Sources must be able to trust that their
|
|
connection is not being intercepted.
|
|
|
|
```bash
|
|
$ fieldwitness serve --host 0.0.0.0
|
|
```
|
|
|
|
FieldWitness auto-generates a self-signed certificate on first HTTPS start. For production use,
|
|
place a reverse proxy with a proper TLS certificate in front of FieldWitness.
|
|
|
|
### Step 2: Create an upload token
|
|
|
|
Navigate to `/dropbox/admin` in the web UI (admin login required), or use the admin panel.
|
|
|
|
Each token has:
|
|
|
|
| Field | Default | Description |
|
|
|---|---|---|
|
|
| **Label** | "Unnamed source" | Human-readable name for the source (stored server-side only, never shown to the source) |
|
|
| **Expiry** | 24 hours | How long the upload link remains valid |
|
|
| **Max files** | 10 | Maximum number of uploads allowed on this link |
|
|
|
|
After creating the token, the admin receives a URL of the form:
|
|
|
|
```
|
|
https://<host>:<port>/dropbox/upload/<token>
|
|
```
|
|
|
|
The token is a 32-byte cryptographically random URL-safe string.
|
|
|
|
### Step 3: Share the URL with the source
|
|
|
|
Share the upload URL over an already-secure channel:
|
|
|
|
- **Best**: in person, on paper
|
|
- **Good**: encrypted messaging (Signal, Wire)
|
|
- **Acceptable**: verbal dictation over a secure voice call
|
|
- **Never**: unencrypted email, SMS, or any channel that could be intercepted
|
|
|
|
### Step 4: Source uploads files
|
|
|
|
The source opens the URL in their browser. The upload page is minimal -- no FieldWitness branding,
|
|
no identifying marks, generic styling. The page works over Tor Browser with JavaScript
|
|
enabled (no external resources, no CDN, no fonts, no analytics).
|
|
|
|
When files are selected:
|
|
|
|
1. The browser computes SHA-256 fingerprints client-side using SubtleCrypto
|
|
2. The source sees the fingerprints and is prompted to save them before uploading
|
|
3. On upload, the server processes each file through the extract-then-strip pipeline
|
|
4. The source receives receipt codes for each file
|
|
|
|
### Step 5: Monitor submissions
|
|
|
|
The admin panel at `/dropbox/admin` shows:
|
|
|
|
- Active tokens with their usage counts
|
|
- Token expiry times
|
|
- Ability to revoke tokens immediately
|
|
|
|
---
|
|
|
|
## The Extract-Then-Strip Pipeline
|
|
|
|
Every file uploaded through the drop box is processed through FieldWitness's EXIF pipeline:
|
|
|
|
1. **Extract**: all EXIF metadata is read from the original image bytes
|
|
2. **Classify**: fields are split into evidentiary (GPS coordinates, capture timestamp --
|
|
valuable for provenance) and dangerous (device serial number, firmware version -- could
|
|
identify the source's device)
|
|
3. **Attest**: the original bytes are attested (Ed25519 signed) with evidentiary metadata
|
|
included in the attestation record. The attestation hash matches what the source actually
|
|
submitted.
|
|
4. **Strip**: all metadata is removed from the stored copy. The stripped copy is saved to
|
|
disk. No device fingerprint persists on the server's storage.
|
|
|
|
This resolves the tension between protecting the source (strip device-identifying metadata)
|
|
and preserving evidence (retain GPS and timestamp for provenance).
|
|
|
|
---
|
|
|
|
## Receipt Codes
|
|
|
|
Each uploaded file generates an HMAC-derived receipt code:
|
|
|
|
```
|
|
receipt_code = HMAC-SHA256(token, file_sha256)[:16]
|
|
```
|
|
|
|
The receipt code proves:
|
|
|
|
- The server received the specific file (tied to the file's SHA-256)
|
|
- The file was received under the specific token (tied to the token value)
|
|
|
|
Sources can verify their receipt by posting it to `/dropbox/verify-receipt`. This returns
|
|
the filename, SHA-256, and reception timestamp if the receipt is valid.
|
|
|
|
> **Note:** Receipt codes are deterministic. The source can compute the expected receipt
|
|
> themselves if they know the token value and the file's SHA-256 hash, providing
|
|
> independent verification.
|
|
|
|
---
|
|
|
|
## Client-Side SHA-256
|
|
|
|
The upload page computes SHA-256 fingerprints in the browser before upload using the
|
|
SubtleCrypto Web API. This gives the source a verifiable record of exactly what they
|
|
submitted -- the hash is computed on their device, not the server.
|
|
|
|
The source should save these fingerprints before uploading. If the server later claims to
|
|
have received different content, the source can prove what they actually submitted by
|
|
comparing their locally computed hash with the server's receipt.
|
|
|
|
---
|
|
|
|
## Storage
|
|
|
|
| What | Where |
|
|
|---|---|
|
|
| Uploaded files (stripped) | `~/.fwmetadata/temp/dropbox/` (mode 0700) |
|
|
| Token metadata | `~/.fwmetadata/auth/dropbox.db` (SQLite) |
|
|
| Receipt codes | `~/.fwmetadata/auth/dropbox.db` (SQLite) |
|
|
| Attestation records | `~/.fwmetadata/attestations/` (standard attestation log) |
|
|
|
|
Expired tokens are cleaned up automatically on every admin page load.
|
|
|
|
---
|
|
|
|
## Operational Security
|
|
|
|
### Source safety
|
|
|
|
- **No FieldWitness branding** on the upload page. Generic "Secure File Upload" title.
|
|
- **No authentication required** -- sources never create accounts or reveal identity.
|
|
- **No IP logging** -- FieldWitness does not log source IP addresses. Ensure your reverse proxy
|
|
(if any) also does not log access requests to `/dropbox/upload/` paths.
|
|
- **Self-contained page** -- inline CSS and JavaScript only. No external resources, CDN
|
|
calls, web fonts, or analytics. Works with Tor Browser.
|
|
- **CSRF exempt** -- the upload endpoint does not require CSRF tokens because sources do
|
|
not have sessions.
|
|
|
|
### Token management
|
|
|
|
- **Short expiry** -- set token expiry as short as practical. 24 hours is the default; for
|
|
high-risk sources, consider 1-4 hours.
|
|
- **Low file limits** -- set `max_files` to the expected number of submissions.
|
|
Once reached, the link stops accepting uploads.
|
|
- **Revoke immediately** -- if a token is compromised or no longer needed, revoke it from
|
|
the admin panel. This deletes the token and all associated receipt records from SQLite.
|
|
- **Audit trail** -- token creation events are logged to `~/.fwmetadata/audit.jsonl` with the
|
|
action `dropbox.token_created`.
|
|
|
|
### Running as a Tor hidden service
|
|
|
|
For maximum source protection, run FieldWitness as a Tor hidden service:
|
|
|
|
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
|
|
|
|
> **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.
|