# freedomofpress/dangerzone architecture

> Architecture diagram of the GitHub repository freedomofpress/dangerzone, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-11-13). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/freedomofpress/dangerzone
- Repository: https://github.com/freedomofpress/dangerzone

## Overview

Dangerzone sanitizes untrusted documents by converting them in an isolation environment to RGB pixel data, then rebuilding a PDF outside the sandbox. Users initiate conversion through the CLI or GUI; document state and conversion coordination lead to a selected isolation provider. OCR is an optional conversion capability. Startup prepares platform-specific runtimes, while a separate updater checks releases and installs verified container images. The README documents the conversion stages; sampled source confirms the CLI, orchestration, provider, settings, and update responsibilities, but not every internal conversion call.

Main entry points: [`dangerzone/startup.py`](https://github.com/freedomofpress/dangerzone/blob/main/dangerzone/startup.py) (Startup tasks), [`dangerzone/updater/installer.py`](https://github.com/freedomofpress/dangerzone/blob/main/dangerzone/updater/installer.py) (Image installer), [`dangerzone/cli.py`](https://github.com/freedomofpress/dangerzone/blob/main/dangerzone/cli.py) (CLI), [`dangerzone/logic.py`](https://github.com/freedomofpress/dangerzone/blob/main/dangerzone/logic.py) (Conversion coordinator)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_entry["User interfaces"]
  node_cli["CLI<br/>[cli.py]"]
  node_gui["GUI<br/>[main_window.py]"]
  node_gui_logic["GUI logic<br/>[logic.py]"]
end

subgraph group_conversion["Document conversion"]
  node_document["Document model<br/>[document.py]"]
  node_conversion_logic["Conversion coordinator<br/>[logic.py]"]
  node_provider_base["Provider base<br/>[base.py]"]
  node_sandbox_convert["Sandbox conversion<br/>[base.py]"]
  node_pixel_data["RGB pixel data<br/>[base.py]"]
  node_safe_pdf["Safe PDF output<br/>[base.py]"]
  node_conversion_errors["Conversion errors"]
end

subgraph group_runtime["Isolation and startup"]
  node_container_provider["Container provider<br/>[container.py]"]
  node_qubes_provider["Qubes provider<br/>[qubes.py]"]
  node_dummy_provider["Dummy provider<br/>[dummy.py]"]
  node_startup["Startup tasks<br/>[startup.py]"]
  node_container_runtime["Container utilities<br/>[container_utils.py]"]
  node_podman_machine["Podman machine<br/>[machine.py]"]
end

subgraph group_updates["Updates and settings"]
  node_settings[("Settings<br/>[settings.py]")]
  node_release_check["Release checks<br/>[releases.py]"]
  node_image_verify["Image signatures<br/>[signatures.py]"]
  node_image_install["Image installer<br/>[installer.py]"]
  node_log_index["Log index<br/>[log_index.py]"]
end

node_user(("User"))

node_user -->|"submits files"| node_cli
node_user -->|"selects documents"| node_gui
node_cli -->|"runs startup"| node_startup
node_cli -->|"creates documents"| node_document
node_gui -->|"uses logic"| node_gui_logic
node_gui_logic -->|"coordinates conversion"| node_conversion_logic
node_conversion_logic -->|"uses provider"| node_provider_base
node_conversion_logic -->|"handles documents"| node_document
node_provider_base -->|"converts in sandbox"| node_sandbox_convert
node_sandbox_convert -->|"produces pixels"| node_pixel_data
node_pixel_data -->|"rebuilds PDF"| node_safe_pdf
node_provider_base -->|"raises errors"| node_conversion_errors
node_startup -->|"initializes machine"| node_podman_machine
node_startup -->|"checks Qubes"| node_qubes_provider
node_container_provider -->|"uses runtime"| node_container_runtime
node_startup -->|"reads settings"| node_settings
node_startup -->|"installs image"| node_image_install
node_image_install -->|"manages images"| node_container_runtime
node_image_install -->|"reads index"| node_log_index
node_image_install -->|"uses signatures"| node_image_verify
node_image_verify -->|"loads image"| node_container_runtime
node_release_check -->|"reads preferences"| node_settings
node_image_install -->|"reads preferences"| node_settings
node_cli -->|"starts conversion"| node_conversion_logic
node_dummy_provider -->|"implements provider"| node_provider_base

click node_cli "https://github.com/freedomofpress/dangerzone/blob/main/dangerzone/cli.py"
click node_gui "https://github.com/freedomofpress/dangerzone/blob/main/dangerzone/gui/main_window.py"
click node_gui_logic "https://github.com/freedomofpress/dangerzone/blob/main/dangerzone/gui/logic.py"
click node_document "https://github.com/freedomofpress/dangerzone/blob/main/dangerzone/document.py"
click node_conversion_logic "https://github.com/freedomofpress/dangerzone/blob/main/dangerzone/logic.py"
click node_provider_base "https://github.com/freedomofpress/dangerzone/blob/main/dangerzone/isolation_provider/base.py"
click node_sandbox_convert "https://github.com/freedomofpress/dangerzone/blob/main/dangerzone/isolation_provider/base.py"
click node_pixel_data "https://github.com/freedomofpress/dangerzone/blob/main/dangerzone/isolation_provider/base.py"
click node_safe_pdf "https://github.com/freedomofpress/dangerzone/blob/main/dangerzone/isolation_provider/base.py"
click node_container_provider "https://github.com/freedomofpress/dangerzone/blob/main/dangerzone/isolation_provider/container.py"
click node_qubes_provider "https://github.com/freedomofpress/dangerzone/blob/main/dangerzone/isolation_provider/qubes.py"
click node_dummy_provider "https://github.com/freedomofpress/dangerzone/blob/main/dangerzone/isolation_provider/dummy.py"
click node_startup "https://github.com/freedomofpress/dangerzone/blob/main/dangerzone/startup.py"
click node_container_runtime "https://github.com/freedomofpress/dangerzone/blob/main/dangerzone/container_utils.py"
click node_podman_machine "https://github.com/freedomofpress/dangerzone/blob/main/dangerzone/podman/machine.py"
click node_settings "https://github.com/freedomofpress/dangerzone/blob/main/dangerzone/settings.py"
click node_release_check "https://github.com/freedomofpress/dangerzone/blob/main/dangerzone/updater/releases.py"
click node_image_verify "https://github.com/freedomofpress/dangerzone/blob/main/dangerzone/updater/signatures.py"
click node_image_install "https://github.com/freedomofpress/dangerzone/blob/main/dangerzone/updater/installer.py"
click node_log_index "https://github.com/freedomofpress/dangerzone/blob/main/dangerzone/updater/log_index.py"
click node_conversion_errors "https://github.com/freedomofpress/dangerzone/blob/main/dangerzone/conversion_errors.py"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_cli,node_gui,node_gui_logic,node_user toneBlue
class node_document,node_conversion_logic,node_provider_base,node_sandbox_convert,node_pixel_data,node_safe_pdf,node_conversion_errors toneAmber
class node_container_provider,node_qubes_provider,node_dummy_provider,node_startup,node_container_runtime,node_podman_machine toneMint
class node_settings,node_release_check,node_image_verify,node_image_install,node_log_index toneRose
```

## Components

### User interfaces

- [CLI](https://github.com/freedomofpress/dangerzone/blob/main/dangerzone/cli.py): `dangerzone/cli.py`
- [GUI](https://github.com/freedomofpress/dangerzone/blob/main/dangerzone/gui/main_window.py): `dangerzone/gui/main_window.py`
- [GUI logic](https://github.com/freedomofpress/dangerzone/blob/main/dangerzone/gui/logic.py): `dangerzone/gui/logic.py`

### Document conversion

- [Document model](https://github.com/freedomofpress/dangerzone/blob/main/dangerzone/document.py): `dangerzone/document.py`
- [Conversion coordinator](https://github.com/freedomofpress/dangerzone/blob/main/dangerzone/logic.py): `dangerzone/logic.py`
- [Provider base](https://github.com/freedomofpress/dangerzone/blob/main/dangerzone/isolation_provider/base.py): `dangerzone/isolation_provider/base.py`
- [Sandbox conversion](https://github.com/freedomofpress/dangerzone/blob/main/dangerzone/isolation_provider/base.py): `dangerzone/isolation_provider/base.py`
- [RGB pixel data](https://github.com/freedomofpress/dangerzone/blob/main/dangerzone/isolation_provider/base.py): `dangerzone/isolation_provider/base.py`
- [Safe PDF output](https://github.com/freedomofpress/dangerzone/blob/main/dangerzone/isolation_provider/base.py): `dangerzone/isolation_provider/base.py`
- [Conversion errors](https://github.com/freedomofpress/dangerzone/blob/main/dangerzone/conversion_errors.py): `dangerzone/conversion_errors.py`

### Isolation and startup

- [Container provider](https://github.com/freedomofpress/dangerzone/blob/main/dangerzone/isolation_provider/container.py): `dangerzone/isolation_provider/container.py`
- [Qubes provider](https://github.com/freedomofpress/dangerzone/blob/main/dangerzone/isolation_provider/qubes.py): `dangerzone/isolation_provider/qubes.py`
- [Dummy provider](https://github.com/freedomofpress/dangerzone/blob/main/dangerzone/isolation_provider/dummy.py): `dangerzone/isolation_provider/dummy.py`
- [Startup tasks](https://github.com/freedomofpress/dangerzone/blob/main/dangerzone/startup.py): `dangerzone/startup.py`
- [Container utilities](https://github.com/freedomofpress/dangerzone/blob/main/dangerzone/container_utils.py): `dangerzone/container_utils.py`
- [Podman machine](https://github.com/freedomofpress/dangerzone/blob/main/dangerzone/podman/machine.py): `dangerzone/podman/machine.py`

### Updates and settings

- [Settings](https://github.com/freedomofpress/dangerzone/blob/main/dangerzone/settings.py): `dangerzone/settings.py`
- [Release checks](https://github.com/freedomofpress/dangerzone/blob/main/dangerzone/updater/releases.py): `dangerzone/updater/releases.py`
- [Image signatures](https://github.com/freedomofpress/dangerzone/blob/main/dangerzone/updater/signatures.py): `dangerzone/updater/signatures.py`
- [Image installer](https://github.com/freedomofpress/dangerzone/blob/main/dangerzone/updater/installer.py): `dangerzone/updater/installer.py`
- [Log index](https://github.com/freedomofpress/dangerzone/blob/main/dangerzone/updater/log_index.py): `dangerzone/updater/log_index.py`

### Other components

- **User**

## Connections

- User → CLI: submits files (evidence: `dangerzone/cli.py`)
- User → GUI: selects documents (evidence: `dangerzone/gui/main_window.py`)
- CLI → Startup tasks: runs startup (evidence: `dangerzone/cli.py`)
- CLI → Document model: creates documents (evidence: `dangerzone/cli.py`)
- GUI → GUI logic: uses logic (evidence: `dangerzone/gui/main_window.py`)
- GUI logic → Conversion coordinator: coordinates conversion (evidence: `dangerzone/gui/logic.py`)
- Conversion coordinator → Provider base: uses provider (evidence: `dangerzone/logic.py`)
- Conversion coordinator → Document model: handles documents (evidence: `dangerzone/logic.py`)
- Provider base → Sandbox conversion: converts in sandbox (evidence: `dangerzone/isolation_provider/base.py`)
- Sandbox conversion → RGB pixel data: produces pixels (evidence: `dangerzone/isolation_provider/base.py`)
- RGB pixel data → Safe PDF output: rebuilds PDF (evidence: `dangerzone/isolation_provider/base.py`)
- Provider base → Conversion errors: raises errors (evidence: `dangerzone/isolation_provider/base.py`)
- Startup tasks → Podman machine: initializes machine (evidence: `dangerzone/startup.py`)
- Startup tasks → Qubes provider: checks Qubes (evidence: `dangerzone/startup.py`)
- Container provider → Container utilities: uses runtime (evidence: `dangerzone/isolation_provider/container.py`)
- Startup tasks → Settings: reads settings (evidence: `dangerzone/startup.py`)
- Startup tasks → Image installer: installs image (evidence: `dangerzone/startup.py`)
- Image installer → Container utilities: manages images (evidence: `dangerzone/updater/installer.py`)
- Image installer → Log index: reads index (evidence: `dangerzone/updater/installer.py`)
- Image installer → Image signatures: uses signatures (evidence: `dangerzone/updater/installer.py`)
- Image signatures → Container utilities: loads image (evidence: `dangerzone/updater/signatures.py`)
- Release checks → Settings: reads preferences (evidence: `dangerzone/updater/releases.py`)
- Image installer → Settings: reads preferences (evidence: `dangerzone/updater/installer.py`)
- CLI → Conversion coordinator: starts conversion (evidence: `dangerzone/cli.py`)
- Dummy provider → Provider base: implements provider (evidence: `dangerzone/isolation_provider/dummy.py`)
