diff --git a/Privacy.md b/Privacy.md new file mode 100644 index 0000000..1d46f32 --- /dev/null +++ b/Privacy.md @@ -0,0 +1,148 @@ +# LinkLog Firefox Extension Privacy Validation + +Date: 2026-09-15 + +## Scope + +This report validates the privacy-relevant properties of the Firefox extension in `webextension/` only. It does not treat the LinkLog backend as part of the extension, except where the extension explicitly sends data to the user-configured backend. + +## Validation Method + +- Reviewed the extension manifest, popup and options scripts, localized privacy text, and packaged-page HTML. +- Searched the extension source for storage, permission, tab-capture, cookie, history, clipboard, and network APIs. +- Ran `python3 scripts/release/validate_release.py` to confirm the checked-in signed XPI and Firefox disclosure metadata are consistent. + +## Summary + +The extension's implemented privacy behavior is mostly consistent with its declared purpose: + +- It does not include telemetry, analytics, adtech, crash reporting, or third-party beaconing. +- It captures website activity only from the active tab when the user opens the popup. +- It stores long-lived account metadata locally, but keeps bearer session credentials in Firefox session storage rather than persistent extension storage. +- It sends captured link data only to the user-selected backend, plus standard extension-update traffic to the configured self-update URL. +- Firefox privacy disclosure metadata is present and validated for the signed XPI. + +The main residual privacy risk is that the extension accepts both `http` and `https` backend URLs. That is useful for local development, but a non-local HTTP backend would expose credentials and saved-link data in transit. + +## Verified Properties + +### 1. Declared Firefox permissions are narrow + +- Required permissions are limited to `activeTab` and `storage`. +- Host access is not pre-granted broadly at install time. Instead, the extension declares optional HTTP and HTTPS host permissions and requests access only for the specific backend origin entered by the user. +- The signed-release validator enforces the Firefox `data_collection_permissions` declaration of required `websiteActivity` and no optional data-collection categories. + +Assessment: consistent with a least-privilege model for a link-saving extension. + +### 2. Website activity access is limited to the active tab + +- The popup reads the current page title and URL via `browser.tabs.query({ active: true, currentWindow: true })`. +- No content scripts are injected into visited pages. +- No background/service-worker logic observes browsing continuously. + +Assessment: the extension collects the minimum page context needed for its stated function when the user explicitly opens the popup. + +### 3. Local storage use is bounded and understandable + +Persistent local storage: + +- `backendUrl` +- `email` +- `username` + +Session-scoped storage: + +- `accessToken` +- `refreshToken` +- `tokenExpiresAt` +- `deviceId` + +Observed behavior: + +- Access and refresh credentials are stored in `browser.storage.session`. +- Sign-out and token invalidation clear those session values and also remove older legacy token keys from `browser.storage.local`. +- Account-identifying metadata remains in persistent storage to preserve configuration across browser restarts. + +Assessment: token persistence is minimized appropriately, but the extension still retains backend/account metadata locally until changed or removed. + +### 4. Outbound network traffic is limited and attributable + +User-configured backend traffic: + +- `POST /api/auth/login` +- `POST /api/auth/refresh` +- `POST /api/auth/logout` +- `GET /api/auth/me` +- `GET /api/tags` +- `GET /api/public/config` +- `GET /api/user/plugins/mastodon` +- `GET /api/links/check` +- `GET /api/scrape` +- `POST /api/links` + +What the extension sends to the backend: + +- Sign-in credentials: email, password, optional OTP. +- Session tokens in `Authorization` headers after login. +- Link payloads: title, cleaned URL, comment, timestamp, and tags. +- Lookup values for duplicate detection and title scraping. + +Other network destinations: + +- Firefox self-update metadata and signed XPI download are configured via `webextension/updates.json` and the manifest `update_url` at `git.kolkman.org`. +- Repository links in the popup and options page go to `git.kolkman.org` only when the user clicks them. + +Assessment: no hidden third-party data sinks were found in the extension code. + +### 5. The extension avoids higher-risk browser APIs + +No use was found of: + +- cookies APIs +- browsing history APIs +- bookmarks APIs +- clipboard APIs +- native messaging +- remote script loading +- `XMLHttpRequest` or `sendBeacon` + +Assessment: this reduces both privacy scope and accidental data leakage paths. + +### 6. Packaged extension pages use a restrictive CSP + +- Extension pages declare `script-src 'self'; object-src 'none'`. +- Popup and options pages load only bundled local scripts and assets. + +Assessment: this materially lowers the risk of third-party script injection into extension pages. + +### 7. The privacy notice is broadly accurate, with one caveat + +The options page says the extension does not collect personal data beyond what is necessary to log links to the LinkLog server. That statement is broadly supported by the code, because the extension only stores and transmits data needed for authentication and link submission. + +Caveat: the notice would be more precise if it explicitly mentioned that the extension stores the configured backend URL, email address, and username locally, and stores session credentials for the current browser session. + +## Residual Privacy Risks + +### R1. Non-TLS backends are allowed + +The extension accepts `http` and `https` backend URLs. For local development this is reasonable, but for non-local use it means login credentials, tokens, titles, URLs, comments, timestamps, and tags can be transmitted without transport encryption. + +Recommendation: enforce `https` for non-localhost backends, or at minimum warn before allowing a non-TLS backend. + +### R2. Backend publication and retention are outside extension control + +The extension's privacy behavior ends once data is sent to the configured LinkLog server. The backend may publish links publicly, combine them with user profile data, retain them, or forward them through enabled plugins such as Mastodon. + +Recommendation: keep extension-facing privacy text explicit that saved link data becomes subject to the chosen backend's policies and configuration. + +### R3. Persistent local account metadata is not cleared on sign-out + +Sign-out clears session credentials, but leaves `backendUrl`, `email`, and `username` in persistent extension storage for convenience. + +Recommendation: this is a reasonable default, but the UI could offer a separate "forget this account on this browser" action. + +## Overall Conclusion + +The Firefox extension has a relatively narrow privacy footprint and largely follows least-privilege principles. Its privacy disclosure about website activity is implemented and release-validated, session tokens are kept in session storage, and no unexpected telemetry or third-party exfiltration paths were found in the extension code. + +The most important remaining privacy improvement is to prevent or strongly discourage non-HTTPS backends outside local development. \ No newline at end of file diff --git a/VIBE/CHAT_LOG.md b/VIBE/CHAT_LOG.md index c3c92a1..b7c4b99 100644 --- a/VIBE/CHAT_LOG.md +++ b/VIBE/CHAT_LOG.md @@ -151,6 +151,12 @@ Run full backend and frontend test suites. ### Assistant outcome The normal backend suite passed with 46 tests. Frontend and extension validation passed for all JavaScript syntax checks, JSON files, XPI rebuild, and unsigned XPI validation. The warnings-as-errors backend variant failed on unclosed SQLite connection `ResourceWarning` instances under Python 3.13; no functional tests failed. +### User +Validate the Privacy properties of the firefox plugin specifically and report them in Privacy.md + +### Assistant outcome +Added `Privacy.md` with a plugin-specific privacy validation covering manifest permissions, active-tab capture scope, local and session storage, outbound network destinations, Firefox `data_collection_permissions`, release validation, and residual privacy risks. Confirmed the signed XPI release metadata validates successfully and identified non-HTTPS backend support as the main remaining privacy caveat. + ### User Address SA-007 and use linklog.example.com as default LINKLOG_PUBLIC_URL. diff --git a/VIBE/PROMPTS.md b/VIBE/PROMPTS.md index 9c93b82..336dddb 100644 --- a/VIBE/PROMPTS.md +++ b/VIBE/PROMPTS.md @@ -318,6 +318,10 @@ If the user uses the filters and/or search in the toolbox then those should limi 259. Make sure the CHANGELOG reflects all changes since commit 74b2c400c6 260. Add a skill to maintain the changelog.md 261. In the new-entry form, provide a warning when the total ammount of characters is over LINKLOG_MAX_POST_CHARACTERS=500 (also indicat the number of characters used/500 count). This is to prevent Mastodon posts from failing - so all characters should be counted. + +## 2026-09-15 + +262. Validate the Privacy properties of the firefox plugin specifically and report them in Privacy.md 262. Implement the same functionality in the firefox plugin ## 2026-09-07