fieldwitness/docs/security/threat-model.md
Aaron D. Lee 5b0d90eeaf
Some checks failed
CI / lint (push) Failing after 12s
CI / typecheck (push) Failing after 12s
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>
2026-04-02 20:10:37 -04:00

24 KiB

FieldWitness Threat Model

Status: Living document -- updated as the design evolves and as external review identifies gaps. Version numbers track significant revisions.

Document version: 0.1 (2026-04-01) Corresponds to: FieldWitness v0.3.0

This document follows the style of the Signal Protocol specification and the Tor design document: it makes precise claims, distinguishes what is guaranteed from what is not, and does not use marketing language. Unresolved questions and known gaps are stated plainly.

This document has not been externally audited. Claims here reflect the designer's intent and analysis. An independent security review is planned as part of Phase 2 (see docs/planning/gtm-feasibility.md). Until that review is complete, treat this document as a design statement, not a security certification.


Table of Contents

  1. Intended Users
  2. Adversary Model
  3. Assets Protected
  4. Trust Boundaries
  5. Security Guarantees
  6. Non-Guarantees
  7. Cryptographic Primitives
  8. Key Management Model
  9. Federation Trust Model
  10. Known Limitations

1. Intended Users

FieldWitness is designed for three overlapping user populations:

Field reporters and documenters. Journalists, human rights monitors, and election observers working in environments where physical device seizure is a plausible risk. Operating assumption: the user may be detained, the device may be confiscated, and the operator at Tier 2 (the org server) may not be reachable in real time. The user needs to attest evidence locally on a Tier 1 (field device) and sync later -- or never, if the USB is destroyed.

Organizational administrators. IT staff and security-aware operators at newsrooms or NGOs running Tier 2 deployments. They manage keys, configure threat levels, operate the source drop box, and maintain federation peering with partner organizations. They are expected to understand basic operational security concepts but are not expected to be cryptographers.

Partner organizations. Organizations that receive attested evidence bundles from the primary organization and need to verify chain-of-custody without installing FieldWitness. They interact with standalone verify.py scripts included in evidence packages.

FieldWitness is not designed as a general-purpose secure communications tool, a replacement for SecureDrop's source protection model, or a consumer privacy application.


2. Adversary Model

2.1 Passive Network Observer

Capability: Can observe all network traffic between nodes, including Tier 2 to Tier 3 communication and gossip federation traffic. Cannot break TLS or Ed25519.

Goal: Determine which organizations are communicating, the timing and volume of attestation syncs, and potentially correlate sync events with news events.

FieldWitness's position: Transport-level metadata (IP addresses, timing, volume) is not hidden. TLS (self-signed, port 8000) protects payload content. A passive observer can determine that two Tier 2 servers are federating; they cannot read the attestation records being exchanged without the relevant Ed25519 public keys.

Gap: No traffic padding, no onion routing, no anonymization of federation topology. Organizations with strong network-level adversaries should route federation traffic through Tor or a VPN. This is not built in.

2.2 Active Network Adversary

Capability: Can intercept, modify, replay, and drop traffic. Can present forged TLS certificates if the operator hasn't pinned the peer's certificate.

Goal: Inject forged attestation records into the federation, suppress legitimate records, or cause evidence to appear tampered.

FieldWitness's position: All attestation records are Ed25519-signed. A network adversary cannot forge a valid signature without the private key. The append-only hash chain makes retroactive injection detectable: inserting a record at position N requires recomputing all subsequent hashes. Consistency proofs during gossip sync detect log divergence.

Gap: Certificate pinning for federation peers is not implemented as of v0.3.0. The Tier 3 relay uses a self-signed certificate; operators should verify its fingerprint out-of-band. Gossip peers authenticate by Ed25519 fingerprint, not certificate, which provides a secondary check.

2.3 Physical Access

Capability: Has physical access to the field device (Tier 1 USB) or the org server (Tier 2). May have forensic tools.

Goal: Extract private keys, recover attested evidence, identify the operator, or determine what evidence was collected.

FieldWitness's position:

  • Tier 1 is designed for amnesia: Debian Live USB with LUKS-encrypted persistent partition. Pulling the USB from the host leaves no trace on the host machine. If the USB itself is seized, LUKS protects the persistent partition.
  • The killswitch (fieldwitness fieldkit purge) destroys all key material and data under ~/.fwmetadata/ in sensitivity order. The deep forensic scrub removes Python bytecache, pip metadata, download cache, and shell history entries. The final step is pip uninstall -y fieldwitness.
  • The dead man's switch fires the killswitch automatically if check-in is missed.
  • Private keys are stored as PEM files with 0600 permissions. Key material is not additionally encrypted at rest beyond the filesystem (LUKS on Tier 1; operator-managed on Tier 2).

