Poftim

Security architecture

What is protected—and what is not

Poftim creates an authenticated, temporary connection between two browsers. File contents and metadata are encrypted before entering the WebRTC transport. The service has not yet had an independent security audit, so this page documents the design and its limits rather than presenting an audit badge.

Summary

The short version

  • File contentsEncrypted end to end
  • File names, types and declared sizesEncrypted
  • Session keysDerived on the devices
  • Peer authenticationQR secret + matching phrase
  • Direct transportPreferred when available
  • Relay transportEncrypted and not stored
  • Independent assessmentNot completed

Threat model

The boundary of the promise

Designed to protect against

A signalling server or relay reading or changing file contents; a passive network observer reading transferred files; replayed or reordered encrypted frames; and a third device joining an already-claimed session.

Outside the protection

A compromised device, browser, extension or page; a recipient who saves or redistributes a file; traffic analysis; unsafe files accepted from another person; and denial-of-service or availability failures.

The matching phrase helps detect a connection that does not derive the same session keys. Compare it on both screens before continuing.

Pairing and keys

Fresh keys for every connection

Pairing secret
32 random bytes created by the host browser and carried in the QR URL fragment. The fragment is not included in the normal HTTP request.
Signalling
The secret derives an AES-256-GCM key that seals SDP, ICE candidates and ephemeral public keys before the signalling server forwards them.
Key agreement
Fresh ECDH P-256 key pairs establish a shared secret. HKDF-SHA-256 derives separate host-to-guest and guest-to-host keys.
Human check
Both devices derive the same short phrase from the session keys. A mismatch means the connection must be abandoned.
Key lifetime
The pairing secret is cleared after key agreement. Session keys remain in browser memory for the temporary connection.
Protocol
QRCABLE/1. Changes that affect interoperability require a protocol-version update.

File protection

Encrypted before transport

AES-256-GCM seals every control message and file chunk with a monotonic counter. The receiver rejects repeated frames, enforces file-chunk order and verifies an end-to-end SHA-256 digest before reporting a file as received.

A frame on the wire. Nine bytes of routing header — one byte of type and eight of counter — are readable by anything carrying the frame. Everything after them is an AES-256-GCM ciphertext and tag, opaque to the relay and to the server. SEALED · UNREADABLE IN TRANSIT TYPE COUNTER 1 BYTE 8 BYTES AES-256-GCM CIPHERTEXT + TAG
Metadata
Names, MIME types, declared sizes, modification times and file digests travel inside encrypted control frames.
Transport
An ordered WebRTC data channel adds DTLS protection beneath the application-level encryption.
Storage
The signalling service never carries file chunks. A TURN relay forwards encrypted packets and is not used as file storage.
Risky files
The receiving interface warns for common executable and active-content extensions. It does not scan files for malware.

Visible metadata

Encryption does not hide the connection itself

  • File contentsNot received in readable form
  • File names and typesEncrypted
  • Encryption keysNot sent to the server
  • Opaque session identifier and roleSeen by signalling
  • IP addressesProcessed by connection infrastructure
  • Connection timing and approximate volumeObservable
  • Transfer historyNot created by the application

Direct peers may learn each other’s network address. “Hide my network address” forces TURN relay transport so the peer does not receive a direct route, but the relay infrastructure still processes both addresses.

Important limitation

The browser must trust the delivered page

The QR fragment is not sent in the HTTP request, but JavaScript running on the page can read it. A compromised deployment, browser or extension could read pairing material, session keys or plaintext files.

The transfer page uses a restrictive Content Security Policy with script-src 'self', same-origin resources only, HTTPS with HSTS, framing protection and a no-referrer policy. No third-party script, advertising or analytics code is permitted to execute there — the policy served with the page refuses every external origin, so that is a property of the deployment rather than a promise about what we chose to include.

The document pages you are reading now — this one, how it works, privacy and the rest — are served under a separate, looser policy that permits Google Analytics after consent. They carry no session material, no keys and no file data. The transfer page and the pages describing it are deliberately not the same security surface.

These controls reduce exposure; they do not remove the need to trust the code delivered by poftim.app.

Sessions and infrastructure

Short-lived and deliberately sparse

Unscanned code
The in-memory signalling session expires after five minutes.
Connected idle session
The server-side idle deadline is fifteen minutes and is refreshed by active signalling.
One-time join
Only the first guest can claim a session. Closing the host invalidates its QR code.
Shared connection links
A link created with “Share connection” carries the same one-time secret as the QR code and is claimed the same way. It forces both devices onto the encrypted relay, so neither receives a direct network route to the other. Treat the link as the secret it is: anyone who reads it before the intended recipient can claim the session.
Received files after disconnect
Files that have finished arriving are held by the receiving page, not by the connection. Closing the connection — from either side — cannot withdraw them, and the receiver stays on the results screen until they leave the page.
Server state
Opaque session IDs, roles, connection state and expiry are held in memory. File metadata and contents are not stored there.
Web access logs
Query strings are excluded and IP addresses are truncated before being written to the configured access log.
Third parties
No third-party script, analytics, advertising or account provider runs in the application page, and its Content Security Policy permits no external origin that could. Funnel counts are sent to poftim.app itself, without cookies or any identifier. The separate document pages use Google Analytics after consent.

Browser compatibility

Current browsers, with practical differences

Poftim requires WebRTC data channels, Web Crypto support for ECDH P-256, HKDF and AES-GCM, JavaScript modules and Blob downloads.

It is designed for current Safari on iPhone and macOS, current Chromium browsers on Android, Windows, macOS and Linux, and current Firefox. Large-file saving, background suspension and memory behaviour differ between platforms.

A formal version-by-version browser and maximum-file test matrix has not yet been completed. Until it is, keep both pages open and screens awake, and avoid treating a particular maximum size as guaranteed.

Start a connection