ivx research

ivx research Disclosure Architecture

Architecture

Overview

Disclosure is a single-binary Go application that serves an HTML web interface and ActivityPub federation endpoints. It uses SQLite for storage and NaCl (libsodium) for end-to-end encryption.

┌─────────────────────────────────┐
│         Disclosure Server       │
│                                 │
│  ┌───────────┐  ┌────────────┐  │
│  │  Web UI   │  │ ActivityPub│  │
│  │  (HTTP)   │  │ Endpoints  │  │
│  └─────┬─────┘  └─────┬──────┘  │
│        │              │         │
│  ┌─────┴──────────────┴─────┐   │
│  │      Service Layer       │   │
│  │  Actor │ Report │ Program│   │
│  └────────────┬─────────────┘   │
│               │                 │
│  ┌────────────┴─────────────┐   │
│  │     SQLite Database      │   │
│  └──────────────────────────┘   │
└─────────────────────────────────┘

Key components

Web interface

The web interface is server-rendered HTML using Go templates and Tailwind CSS. It provides:

  • Dashboard — Overview of reports and programs
  • Report submission — End-to-end encrypted report forms
  • Program management — Create and configure bug bounty programs
  • Access control — Grant and request access to encrypted reports
  • Notifications — Real-time notifications for status changes

ActivityPub federation

Disclosure implements ActivityPub (the same protocol used by Mastodon) to enable federation between instances:

  • Announce — When a report is submitted, an Announce activity is sent to the vendor's inbox
  • Offer — Researchers can request access to reports on other instances
  • Accept — Vendors can grant access by sending encrypted keys
  • Disclose — Reports can be publicly disclosed, making them visible on the homepage

End-to-end encryption

All report content is encrypted using NaCl (libsodium):

  1. A symmetric key is generated for each report
  2. The content is encrypted with this key using XSalsa20-Poly1305
  3. The key is encrypted for each recipient using NaCl's box (public-key authenticated encryption)
  4. Only recipients with the corresponding private key can decrypt the key, then decrypt the content

This means the server operator cannot read any report content — only the researcher who submitted it and the vendor who has been granted access can decrypt it.

Authentication

Disclosure uses session-based authentication with HMAC-signed cookies. Passwords are stored as bcrypt hashes. There is no external OAuth — accounts are created via the CLI.

Rate limiting

Login and other sensitive endpoints are rate-limited per IP to prevent brute-force attacks.

CSRF protection

All state-changing requests require a CSRF token (double-submit cookie pattern) to prevent cross-site request forgery.

Security headers

The server sets standard security headers on every response:

  • X-Content-Type-Options: nosniff
  • X-Frame-Options: DENY
  • Referrer-Policy: strict-origin-when-cross-origin
  • Content-Security-Policy with strict defaults
  • Permissions-Policy: camera=(), microphone=(), geolocation=()