Gap: If the device is seized before the killswitch fires and LUKS has been unlocked (i.e., the device is running), private keys are accessible. Cold boot attacks against unlocked LUKS volumes are not mitigated. Key material is not stored in a hardware security module or OS keychain.

Capability: Can compel the operator (or their legal jurisdiction) to produce data, keys, or records. May use court orders, search warrants, or jurisdiction-specific administrative processes.

Goal: Obtain attestation records or private keys under legal authority.

FieldWitness's position: FieldWitness provides tools (selective disclosure, evidence packages) for producing specific records under court order without revealing the full chain. The Federation Relay (Tier 3) stores only hashes and signatures -- never private keys or plaintext. Placing Tier 3 in a jurisdiction with strong press protections limits one compulsion surface.

Gap: If private keys are seized, all past and future attestations signed by those keys are attributable to the key holder. Key rotation limits forward exposure after a compromise, but prior records signed by the old key remain attributable. FieldWitness does not implement deniable authentication.

2.5 Insider Threat

Capability: Has legitimate access to the FieldWitness instance (e.g., a trusted administrator or a compromised org server). Can read key material, attestation records, and logs.

Goal: Selectively alter or delete records, export keys, or suppress evidence.

FieldWitness's position: The append-only hash chain makes deletion or modification of prior records detectable: the chain head hash changes and any external anchor (RFC 3161 TSA, blockchain transaction) will no longer match. Key rotation is logged in the chain as a fieldwitness/key-rotation-v1 record signed by the old key, creating an auditable trail.

Gap: An insider with direct filesystem access can overwrite chain.bin entirely, including the chain head, before an external anchor is taken. The chain provides integrity guarantees only to the extent that external anchors are taken regularly and independently (by another party or a public TSA). Frequency of anchoring is an operational decision, not enforced by the software.


3. Assets Protected

The following assets are in scope for FieldWitness's security model:

Asset Description Primary Protection
Attestation records Ed25519-signed records linking a file hash to a time, identity, and optional metadata Append-only chain, Ed25519 signatures
Identity private key Ed25519 private key used to sign attestations 0600 filesystem permissions, LUKS on Tier 1, killswitch
Channel key AES-256-GCM key used for steganographic encoding 0600 filesystem permissions, separate from identity key
Source submissions Anonymous uploads through the drop box EXIF stripping, no-branding upload page, HMAC receipt codes
Evidentiary metadata GPS, timestamp, device model extracted from EXIF Stored in attestation record, dangerous fields stripped
Federation topology Which organizations are peering Not protected at network level (see 2.1)

The following are out of scope (not protected by FieldWitness):

  • Source identity beyond what is stripped from EXIF
  • Operator identity (FieldWitness does not provide anonymity)
  • Content of files beyond what is hashed and signed (files are not encrypted at rest unless encrypted before attestation)
  • The Tier 3 relay's knowledge of federation topology

4. Trust Boundaries

[Field reporter / Tier 1] --- LUKS + killswitch --- [Seized device adversary]
         |
    [USB sneakernet or LAN]
         |
[Org Server / Tier 2] ------- TLS (self-signed) ---- [Network adversary]
         |                                            [Active attacker: no forged sigs]
    [Gossip federation]
         |
[Federation Relay / Tier 3] - Stores hashes+sigs only, no keys
         |
[Partner Org / Tier 2] ------ Ed25519 trust store -- [Untrusted peers rejected]
         |
[Verifying party] ----------- standalone verify.py, cryptography package only

Tier 1 trusts: Its own key material (generated locally), the Tier 2 server it was configured to sync with.

Tier 2 trusts: Its own key material, the Ed25519 public keys in its trust store (imported explicitly by the administrator), the Tier 3 relay for transport only (not content validation).

Tier 3 trusts: Nothing. It is a content-unaware relay. It cannot validate the semantic content of what it stores because it has no access to private keys.

Verifying party trusts: The signer's Ed25519 public key (received out-of-band, e.g., in the evidence package), the cryptography Python package, and the chain linkage logic in verify.py.


5. Security Guarantees

The following are properties FieldWitness is designed to provide. Each is conditional on the named preconditions.

G1: Attestation integrity. Given an attestation record and the signer's Ed25519 public key, a verifier can determine whether the record has been modified since signing. Precondition: The verifier has the correct public key and the cryptography package. Mechanism: Ed25519 signature over deterministic JSON serialization of the record.

G2: Chain append-only property. If a record is in the chain at position N, it cannot be removed or modified without invalidating every subsequent record's hash linkage. Precondition: The verifier has observed the chain head at some prior point or has an external anchor. Mechanism: Each record includes prev_hash = SHA-256(canonical_bytes(record[N-1])).

G3: Timestamp lower bound. If the chain head has been submitted to an RFC 3161 TSA and the token is preserved, all records prior to the anchored head provably existed before the TSA's signing time. Precondition: The TSA's clock and signing key are trusted. Mechanism: RFC 3161 timestamp tokens stored in chain/anchors/.

