Skip to content

Security: onesyue/yuelink

Security

SECURITY.md

Security Policy

YueLink ships a network client with VPN privileges. Security regressions have outsized blast radius. This file is the contract.


Reporting a vulnerability

If you believe you have found a security issue:

  1. Do not open a public issue.
  2. Email onesyue@gmail.com with subject prefix [SECURITY]. Include:
    • YueLink version (Settings → About).
    • Platform + OS version.
    • Reproduction steps.
    • Whether the issue is exploitable in default settings.
  3. We acknowledge within 72 hours and aim to fix within 14 days for critical issues, 30 days for high, 90 days for medium.

For public CVE assignment, we will request from MITRE after a fix is shipped and a coordinated disclosure window has passed.

Supported versions

Channel Supported
Latest stable (vX.Y.Z) ✅ Active support.
Previous stable (vX.Y.(Z-1)) ✅ Critical fixes only, until next stable ships.
Older stable ❌ Not supported. Upgrade.
Pre-release (pre / vX.Y.Z-pre) ⚠️ Best-effort. Issues acknowledged, fixes flow into the next stable.
Forks / unofficial builds ❌ Not supported.

Hard rules — do not violate

These are enforced by scripts/security_scan.sh (pre-commit + release gate) and .github/workflows/security.yml:

  1. No secrets in repo. No tokens, signing keys, API passwords, subscription URLs, or private node configurations. The scanner has FAIL patterns for the historic prod DB password and CloudFront tokens.
  2. No PII in logs. All log export paths must go through redactDiagnosticPii in lib/shared/diagnostic_report.dart. Redaction covers 13 classes — see that file for the canonical list. tool/automation/pii_redaction_guard.dart runs in CI.
  3. No subscription tokens in URL query strings. Tokens go in the Authorization: Bearer header. _buildClient in lib/infrastructure/datasources/xboard/client.dart is the only sanctioned HTTP client for XBoard calls.
  4. WebSocket secrets via header, not URL — MihomoStream uses IOWebSocketChannel.connect(uri, headers: {Authorization: ...}).
  5. No credential persistence in plain JSON unless it is in flutter_secure_storage or — on macOS — SecureStorageService's AES-256-GCM file (the only sanctioned exception, see CLAUDE.md).
  6. No bypassing platform restrictions. No anti-detection, no fake profile signatures, no help-evade-VPN-checks code. App-store builds compile with STANDALONE=false and disable in-app updater.

Dependency policy

Source Policy
pubspec.yaml (Dart/pub) Dependabot, weekly. Patch may auto-merge with green CI. Minor / major manual.
core/go.mod, service/go.mod (Go) Dependabot, weekly. govulncheck on every PR + weekly schedule. Patch may auto-merge.
.github/workflows/* (Actions) Dependabot, weekly. SHA-pinned where the action is third-party.
core/mihomo (submodule) Manual bump per governance/mihomo-bump-cadence.md. Stay on Meta, never Alpha.
Native binary deps (Wintun, geo data) Pinned by SHA-256 in repo. CI verifies on every Windows leg. Bumps go through a tracked PR.

CVE response SLA:

  • Critical with fix available: ship within 7 days.
  • High with fix available: ship within 14 days.
  • Medium: ship in next planned release.
  • No fix available: open a tracking issue, document mitigation, watch upstream.

govulncheck and dependency-review-action block PRs that introduce high-severity vulnerabilities without a follow-up plan in the PR body.

Secret scanning & push protection

  • GitHub native secret scanning + push protection: enabled. Maintain this in repo settings; not configurable per-PR.
  • Working-tree scanner: scripts/security_scan.sh (run by pre-commit hook + release-gate.yml). Patterns include Postgres DSNs, XBoard subscription URLs, Bearer tokens, the historic leaked password.
  • A FAIL finding blocks commits and releases. Allowlisting is via scripts/security_scan.allowlist with a comment explaining why.

Code scanning

  • gitleaks runs on every PR (security.yml).
  • govulncheck runs against core/ and service/ Go modules.
  • dependency-review-action runs on every PR with a config gating new high-severity dependencies.
  • CodeQL is not currently configured for Dart (unsupported language). Go CodeQL coverage is opt-in via security.yml and considered SHOULD-have.

Privacy

  • Telemetry is opt-in (default off) and clearly disclosed in Settings.
  • Telemetry events are anonymous — client_id is a random UUID stored in SettingsService, never linked to user account. Joining client_id to user_id is forbidden by feedback_north_star_two_layer policy.
  • Diagnostic exports redact 13 PII classes before any file leaves the device. Validated in CI by pii_redaction_guard.dart.

Operational hardening

  • master and release are protected branches. PR + CI required.
  • Required status checks: analyze, release-gate, security (where configured).
  • Force pushes to protected branches are blocked at the repo settings level. Do not enable, even temporarily.
  • Signing keys live outside the repo; CI uses repo / org secrets only.
  • Rotating any signing key follows docs/security/credential_rotation_sop.md.

Audit trail

Every security-relevant change leaves a record:

  • Commits land via PR.
  • Workflow runs are retained for 90 days.
  • governance/ archives sprint-level investigation notes.
  • docs/security/history_scan_report.md is the canonical record of past history scans.

There aren't any published security advisories