# PhoneToPC Security Hardening Report

Date: 2026-07-26

## Scope

- PersonalCloud.Server, PersonalCloud.Relay and PhoneToPC.Host
- Android application
- Windows and relay deployment packages
- Live relay at `relay.phonetopc.eu`
- VPS host, Docker runtime, Caddy, SSH, firewall and fail2ban
- Source, generated artifacts and dependency vulnerability scans

No secret values are included in this report.

## Fixed Findings

### Secret exposure and credential handling

- Permanently removed 37 obsolete deploy archives containing configured secrets,
  user hashes, device data or `.env` files.
- Removed four stale generated secret files and five additional secret-bearing
  files from old security/build artifacts.
- Rotated the live relay admin password, JWT signing key and device agent key.
- Preserved the pairing account so existing Android pairing remains usable.
- Restricted operational `.env` and agent-key ACLs to the owner, SYSTEM and
  Administrators.
- Stopped the relay agent from sending the PC API key or direct PC URLs.
- Replaced the legacy Windows packager with
  `deploy/New-SecureWindowsDesktopPackage.ps1`. The new packager blocks `.env`,
  credentials, relay data, logs, storage and other runtime state.

### Server and relay request security

- Fixed sibling-prefix path traversal in trash path resolution.
- Removed the relay's direct HTTP fallback and its SSRF-capable device URL fields.
  A missing websocket tunnel now fails closed with HTTP 503.
- Stopped trusting caller-controlled forwarded host, scheme and IP headers.
- Added request-body limits to authentication and control endpoints.
- Added relay agent authentication rate limiting and safer rate-limit keys.
- Added device ID, device name, library, username and password validation.
- Removed internal exception details from responses returned through the relay.
- Added atomic JSON persistence and private directory/file permissions.

### Upload, image and Android security

- Limited thumbnail source size to 512 MiB and image dimensions to 200 million
  pixels before decode to reduce image/decompression bomb risk.
- Kept upload endpoints outside small control-body limits while retaining file,
  request, count, extension and free-disk policies.
- Stopped Android API keys, relay passwords and access tokens from being saved in
  activity saved-state bundles.
- Retained Android Keystore AES-GCM secret storage.
- Enabled screen-content protection by default for fresh Android installs.

### Container and VPS hardening

- Relay runs as UID/GID `10001:10001`, not root.
- Relay root filesystem is read-only with all Linux capabilities dropped and
  `no-new-privileges`.
- Caddy also uses a read-only filesystem, dropped capabilities and only the
  bind-service capability required for ports 80/443.
- Relay data directory is mode `700`; user/device files are mode `600`.
- Container builds now apply Ubuntu package upgrades before installing runtime
  dependencies. The rebuilt image upgraded 11 base packages.
- Updated 45 VPS packages, including AppArmor, nftables, runc, Docker Compose,
  networking, initramfs and guest tools.
- Rebooted from kernel `6.8.0-90` into `6.8.0-136`.
- Verified SSH password and keyboard-interactive authentication are disabled.
- Verified UFW, fail2ban and Docker are active.
- Verified only ports 22, 80 and 443 are publicly listening.

## Verification

- `dotnet build PersonalCloud.sln`: success, 0 warnings, 0 errors.
- Android debug and release builds: success, including release lint.
- `Test-PhoneToPC-SecurityRegression.ps1`: all tests passed.
- `Test-PhoneToPC-RemoteGate.ps1 -KeepRunnerAlive`: all checks passed at
  `2026-07-26T12:48:12.7323147Z`.
- Live remote upload, list and delete smoke test: passed.
- Reconnect after VPS reboot: automatic; heartbeat and websocket tunnel connected.
- NuGet vulnerable transitive package audit: 0 findings.
- OSV Scanner 2.4.0 PhoneToPC source audit: 0 findings.
- Gitleaks 8.30.1 workspace audit: 0 findings.
- Gitleaks artifacts audit after cleanup: 0 findings.
- Gitleaks generated Windows package audit: 0 findings.
- Generated Windows ZIP: 970 entries, 0 forbidden entries; host, server and relay
  executables present.
- Live HTTP checks: HSTS, CSP, frame denial and content-type protection present;
  TRACE rejected, public registration denied, unsigned JWT denied and CORS not
  opened.
- Live TLS/Nmap checks: TLS 1.2 strong cipher set; top 1000 TCP scan exposed only
  22, 80 and 443.
- Bitdefender antivirus/firewall services: active; latest update check reported no
  available update and no update error.

## Current Live State

- Relay health: OK
- Device: `Onur-PC`
- Tunnel: connected
- Heartbeat: connected
- Public relay: `https://relay.phonetopc.eu`
- Local server: `http://127.0.0.1:5157`
- Current secure relay package:
  `deploy/relay-runtime-deploy-20260726-144149.zip`
- Current secure Windows package:
  `deploy/phonetopc-windows-20260726-150159.zip`

## Operational Notes

- Do not restore old deploy ZIP files or the legacy Windows packager from backups.
- Do not place configured secrets in source `appsettings.json` files.
- Rotate the pairing account only during a planned re-pairing window, because it
  will require Android devices to scan a new QR code.
- Re-run the security regression and remote gate before every live relay deploy.