G4: Selective disclosure soundness. A selective disclosure bundle proves that the disclosed records are part of an unbroken chain without revealing the contents of non-disclosed records. Precondition: The verifier has the chain head hash from an external source. Mechanism: Non-selected records appear as hashes only; chain linkage is preserved.

G5: Federation record authenticity. Records received via federation are accepted only if signed by a key in the local trust store. Precondition: The trust store contains only keys the operator has explicitly imported. Mechanism: Ed25519 verification against trust store before appending federated records.

G6: Source drop box anonymity (limited). A source submitting via the drop box does not need an account, FieldWitness is not mentioned on the upload page, and dangerous EXIF fields are stripped before the file is stored. Precondition: The source accesses the drop box URL over HTTPS without revealing their identity through other means (IP, browser fingerprint, etc.). Limitation: FieldWitness does not route drop box traffic through Tor or any anonymization layer. Network-level anonymity is the source's responsibility.


6. Non-Guarantees

The following properties are explicitly not provided by FieldWitness. Including them here prevents users from assuming protection that does not exist.

NG1: Operator anonymity. FieldWitness does not hide the identity of the organization running the instance. The Tier 2 server has an IP address. The federation relay knows which Tier 2 servers are peering.

NG2: Deniable authentication. Attestation records are non-repudiably signed by Ed25519 keys. There is no plausible deniability about which key produced a signature.

NG3: Forward secrecy for attestation keys. Ed25519 identity keys are long-lived. If a private key is compromised, all attestations signed by that key are attributable to the key holder. Key rotation limits future exposure but does not retroactively remove attributability.

NG4: Protection against a compromised Tier 2 before anchoring. An insider with full Tier 2 access can rewrite the chain before any external anchor is taken. External anchors are the primary protection against insider tampering; their value is proportional to how frequently and independently they are taken.

NG5: Content confidentiality. FieldWitness does not encrypt attested files at rest. Files are hashed and signed, not encrypted. Encryption before attestation is the operator's responsibility.

NG6: Source protection beyond EXIF stripping. The drop box strips dangerous EXIF fields and does not log source IP addresses in attestation records. It does not provide the same source protection model as SecureDrop. Organizations with strong source protection requirements should use SecureDrop for intake and FieldWitness for evidence chain management.

NG7: Auditability of the Tier 3 relay. The relay stores only hashes and signatures, but FieldWitness does not currently provide a mechanism for operators to audit what the relay has and has not forwarded. The relay is trusted for availability, not integrity.


7. Cryptographic Primitives

All cryptographic choices are documented here to support independent review and long-term archival verifiability.

Signing

Primitive Algorithm Parameters Use
Identity signing Ed25519 RFC 8032 Sign attestation records, key rotation records, delivery acks
Key storage PEM PKCS8 (private), SubjectPublicKeyInfo (public) Disk format for identity keypair

Ed25519 was chosen for: short key and signature sizes (32-byte public key, 64-byte signature), deterministic signing (no random oracle required per operation), strong security margins, and wide library support.

Encryption (Stego channel key domain)

Primitive Algorithm Parameters Use
Symmetric encryption AES-256-GCM 256-bit key, 96-bit IV, 128-bit tag Payload encryption in stego encode
Key derivation Argon2id time=3, memory=65536, parallelism=4, saltlen=16 Derive AES key from passphrase + PIN + reference photo fingerprint

Note: The AES-256-GCM channel key domain (Stego) and the Ed25519 identity key domain (Attest) are kept strictly separate. They serve different security purposes and share no key material.

Hashing

Primitive Algorithm Use
Cryptographic hash SHA-256 Chain record linkage (prev_hash), content fingerprinting
Content fingerprinting SHA-256 ImageHashes.sha256 for all file types
Perceptual hash pHash (DCT-based) Image tamper detection, survives compression
Perceptual hash dHash (difference hash) Image tamper detection
Perceptual hash aHash (average hash) Fuzzy matching, high tolerance
Chain serialization CBOR (RFC 7049) Canonical encoding for chain records
HMAC HMAC-SHA256 Drop box receipt code derivation

External Timestamping

Mechanism Standard Use
RFC 3161 TSA RFC 3161 Automated, signed timestamp tokens
Manual anchor Any external witness Chain head hash submitted to blockchain, email, etc.

8. Key Management Model

Key types and locations

Key Type Location Purpose
Identity private key Ed25519 ~/.fwmetadata/identity/private.pem Sign all attestation records
Identity public key Ed25519 ~/.fwmetadata/identity/public.pem Shared with verifiers; included in evidence packages
Channel key AES-256-GCM ~/.fwmetadata/stego/channel.key Stego encoding/decoding shared secret
Trust store keys Ed25519 (public only) ~/.fwmetadata/trusted_keys/<fingerprint>/ Verify federated records from partners

