PostPilot Security Overview

This document describes how PostPilot handles your data, what leaves your machine, and what security practices are in place. It is intended for users who want to review the app before using it with sensitive credentials.


1. Architecture

PostPilot is a local-first desktop application built with Tauri (Rust backend) and a Nuxt frontend. There is no PostPilot cloud backend involved in your API calls, database queries, or data inspection work. All core operations run entirely on your machine.


2. Data Flow

  • HTTP requests go directly from your machine to the target server. PostPilot never sees the payload, headers, or response content.
  • Database queries execute directly from your machine to your database server — no data is routed through PostPilot infrastructure.
  • No request or response content is sent to PostPilot servers, logged to disk, or stored externally.

3. Credential Storage

Database Passwords

Database passwords are stored in your OS-native secure storage and are never written to disk in plaintext:

PlatformStorage
macOSKeychain Access
WindowsCredential Manager
LinuxSecret Service (GNOME Keyring / KWallet)

Workspace connection files contain only { "password": { "keychain": true } }. The actual password lives only in the OS keychain, retrieved at query time.

Environment Variables

Environment variables — including API keys, tokens, and any secret stored as {{variableName}} — are saved as plain JSON files inside your workspace folder under the environments/ directory. They are not encrypted at rest.

Recommendation: If you version-control your workspace with Git, add environments/ to your .gitignore to avoid accidentally committing secrets.


4. Network Communication

PostPilot makes outbound network requests in two situations only:

Your API Calls

HTTP requests you execute in PostPilot go directly from your machine to the target URL using the system network stack (Rust reqwest library). No content is routed through PostPilot servers. No request or response data is written to disk or app logs.

License Verification

On every app launch, PostPilot contacts https://license.postpilot.dev/api to verify your license. See Section 7 — License Service for the full breakdown of what is sent.


5. Offline Capability

Editing kits, running API requests, executing database queries, and inspecting data all work offline. License verification requires an internet connection on app startup. If the network is unavailable, the app will inform you.


6. Local Data Storage

File Structure (Desktop)

Workspace data is stored as human-readable JSON files in the folder you select when creating a workspace:

my-workspace/
├── workspace.json
├── environments/                   ← Variable values stored here in plaintext
│   └── <env-name>/
│       └── environment-variables.json
├── collections/                    ← HTTP and DB kit definitions (no secrets)
│   └── <collection>/
│       └── *.http.json
└── database-connections/           ← Connection metadata (no passwords)
    └── *.connection.json

What Is and Isn't Encrypted at Rest

DataWhereEncrypted?
Database passwordsOS KeychainYes (OS-managed)
Environment variablesWorkspace JSON fileNo — plaintext
HTTP kit contentWorkspace JSON fileNo
License keyApp data directoryNo (not a sensitive secret)
Device key (for license)OS secure storageYes (OS-managed)

7. License Service

Endpoint

All license operations contact: https://license.postpilot.dev/api

The app makes three types of requests to this endpoint:


Trial Creation — POST /licenses/trial

Sent once when starting a free trial.

{
  "device": {
    "id": "<32-char device ID, derived from public key hash>",
    "publicKey": "<ECDSA P-256 public key, base64 DER encoded>",
    "keyOrigin": "OS_SECURE",
    "keyType": "ECDSA_P256"
  }
}

License Activation — POST /licenses/activate

Sent once when activating a purchased license on a device.

{
  "licenseKey": "XXXX-XXXX-XXXX-XXXX",
  "device": {
    "id": "<device ID>",
    "publicKey": "<ECDSA P-256 public key, base64 DER encoded>",
    "keyOrigin": "OS_SECURE",
    "keyType": "ECDSA_P256"
  },
  "appVersion": "1.x.x"
}

License Verification — POST /licenses/verify

Sent on every app launch to confirm the license is still active.

{
  "licenseKey": "XXXX-XXXX-XXXX-XXXX",
  "deviceId": "<device ID>",
  "appVersion": "1.x.x"
}

This request is signed with your device's private key (stored in OS secure storage). The private key itself is never transmitted — only the cryptographic signature is sent, allowing the server to verify your device without ever seeing the key.


What Is Stored on Our Server

DataStored?Purpose
License key + statusYesTrack whether license is active, expired, or suspended
Device ID (public key hash)YesBind license to your device
Device public keyYesVerify cryptographic signatures on future requests
App version at activationYesVersion enforcement
Request/response payloadsNo
API keys or environment variablesNo
Hardware identifiersNo
IP address logsNo
Usage analyticsNo

Device Identity

Your device ID is derived as hex(sha256(publicKey)[0..16]) — a 32-character opaque identifier computed from your device's cryptographic public key. It does not directly expose any hardware identifiers.

Data Retention

  • Trial licenses: License records are stored to enforce the one-trial-per-device policy (trials are valid for 14 days; a new trial is available after 6 months). We do not yet automatically delete these records — this is a known gap we plan to address with a 6-month retention policy.
  • Perpetual licenses: Stored while your license is active. To request deletion, contact us directly.

8. Telemetry and Analytics

  • Desktop app: No telemetry, crash reporting, or usage analytics are collected.
  • Web version (postpilot.dev): Vercel Analytics is used for anonymous page visit counts only. No personal data, session behavior, or feature usage is tracked.

9. Auto-Update

The desktop app does not auto-update. There is no background update process. Updates are published to the website and must be downloaded and installed manually by the user.


10. Threat Model

What PostPilot Protects Against

  • Network interception of API/DB traffic: Requests never pass through PostPilot servers.
  • Database password exposure: Stored in the OS keychain — never written to any file.
  • License response tampering: Server responses are cryptographically signed with an RSA key embedded in the app binary. The app rejects responses that fail signature verification.
  • License replay attacks: Each verification uses a single-use nonce, so captured requests cannot be replayed.

What PostPilot Does Not Protect Against

  • A fully compromised OS: If your operating system or user account is compromised, files in your workspace folder (including environment variable files) are accessible to the attacker.
  • Environment variable exposure via filesystem access: These files are plaintext JSON. Anyone with read access to your workspace folder can read them.
  • Browser-level threats on the web version: localStorage is readable via browser devtools and accessible to scripts running on the same origin.

11. Web Version

The browser-based version of PostPilot has a different security profile from the desktop app:

AspectDesktopWeb
Data storageFilesystem (workspace folder)Browser localStorage
Credential storageOS Keychain for DB passwordsNo keychain — all localStorage
Database clientsSupportedNot supported
HTTP transportRust reqwest (direct)Browser Axios (CORS applies)
AnalyticsNoneVercel anonymous page visits
UpdatesManual downloadAlways latest deployed version

Recommendation: For work involving production credentials, database connections, or sensitive API keys, use the desktop app. The web version does not have access to OS-level secure storage.