Repository navigation
Security
Do not open a public issue.
Report via GitHub Security Advisories with:
- A description of the vulnerability
- Reproduction steps
- Affected versions (if known)
Response times are a future goal, not a committed SLA at this time.
3va's security model is built around three principles:
No access to the filesystem, network, environment variables, or child processes unless explicitly granted via a flag — and that applies uniformly to application code and to every dependency it pulls in. See Permissions for the capability model, including package.json grants and per-dependency scoping.
The package manager treats packages as untrusted code. Lifecycle scripts (preinstall, install, postinstall) are blocked by default — the single escape hatch is opting out per-invocation with 3VA_ALLOW_SCRIPTS=1, which re-enables exactly the class of attack the deny-by-default model exists to close.
Install-time supply-chain checks:
- Tarball integrity — SHA-256/SHA-512 verification
-
Dependency-confusion protection —
.npmrc-pinned scopes never fall back to public registries - Typosquatting detection — edit-distance check against a popular-packages list
- Automatic per-tarball malware gate — aborts the install on high-severity findings
The 3va audit command adds a fuller picture:
- Known malicious patterns (static analysis)
- CVEs via the OSV database (24-hour cache)
- Leaked secrets and credentials (opt-in with
--secrets)
The full audit is not automatic on install — only the per-tarball malware gate is. Run 3va audit --secrets yourself after adding dependencies. See Package Manager and Roadmap.
The vvva_crypto crate uses NIST-standardized post-quantum primitives:
- ML-KEM-768 for key encapsulation
- ML-DSA for digital signatures
tls.pqConnect(port, host[, options]) (needs --allow-net=<host>) performs a real in-handshake hybrid X25519MLKEM768 key exchange inside TLS 1.3 (RFC 10024); check socket.pqNegotiated / socket.negotiatedGroup to see whether the server agreed. https.createServer() offers the same group to clients since 2.12. See Roadmap.
ssh2.Client.connect() verifies the server key and fails closed (EHOSTUNVERIFY). A connection needs hostFingerprint (a SHA256:… fingerprint), knownHosts (an OpenSSH known_hosts file, read through the --allow-read permission model) or hostVerifier (a callback returning exactly true to accept). A connect that passes none of these is trusted only on loopback or under --allow-insecure; an explicit option is enforced there too. A known_hosts entry whose key changed is refused.
A built-in firewall (vvva_firewall) operates in the connection-accept loop before any byte reaches JavaScript: per-IP rate and connection limits, Slowloris/RUDY deadlines, adaptive auto-block escalation for repeat offenders, and a request-smuggling guard. See HTTP Performance.
Every commit and PR is scanned by:
-
Semgrep SAST — custom rules in
.semgrep/rules/covering unsafe Rust patterns, filesystem access, and 3va-specific security properties - CodeQL — GitHub's semantic code analysis
- Gitleaks — secret scanning
- cargo-audit — Rust dependency CVE scanning
- cargo-deny — dependency license and ban enforcement
Honest accounting of what's still open:
- npm provenance verification (opt-in
--require-provenance) checks the Sigstore DSSE signature and in-toto subject but does not yet validate the Fulcio certificate chain to its root or Rekor inclusion proofs. - Package-scoped permission enforcement wraps plain factory functions only — a PascalCase constructor like
net.Socketis deliberately left unwrapped (wrapping it would breakinstanceof), sonew require('net').Socket()followed by.connect()bypasses scoping. See Permissions. -
3va permissions suggest/learndon't yet write intopackage.json.
See Roadmap for the full list.
We follow coordinated disclosure. If you discover a vulnerability, please give us reasonable time to address it before public disclosure. No fixed timeline has been committed to at this time.