From 1215b95df2f8b9a44a5fdc61f7d19e84da855719 Mon Sep 17 00:00:00 2001 From: PageZ948 Date: Wed, 19 Aug 2026 21:14:55 +0000 Subject: [PATCH] docs: record APT security hardening baseline --- .../2026-08-19-apt-security-foundation.md | 533 ++++++++++++++++++ docs/security/2026-08-security-baseline.md | 18 + 2 files changed, 551 insertions(+) create mode 100644 docs/plans/2026-08-19-apt-security-foundation.md create mode 100644 docs/security/2026-08-security-baseline.md diff --git a/docs/plans/2026-08-19-apt-security-foundation.md b/docs/plans/2026-08-19-apt-security-foundation.md new file mode 100644 index 0000000..d2484a3 --- /dev/null +++ b/docs/plans/2026-08-19-apt-security-foundation.md @@ -0,0 +1,533 @@ +# Alta Proxy Tool Security Foundation and Product Roadmap Implementation Plan + +> **For Hermes:** Use subagent-driven-development skill to implement this plan task-by-task. + +**Goal:** Remove APT’s Critical/Important security and release blockers, establish a reproducible Windows baseline, recover the Mac implementation into source control, and only then open a controlled lane for new features. + +**Architecture:** Keep Electron’s renderer unprivileged. Move session credentials, URL validation, proxy launching, process ownership, and update verification into small main-process modules with narrow IPC contracts. Development occurs in an isolated GitPeji worktree; existing Tool Hub downloads and production surfaces remain unchanged until a fully tested, exact-commit release is approved. + +**Tech Stack:** Electron, Node.js built-in `node:test`, Chrome Manifest V3 extension APIs, Electron Builder, GitPeji/Gitea Actions, SHA-256 release manifests, Windows Authenticode when available. + +--- + +## Executive sequencing + +### Phase A — Security containment and proof + +No feature work enters this phase. It must close: + +1. arbitrary-code self-updater; +2. CR/LF batch command injection; +3. renderer-controlled URL/cookie exfiltration; +4. cookie leakage through logs, temporary files, command lines, and broad clipboard handling; +5. stale/vulnerable Electron, Axios, and build dependencies. + +### Phase B — Product/release foundation + +1. canonical GitPeji source and exact tagged builds; +2. automated tests and CI; +3. reproducible Windows kit with helper provenance; +4. recover Mac source, then separately decide Intel/Rosetta versus native Apple Silicon; +5. safe, signed/digest-bound updater only after all earlier gates pass. + +### Phase C — New features + +Feature discovery begins only after Phase A passes independent security review and Phase B has a reproducible development build. New functions go into a written backlog with user value, permissions, data touched, risk, and acceptance tests before implementation. + +## Non-negotiable guardrails + +- GitPeji is the only source of truth. Do not fetch from, push to, publish on, or update from GitHub. +- Use a fresh worktree from GitPeji `master` at `a80074ac57b7a4517837b5d95754f5e6433df3ac` or newer. +- Preserve current Tool Hub downloads and production visibility until Zac approves replacement. +- Do not use real Alta cookies in automated tests; use conspicuous synthetic sentinels. +- Do not write cookies to logs, disk, command files, shell strings, crash reports, analytics, or test artifacts. +- No production release until the exact candidate passes controller verification plus independent security and release reviews. +- Mac distribution remains approval-gated under Kanban task `t_42bad4d3`. + +--- + +## Milestone 0: Establish an isolated hardening lane + +### Task 1: Create the clean GitPeji worktree and baseline evidence + +**Objective:** Start from an exact, clean canonical source without modifying the archived checkout. + +**Files:** +- Create worktree: `/home/peji/worktrees/apt-security-foundation` +- Create: `docs/security/2026-08-security-baseline.md` +- Reference: `/home/peji/.hermes/reports/alta-proxy-tool-full-review-2026-08-19.md` + +**Steps:** + +1. Fetch only GitPeji and verify `origin/master`. +2. Create branch `hardening/security-foundation` in the isolated worktree. +3. Record full starting SHA, remote, branch, clean status, dependency audit counts, current package version, and the review report path. +4. Confirm the archived checkout and Tool Hub checkout remain clean. +5. Commit only the baseline document. + +**Commands:** + +```bash +git fetch origin master +git worktree add -b hardening/security-foundation /home/peji/worktrees/apt-security-foundation origin/master +git -C /home/peji/worktrees/apt-security-foundation status --short --branch +``` + +**Expected:** clean branch based on exact GitPeji `origin/master`; no GitHub remote used. + +**Commit:** `docs: record APT security hardening baseline` + +--- + +## Milestone 1: Add a testable security boundary + +### Task 2: Introduce the smallest useful test harness + +**Objective:** Make security fixes test-first instead of relying on ad-hoc probes. + +**Files:** +- Modify: `package.json` +- Create: `test/url-policy.test.js` +- Create: `test/error-redaction.test.js` +- Create: `test/proxy-launch.test.js` +- Create: `test/update-policy.test.js` +- Create: `test/bridge-auth.test.js` +- Create: `src/url-policy.js` +- Create: `src/error-redaction.js` + +**Steps:** + +1. Add `npm test` using `node --test` and `npm run check` for syntax/tests. +2. Write failing URL-policy tests for: + - HTTPS Alta subdomains accepted; + - HTTP rejected; + - non-Alta hosts rejected; + - userinfo, fragments, unexpected paths/ports, CR/LF, and malformed URLs rejected. +3. Write failing error-redaction tests proving a synthetic `va=HERMES_SENTINEL_SECRET` never appears in formatted output. +4. Implement minimal pure helpers. +5. Run tests and syntax checks. + +**Commands:** + +```bash +npm test +npm run check +``` + +**Expected:** all tests pass; no source code needs Electron to test URL/redaction logic. + +**Commit:** `test: add APT security regression harness` + +--- + +## Milestone 2: Remove the Critical updater path + +### Task 3: Disable executable self-update completely + +**Objective:** Remove the current arbitrary-native-code installation surface before redesigning updates. + +**Files:** +- Modify: `main.js:454-630` +- Modify: `preload.js:25-37` +- Modify: `renderer.js:24-34,57-61,602-712,756-760` +- Modify: `index.html:38-41,84-106` +- Modify: `README.md:13,68-74,166` +- Test: `test/update-policy.test.js` + +**Steps:** + +1. Write failing source/contract tests asserting no `download-and-install-update` IPC method is exposed and no executable replacement code remains. +2. Remove updater IPC handlers, redirect downloader, executable overwrite batch script, progress event, and install controls. +3. Replace the UI with either no update control or a safe informational link to an authenticated/internal release page; do not download or execute anything. +4. Remove startup network update checks. +5. Run tests and confirm the app still starts/builds. + +**Acceptance:** no renderer-to-main path can download, overwrite, or launch an executable. + +**Commit:** `fix: remove unsafe in-place updater` + +--- + +## Milestone 3: Close command injection and process-control hazards + +### Task 4: Replace `.bat` construction with direct process spawning + +**Objective:** Eliminate command injection and plaintext cookie batch files. + +**Files:** +- Create: `src/proxy-launch.js` +- Modify: `main.js:26-31,274-387` +- Test: `test/proxy-launch.test.js` + +**Steps:** + +1. Write failing tests for CR/LF, shell metacharacters, malformed UUIDs, invalid domains, oversized cookie values, and missing helper. +2. Define strict input contracts: + - deployment host comes from validated main-process session state; + - device UUID matches the exact supported identifier shape; + - cookie length is bounded and never serialised into a command string; + - executable path is resolved from an approved fixed location. +3. Spawn `aware-cam-proxy.exe` directly with an argument array and `shell: false`. +4. Remove `sanitizeBatchInput()`, temporary `.bat` files, `cmd /c start`, and cookie-bearing echo output. +5. Capture only process ID, device ID, start time, and safe status metadata. +6. Add a Windows-specific smoke harness that substitutes a harmless fixture executable/script and records argv without exposing the cookie. + +**Acceptance:** the CR/LF reproducer is rejected; no batch/command file exists; cookie is not printed or persisted. + +**Commit:** `fix: launch proxy without shell command files` + +### Task 5: Stop only APT-owned proxy processes + +**Objective:** Prevent “Stop Proxy” from killing unrelated helper processes. + +**Files:** +- Modify: `src/proxy-launch.js` +- Modify: `main.js:389-452` +- Modify: `renderer.js:147-177` +- Test: `test/proxy-launch.test.js` + +**Steps:** + +1. Write a failing test proving only tracked child process IDs are terminated. +2. Replace `taskkill /im aware-cam-proxy.exe` with tracked-process termination. +3. Return per-device stop results and remove dead entries from the process map. +4. Handle already-exited and permission-denied states honestly. +5. Verify two fixture processes: stopping one leaves the other alive. + +**Commit:** `fix: scope proxy termination to APT processes` + +--- + +## Milestone 4: Move trust and cookies into the main process + +### Task 6: Replace renderer-supplied URL/cookie IPC parameters + +**Objective:** Prevent a compromised renderer from sending Alta cookies to arbitrary destinations. + +**Files:** +- Create: `src/session-store.js` +- Create: `src/alta-client.js` +- Modify: `main.js:192-272` +- Modify: `preload.js:5-12` +- Modify: `renderer.js:225-304,714-743` +- Test: `test/url-policy.test.js` +- Create: `test/alta-client.test.js` + +**Steps:** + +1. Write failing tests showing API methods reject renderer-provided URL/cookie fields. +2. Store deployment origin and cookie only in main-process memory. +3. Expose narrow IPC calls: `getDevices()`, `getDeviceSites()`, `getAuthInfo()`, `launchProxy(deviceId)`, `disconnect()`. +4. Revalidate HTTPS Alta origin inside the main process before every request. +5. Disable ambient proxy use for cookie-bearing requests unless a separately reviewed explicit enterprise-proxy configuration is later required. +6. Disable cross-origin redirects or validate every redirect before forwarding credentials. +7. Validate `event.senderFrame` against the app’s local file origin/window. +8. On disconnect and app quit, overwrite references and clear session state. + +**Acceptance:** renderer messages cannot choose a destination or supply/receive the bearer cookie. + +**Commit:** `fix: keep Alta session authority in the main process` + +### Task 7: Redact all network and process errors + +**Objective:** Ensure failures cannot print cookies or secret-bearing request configuration. + +**Files:** +- Modify: `src/error-redaction.js` +- Modify: `src/alta-client.js` +- Modify: `main.js` +- Test: `test/error-redaction.test.js` + +**Steps:** + +1. Add synthetic Axios errors containing secrets in headers, URLs, nested config, causes, and response bodies. +2. Format only bounded fields: operation, safe error code, HTTP status, timeout flag, and a sanitised message. +3. Remove all full-object `console.error(..., error)` calls from credential-bearing paths. +4. Add a source scan test for forbidden logging patterns. +5. Run a sentinel failure probe and assert zero secret occurrences in stdout/stderr. + +**Commit:** `fix: redact credentials from APT errors` + +--- + +## Milestone 5: Replace the public hard-coded bridge secret + +### Task 8: Add explicit extension pairing + +**Objective:** Stop treating `apt-local-bridge-token` as authentication. + +**Recommended v1 design:** keep loopback temporarily but pair the extension to the desktop app with a random per-install secret and a stable extension identity. Native Messaging is a later option if portability/setup proves acceptable. + +**Files:** +- Create: `src/bridge-auth.js` +- Modify: `main.js:12-145` +- Modify: `chrome-extension/manifest.json` +- Modify: `chrome-extension/popup.js` +- Create: `chrome-extension/options.html` +- Create: `chrome-extension/options.js` +- Test: `test/bridge-auth.test.js` +- Create: `test/extension-contract.test.js` + +**Steps:** + +1. Write failing tests for missing/wrong secret, unknown extension origin, replay/rotation, oversized body, slow body, and malformed JSON. +2. Generate a cryptographically random pairing secret and store it with user-only permissions under Electron `userData`. +3. Add a one-time pairing flow: desktop shows code; extension stores the resulting secret in `chrome.storage.local`. +4. Give the extension a stable ID and accept only that exact extension origin. +5. Compare secrets in constant time. +6. Add request/body deadlines and bounded concurrency before body reads. +7. Rotate/revoke pairing from the desktop UI. +8. Remove `apt-local-bridge-token` from source. + +**Acceptance:** a different Chrome extension cannot submit data even when it knows the source code; pairing can be revoked without reinstalling APT. + +**Commit:** `feat: add paired authentication for the Chrome bridge` + +### Task 9: Make clipboard token copying explicitly guarded + +**Objective:** Retain Zac’s requested copy function without presenting it as harmless. + +**Files:** +- Modify: `chrome-extension/popup.html` +- Modify: `chrome-extension/popup.js` +- Modify: `chrome-extension/popup.css` +- Test: `test/extension-contract.test.js` + +**Steps:** + +1. Require a deliberate confirmation for copying the full bearer token. +2. Show a concise warning that clipboard history/synchronisation may retain it. +3. Never auto-copy. +4. Clear extension references immediately after the operation. +5. Test cancellation, permission denial, missing/expired cookie, and success messaging. + +**Commit:** `fix: guard VA token clipboard export` + +--- + +## Milestone 6: Modernise dependencies and desktop hardening + +### Task 10: Upgrade Electron, Axios, and packaging dependencies + +**Objective:** Remove known dependency blockers without mixing in feature changes. + +**Files:** +- Modify: `package.json` +- Modify: `package-lock.json` +- Modify: `main.js:148-167` +- Remove dependency if unused: `crypto-js` +- Remove/replace: `electron-packager` + +**Steps:** + +1. Create a dependency-upgrade branch commit separately from behaviour changes. +2. Upgrade Electron to a currently supported major compatible with the target Windows estate. +3. Upgrade Axios and transitive packages to patched releases. +4. Remove unused `crypto-js` and deprecated `electron-packager` if source/runtime scans confirm no use. +5. Enable explicit renderer sandboxing and deny unexpected navigation/window creation. +6. Run full tests, `npm audit`, Electron smoke, and Windows package build. +7. Do not accept Critical/High runtime findings; document any build-only exception with CVE reachability evidence. + +**Acceptance:** zero Critical/High production audit findings; supported Electron line; app smoke passes. + +**Commit:** `chore: modernize Electron runtime and dependencies` + +--- + +## Milestone 7: Canonical source and reproducible releases + +### Task 11: Add helper provenance without committing the binary blindly + +**Objective:** Make the Windows kit reproducible and auditable while respecting vendor licensing. + +**Files:** +- Create: `vendor/aware-cam-proxy/README.md` +- Create: `vendor/aware-cam-proxy/checksums.json` +- Modify: `build-kit.ps1` +- Modify: `README.md` +- Create: `LICENSE` +- Create: `THIRD_PARTY_NOTICES.md` + +**Steps:** + +1. Confirm redistribution rights for Windows/macOS helper binaries; stop if unavailable. +2. Record approved filename, platform, architecture, version/source owner, exact size, SHA-256, and acquisition procedure. +3. Make the kit build reject any helper that does not match the approved manifest. +4. Replace `author: "Your Name"` and add accurate project/third-party licensing. +5. Add ZIP content, path-safety, extension-content, executable-presence, and checksum tests. + +**Commit:** `build: verify proxy helper provenance in release kits` + +### Task 12: Recover Mac implementation into GitPeji source + +**Objective:** Stop treating the Tool Hub Mac ZIP as source control. + +**Files:** +- Recover into: `src/proxy-launch.js` +- Modify: `package.json` +- Modify: `README.md` +- Create: `docs/platforms/macos.md` +- Test: `test/proxy-launch.test.js` + +**Steps:** + +1. Extract and diff the current Tool Hub Mac `app.asar` against the hardened source. +2. Port only reviewed platform logic; do not copy the stripped packaged `package.json` wholesale. +3. Reuse the direct-spawn/no-shell/session rules from Windows. +4. Add explicit x64 and arm64 packaging targets, but publish only architectures with a matching approved helper. +5. Test on Intel/Rosetta and a current Apple Silicon Mac. +6. Keep Kanban `t_42bad4d3` open until native Apple Silicon/helper support is proven or Zac explicitly accepts Rosetta-only scope. + +**Commit:** `feat: restore reviewed macOS source and build targets` + +### Task 13: Add GitPeji CI and exact-commit release evidence + +**Objective:** Build every release from one tagged GitPeji commit with retained evidence. + +**Files:** +- Create: `.gitea/workflows/ci.yml` +- Create: `.gitea/workflows/release.yml` +- Remove or retire: `.github/workflows/deploy-pages.yml` +- Modify: `docs/index.html` +- Create: `scripts/verify-kit.js` + +**Steps:** + +1. CI gate: `npm ci`, syntax, tests, audit policy, Windows unpacked build, kit verification, secret scan. +2. Release gate: tag/version match, clean source, approved helper checksum, exact artifact hashes, SBOM, checksums, retained logs. +3. Point docs/downloads to GitPeji or the approved Tool Hub route, never GitHub. +4. Publish no artifact automatically until the first manual release rehearsal passes. +5. Rehearse on a non-production candidate tag and verify fresh download/extraction. + +**Commit:** `ci: add GitPeji build and release gates` + +--- + +## Milestone 8: Reintroduce updates safely, if still worthwhile + +### Task 14: Decide whether APT actually needs in-place updates + +**Objective:** Avoid rebuilding a dangerous feature merely because it existed before. + +**Decision gate:** + +- Preferred simplest option: notify that a verified update exists and open the trusted Tool Hub/GitPeji release page; user installs it manually. +- In-place update is allowed only if code signing, digest verification, rollback, and platform-specific testing are available. + +**Deliverable:** `docs/decisions/0001-update-strategy.md` + +**Commit:** `docs: decide APT update strategy` + +### Task 15: Implement a verified updater only if the decision approves it + +**Objective:** Bind installation to an exact trusted release. + +**Files:** +- Create: `src/update-manifest.js` +- Create: `src/updater.js` +- Modify: `main.js` +- Modify: `preload.js` +- Test: `test/update-policy.test.js` + +**Required tests:** wrong host, redirect host change, wrong size, wrong SHA-256, wrong signature, downgrade, wrong platform/architecture, truncated body, oversized body, interrupted download, failed replacement, successful rollback. + +**Acceptance:** only a manifest-authenticated, platform-matched artifact can reach replacement code; failure leaves the installed executable intact. + +**Commit:** `feat: add manifest-verified GitPeji updates` + +--- + +## Milestone 9: Closure and controlled release + +### Task 16: Run adversarial security closure review + +**Objective:** Independently prove every Critical/Important finding is closed. + +**Required probes:** + +- arbitrary updater URL cannot execute; +- CR/LF proxy parameters cannot become commands; +- renderer cannot choose request destination or supply cookies; +- Axios failures contain no sentinel secret; +- bridge rejects unknown extension/wrong secret/slow bodies; +- cookies never appear in files, process command strings, logs, tests, ZIP metadata, or analytics; +- stop affects only APT-owned child processes; +- dependency audit and Electron support policy pass. + +**Output:** finding-to-fix closure matrix with exact tests and commit. + +### Task 17: Build a DEV release candidate and preserve production + +**Objective:** Give Zac a testable candidate without replacing current downloads. + +**Steps:** + +1. Query usage/confirm release lane before changing Tool Hub visibility. +2. Build exact tagged candidate and record artifact SHA-256. +3. Publish only to an isolated DEV/download location clearly marked pre-release. +4. Run Windows app, extension pairing, device discovery, proxy launch/stop, disconnect, error, and update-notification workflows. +5. Verify current production Tool Hub/download hashes did not change. +6. Request Zac acceptance. + +### Task 18: Promote only the accepted exact artifact + +**Objective:** Replace the existing release safely and reversibly. + +**Steps:** + +1. Preserve current Windows/Mac kits and hashes as rollback artifacts. +2. Promote the exact accepted candidate—do not rebuild. +3. Verify GitPeji tag/release, Tool Hub route, download size/hash, extension contents, Windows smoke, and analytics. +4. Keep Mac separate until its own acceptance gate passes. +5. Remove temporary DEV artifacts only after production verification and rollback proof. + +--- + +## Feature roadmap gate + +### Task 19: Capture and prioritise new functions with Zac + +**Objective:** Turn feature ideas into a safe, ordered backlog after the red flags are closed. + +For each feature record: + +- user/problem and field-engineer value; +- exact user journey; +- read versus write operations; +- Alta endpoints/data required; +- cookie/session impact; +- local helper/process impact; +- Windows/macOS parity expectation; +- failure and offline behaviour; +- acceptance tests; +- release risk and whether it can remain DEV-only. + +**Suggested buckets for the discussion:** + +1. **Proxy workflow improvements:** multi-camera queue, per-camera status, retry/diagnostics, safe logs. +2. **Commissioning:** thumbnail/stream health, recording/site checks, readiness report. +3. **Troubleshooting:** streams debug, recent alerts, support bundle. +4. **Operator UX:** saved non-secret deployment aliases, clearer helper detection, version/support panel. +5. **Platform:** native Apple Silicon, managed extension packaging, enterprise deployment. + +Do not implement feature buckets during the hardening branch. Create separate feature branches from the accepted security foundation. + +--- + +## Definition of “major red flags fixed” + +All must be true: + +- [ ] Unsafe updater removed or cryptographically verified. +- [ ] No shell/batch construction from user or renderer data. +- [ ] Main process owns deployment origin and cookies. +- [ ] Privileged IPC validates sender and strict schemas. +- [ ] No cookie in logs, files, command strings, or automatic clipboard actions. +- [ ] Loopback bridge uses revocable pairing and exact extension identity. +- [ ] Proxy stop is process-scoped. +- [ ] Supported Electron/Axios versions; no Critical/High runtime audit findings. +- [ ] Automated tests and GitPeji CI pass. +- [ ] Windows kit is exact-commit reproducible with helper provenance. +- [ ] Mac source is canonical or Mac distribution remains explicitly withheld. +- [ ] Independent security closure review returns PASS. +- [ ] Existing production/download state remains unchanged until Zac approves promotion. diff --git a/docs/security/2026-08-security-baseline.md b/docs/security/2026-08-security-baseline.md new file mode 100644 index 0000000..d85bfd4 --- /dev/null +++ b/docs/security/2026-08-security-baseline.md @@ -0,0 +1,18 @@ +# APT security hardening baseline + +- Canonical source: GitPeji `peji/Alta-Proxy-Tool` +- Starting commit: `a80074ac57b7a4517837b5d95754f5e6433df3ac` +- Branch: `hardening/security-foundation` +- Original review: `/home/peji/.hermes/reports/alta-proxy-tool-full-review-2026-08-19.md` +- Implementation plan: `docs/plans/2026-08-19-apt-security-foundation.md` +- Starting package version: `1.0.0` +- Starting audit: 25 findings (1 critical, 22 high, 2 moderate); production-only audit 3 findings (2 high, 1 moderate) +- Starting release state: GitPeji/GitHub split-brain, no application CI, unsafe unsigned updater, no automated tests + +## Guardrails + +- GitPeji only; GitHub remote removed. +- Production Tool Hub and existing downloads remain unchanged. +- Synthetic sentinel credentials only in tests. +- Work remains on the isolated hardening branch until review gates pass. +- No feature additions until Critical/Important security closure.