Key rotation

Identity rotation creates a fieldwitness/key-rotation-v1 chain record signed by the old key, containing the new public key. This establishes a cryptographic chain of trust from the original key through all rotations. Verifiers following the rotation chain can confirm that new attestations come from the same organizational identity as old ones.

Channel (AES) key rotation creates a new key and archives the old one. Old channel keys are required to decode stego payloads encoded with them; archived keys are preserved under ~/.fwmetadata/stego/archived/.

Identity recovery

After device loss, a fieldwitness/key-recovery-v1 chain record is signed by the new key, carrying the old key's fingerprint and optional cosigner fingerprints. This is an auditable assertion, not a cryptographic proof that the old key authorized the recovery (the old key is lost). The recovery record's legitimacy depends on out-of-band confirmation (e.g., cosigner verification, organizational attestation).

Backup

The keystore manager (fieldwitness/keystore/manager.py) tracks backup state. Encrypted key bundles can be exported to the SOOBNDL format for cold storage. The backup reminder interval is configurable; the default is 7 days.


9. Federation Trust Model

Peer authentication

Federation peers are identified by their Ed25519 public key fingerprint (first 16 bytes of SHA-256 of the public key, hex-encoded). Peering is established by explicit administrator action: the peer's public key fingerprint is configured locally. There is no automatic peer discovery or trust-on-first-use.

Record acceptance

A record received via federation is accepted only if:

  1. It is signed by an Ed25519 key in the local trust store.
  2. The signature is valid over the record's canonical serialization.
  3. The record does not duplicate a record already in the local log (by record ID).

Records signed by unknown keys are silently dropped. There is no mechanism to accept records from temporarily trusted but unregistered peers.

The Tier 3 relay

The Tier 3 relay is a content-unaware intermediary. It forwards attestation bundles between Tier 2 nodes but has no access to private keys and cannot validate the semantic content of records. It is trusted for availability (it should forward what it receives) but not for integrity (it cannot be used as an authority for whether records are authentic).

Consistency proofs

During gossip sync, nodes exchange their current Merkle log root and size. If roots differ, the node with fewer records requests a consistency proof from the node with more records. The consistency proof proves that the smaller log is a prefix of the larger log, preventing log divergence. Records are fetched incrementally after the proof verifies.

The consistency proof implementation is in src/fieldwitness/attest/merkle.py.


10. Known Limitations

This section is a candid accounting of current gaps. Items here are candidates for future work, not dismissals.

L1: No hardware key storage. Private keys are stored as PEM files protected only by filesystem permissions and LUKS (on Tier 1). A hardware security module (HSM), TPM, or OS keychain would provide stronger protection against physical extraction from a running system. This is a significant gap for high-threat deployments.

L2: No certificate pinning for federation. Tier 2 to Tier 3 connections use TLS with self-signed certificates. The peer's certificate fingerprint is not currently pinned in configuration. An active network adversary with the ability to present a forged certificate could intercept federation traffic. The Ed25519 peer fingerprint provides a secondary check but is not a substitute.

L3: Killswitch reliability. The killswitch's effectiveness depends on the operating system's file deletion semantics. On HDDs without secure erase, file overwriting may not prevent forensic recovery. On SSDs with wear leveling, even overwriting does not guarantee physical deletion. The deep forensic scrub does multiple passes, but this is not equivalent to verified physical destruction. For critical-threat deployments, physical destruction of storage media is more reliable than software scrub.

L4: Anchor frequency is an operational decision. The chain's tamper-evidence properties against insider threats depend on how frequently external anchors are taken. FieldWitness does not enforce or automate anchor frequency. An organization that anchors infrequently has a larger window during which insider tampering is undetectable.

L5: Gossip topology is not hidden. The list of peers a node gossips with is visible to a network observer. For organizations where federation topology is itself sensitive information, all federation should be routed through Tor or equivalent.

L6: No audit of Tier 3 relay behavior. FieldWitness does not currently provide a way for operators to verify that the Tier 3 relay has faithfully forwarded all bundles it received. A malicious or compromised relay could suppress specific records. The design mitigation is 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 -- 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 stego channels are not guaranteed to be undetectable by modern ML-based steganalysis tools under all conditions. Stego should be treated as a covert channel with meaningful detection risk, not a guaranteed-invisible channel.

L9: No formal security proof. The security of FieldWitness's federation protocol, chain construction, and selective disclosure has not been formally analyzed. The design draws on established primitives (Ed25519, SHA-256, RFC 3161, Merkle trees) and patterns (gossip, append-only logs, Certificate Transparency-inspired consistency proofs), but informal design analysis is not a substitute for a formal proof or an independent security audit.