# Security Policy ## Reporting Vulnerabilities **Do not** open public GitHub issues for security vulnerabilities. Report vulnerabilities privately via: - GitHub Security Advisories (preferred): use the "Report a vulnerability" button on the Security tab. - Email: security@vaultkeepr.xyz Please include: - A clear description of the issue and its impact. - Steps to reproduce (proof of concept if possible). - The affected package(s) and version(s). ## Scope This policy covers the open-source packages and Solidity contracts in this repository: `packages/core`, `packages/sync`, `packages/ipfs`, `packages/recovery`, `packages/premium`, `packages/wallet-messages`, `packages/smart-account`, `packages/cloud`, `packages/alias`, `packages/logger`, `packages/i18n`, `packages/ui`, `packages/sentry`, `packages/legacy`, `packages/ocr-native`, and `contracts/`. The web app, browser extension, iOS/Android apps, and the enterprise/API server are in a private repository and are **out of scope** for this public policy. ## Response We acknowledge reports within 48 hours and aim to provide a fix or mitigation within 30 days, depending on severity. Coordinated disclosure is appreciated. ## Secret and Credential Management Policy - **Storage**: CI credentials live exclusively in encrypted GitHub Actions secrets (e.g. `SCORECARD_TOKEN`). They are never committed, logged, or passed to third-party services beyond their intended workflow. - **No secrets in code**: secret scanning with push protection is enabled; any pushed secret is blocked before it reaches the repository. - **Least privilege**: the default `GITHUB_TOKEN` is read-only; jobs that need more (CodeQL upload, Scorecard publish) declare minimal job-level permissions explicitly. - **Rotation**: CI secrets are rotated at least every 90 days, immediately after any suspected exposure, and whenever a person with admin access leaves the project. - **Local development**: local `.env` files are gitignored; wallet keys and production credentials are never stored in this repository. ## Vulnerability Remediation Policy **SCA (dependency) findings** (Dependabot + lockfile scanning): | Severity | Remediation target | |---|---| | Critical / High | Fix or mitigate within 7 days | | Medium | Within 30 days | | Low | Within 90 days or accepted with written justification | License policy: dependencies shipped to clients must carry permissive licenses (MIT, BSD, Apache-2.0, ISC); copyleft licenses are restricted to development-only tooling. Violations block the dependency update. **Pre-release check**: before any official release, all open Critical/High SCA findings must be fixed, mitigated, or explicitly accepted in the release notes. ### Accepted Risk Register Open SCA findings that cannot be remediated upstream are documented here with their exposure assessment. Each entry is re-evaluated monthly and removed as soon as a patched version becomes available. | Advisory | Package | Sev | Status | Rationale | |---|---|---|---|---| | [GHSA-w3rx-r6r6-pgpr](https://github.com/advisories/GHSA-w3rx-r6r6-pgpr) | image-size (via `metro@0.87.0`) | High | Accepted 2026-09-09 | Infinite loop in the ICNS parser: a buffer with valid magic bytes and a zero-valued entry length field never advances the offset, so the `while` loop blocks the Node.js event loop permanently. **No patched release exists** (latest `image-size@2.0.2` is affected; OSV lists `patched: <0.0.0`); the vulnerable `image-size@1.2.1` is pulled transitively by the React Native bundler used by `packages/ocr-native`. Exposure is build-time only: metro parses local asset files of the developer's own repo during bundling — no attacker-controlled buffer ever reaches the parser at runtime, and no parser ships in any client bundle. Worst case is a hung bundler process in dev/CI, not a remotely triggerable DoS. Re-evaluate on the next metro / React Native upgrade or when an `image-size` fix ships. | | [GHSA-5p2g-fcmc-qvqq](https://github.com/advisories/GHSA-5p2g-fcmc-qvqq) | image-size (via `metro@0.87.0`) | High | Accepted 2026-09-09 | Same class of bug, JXL/HEIF parsers: a crafted box with a zero-valued size field in a recognized box-type never advances the offset, hanging the event loop permanently. Same root cause, same build-time-only exposure and no runtime attacker-controlled input path as above; remediation is blocked on the same upstream fix. | **SAST findings** (CodeQL, `security-extended`): - New High/Critical SAST findings block merge — CodeQL is a required status check on `main`. - Triage target for any SAST finding: 7 days to fix or document non-exploitability (inline suppression with justification). **Enforcement**: all changes are evaluated automatically on every PR (Dependabot for dependencies, CodeQL for code weaknesses); violating commits cannot merge while the required checks fail. Suppression of a finding requires a written non-exploitability rationale. ## Security Model VaultKeepR is zero-knowledge: the master password never leaves the user's device. All encryption (XChaCha20-Poly1305, Argon2id) runs client-side. The on-device SLM engine (auto-tagging, breach summary) performs all inference locally — no vault data is sent to any server. A full threat model — assets, adversaries, trust boundaries, and accepted limitations — is documented in [`docs/THREAT_MODEL.md`](./docs/THREAT_MODEL.md). The most impactful risks and their mitigations are tracked in [`SECURITY_ASSESSMENT.md`](./SECURITY_ASSESSMENT.md). ## Security Scans & Reports Automated security scan reports for the shipped clients and web app are published in the [`audits/`](./audits) directory for transparency. These are tool-generated reports (not manual third-party code audits); findings are triaged under the [Vulnerability Remediation Policy](#vulnerability-remediation-policy). | Report | Scope | Tool | Date | |---|---|---|---| | [`2026-08-audit-extension-v1.8.5.pdf`](audits/2026-08-audit-extension-v1.8.5.pdf) | Browser extension v1.8.5 | Internal full audit | 2026-08 | | [`2026-09-appsec-scorecard-ios.pdf`](audits/2026-09-appsec-scorecard-ios.pdf) | iOS client | AppSec Scorecard | 2026-09 | | [`2026-09-appsec-scorecard-android.pdf`](audits/2026-09-appsec-scorecard-android.pdf) | Android client | AppSec Scorecard | 2026-09 | | [`2026-09-virustotal-ios-v1.8.5.pdf`](audits/2026-09-virustotal-ios-v1.8.5.pdf) | iOS IPA v1.8.5 | VirusTotal | 2026-09 | | [`2026-09-virustotal-android-v1.8.5.pdf`](audits/2026-09-virustotal-android-v1.8.5.pdf) | Android APK v1.8.5 | VirusTotal | 2026-09 | | [`2026-09-http-observatory-web.pdf`](audits/2026-09-http-observatory-web.pdf) | vaultkeepr.xyz web app | MDN HTTP Observatory | 2026-09 | | [`2026-09-maestro-e2e-ios.pdf`](audits/2026-09-maestro-e2e-ios.pdf) | iOS client — functional E2E | Maestro | 2026-09 | | [`2026-09-maestro-e2e-android.pdf`](audits/2026-09-maestro-e2e-android.pdf) | Android client — functional E2E | Maestro | 2026-09 | | [`2026-09-mobsf-android-v1.8.9.pdf`](audits/2026-09-mobsf-android-v1.8.9.pdf) | Android APK v1.8.9 — static analysis (0/432 trackers) | MobSF | 2026-09 | Reports are refreshed with each client release. Manually conducted code audits, when they happen, will be published here under the auditor's consent. ## Release Integrity (Signed Releases) Release artifacts (Android APK, iOS IPA, browser extensions) are built on the maintainer's machine and **signed with [minisign](https://github.com/jedisct1/minisign)** (Ed25519). The signing public key is committed in this repository ([`minisign.pub`](minisign.pub)) — its integrity is anchored by the git history. ### Verify a release artifact ```bash # 1. Download the artifact and the repository's public key gh release download v0.2.0 -R VaultKeepR/vaultkeepr-public curl -LO https://raw.githubusercontent.com/VaultKeepR/vaultkeepr-public/main/minisign.pub # 2. Verify the signature (minisign: brew install minisign / apt install minisign) minisign -Vm vaultkeepr-android-v0.2.0.apk -p minisign.pub # → "Signature and comment signature verified" # 3. Cross-check the SHA-256 against the signed checksums.txt shasum -a 256 -c checksums.txt ``` Every release also ships `checksums.txt` (SHA-256 of all artifacts) with its own minisign signature, so the checksum list itself is authenticated. If signature verification fails, **do not install the artifact** and please [open a security advisory](#reporting-vulnerabilities). ### Verify the SDK build provenance The `@vaultkeepr/*` packages published to npmjs.org are built and published by GitHub Actions from this repository, so they carry a **SLSA build provenance** attestation generated by [`actions/attest-build-provenance`](https://github.com/actions/attest-build-provenance). The bundle is attached to each GitHub Release as `vaultkeepr-sdk-.intoto.jsonl` (one line per SDK tarball), and npm shows the same provenance on the package page: ```bash # Download the tarball and check it was built by this repository's release workflow npm pack @vaultkeepr/core gh attestation verify vaultkeepr-core-0.1.3.tgz --repo VaultKeepR/vaultkeepr-public ``` **Scope, stated plainly:** this attestation covers only the **npm SDK tarballs built by the release workflow**. The application artifacts (Android APK, iOS IPA, browser extension zips) are built on the maintainer's machine: they are covered by the minisign signature and the signed `checksums.txt` above, and no CI build provenance is claimed for them.