Security
pagevault uses industry-standard cryptography and best practices to protect encrypted content.
Cryptography
Encryption Algorithm
AES-256-GCM (Advanced Encryption Standard, 256-bit key, Galois/Counter Mode)
- Standard: NIST approved, used by TLS, Signal, and other production systems
- Key size: 256 bits (2^256 possible keys)
- Mode: GCM provides authenticated encryption (detects tampering)
- Implementation: WebCrypto API (built into all modern browsers)
Key Derivation
PBKDF2-SHA256 with 310,000 iterations
- Standard: OWASP recommended as of 2023
- Hash function: SHA-256 (cryptographically secure)
- Iterations: 310,000 (computationally expensive, slows down brute-force attacks)
- Salt: 32-character random hex, unique per configuration
Authentication
GCM mode includes authentication. If encrypted content is tampered with, decryption fails and error message shows.
Security Properties
✅ What pagevault Protects
- Content confidentiality: Encrypted content is unreadable without password
- Tamper detection: Modified encrypted files won’t decrypt
- Password-based access: Same password required by each user
- No plaintext leakage: Encrypted files contain only ciphertext and metadata
❌ What pagevault Does NOT Protect
- Password security: We use standard algorithms. Your password strength matters.
- Distribution security: If you share password insecurely, attacker can decrypt
- Browser security: If visitor’s computer is compromised, password can be stolen
- Source control: Don’t commit
.pagevault.yaml to version control
- Server security: If your hosting is compromised, files can be accessed
pagevault is client-side only. It can’t protect against attacks on your server, distribution channel, or visitor’s machine.
Threat Model
pagevault is designed to protect against opportunistic attackers:
- ✅ Casual browser: Can’t view encrypted content without password
- ✅ Automated scanners: Can’t extract plaintext from encrypted HTML
- ✅ Archive crawlers: Can’t index encrypted sections
- ✅ Data breaches: Encrypted files are useless without password
pagevault is NOT designed for:
- ❌ Government-level adversaries with extensive resources
- ❌ Attackers with physical access to visitor’s computer
- ❌ Compromised hosting infrastructure
- ❌ Weak passwords (pagevault can’t fix password selection)
Practical Security Advice
Passwords
- Use strong passwords
- At least 16 characters
- Mix uppercase, lowercase, numbers, symbols
- Use a password manager (KeePass, 1Password, Bitwarden)
- Avoid dictionary words, personal info, patterns
# Bad: "password123", "Site2024", "MyBlog"
# Good: "7#kL9$pQ2mX!vN4bW" (from password manager)
- Rotate passwords periodically
pagevault config user passwd alice
pagevault sync _locked/ -r # Re-encrypt with new password
- Don’t reuse passwords
- Use different password for pagevault than your email, GitHub, etc.
- If one service is compromised, others aren’t affected
Configuration Files
- Add
.pagevault.yaml to .gitignore
echo ".pagevault.yaml" >> .gitignore
git rm --cached .pagevault.yaml # If already committed
- Store backups securely
- Password manager
- Encrypted external drive
- KMS system (AWS Secrets Manager, GitHub Secrets, etc.)
- Never commit to version control
# Bad
git add .pagevault.yaml
git commit -m "Add password"
# Good
# .pagevault.yaml is in .gitignore
Distribution
- Separate password from HTML
# ✅ Good: File and password distributed separately
# Send HTML file via email attachment
# Send password via Slack or Signal
# ❌ Bad: Both in same message
# Sends: "Password is 'secret' here's the HTML..."
- Use HTTPS for downloads
- GitHub Pages: HTTPS enabled by default ✅
- Netlify: HTTPS enabled by default ✅
- Self-hosted: Use Let’s Encrypt for free HTTPS
- Consider temporary passwords for time-limited access
# Change password after disclosure period
pagevault config init # Generates new password
pagevault lock site/ -r # Re-encrypt
For Multi-User Setup
- Each user gets unique password
users:
alice: "alice-unique-password"
bob: "bob-unique-password"
- Rotate individual user passwords
pagevault config user passwd alice
pagevault sync _locked/ -r
- Remove inactive users
pagevault config user rm bob
pagevault sync _locked/ -r
For CI/CD Environments
- Use secret management
```bash
GitHub Actions
- run: pagevault lock . -p “$”
GitLab CI
- pagevault lock . -p “$PAGEVAULT_PASSWORD”
Environment variable in CI/CD settings, never in code
```
- Rotate secrets
- Update in GitHub Secrets / GitLab CI Variables
- Re-run pipeline to re-encrypt
- Audit access logs
- Who downloaded secrets?
- When were they accessed?
- GitHub: Settings → Security → Audit log
Cryptographic Assumptions
pagevault assumes:
- Passwords have sufficient entropy: Passwords should have ~128+ bits of entropy (use password manager)
- WebCrypto implementation is secure: Browser’s native crypto is trusted (tested regularly by browser vendors)
- User’s computer is trustworthy: No keylogger, malware, or compromise on visitor’s machine
- HTTP transmission is secure: Only access over HTTPS (GitHub Pages, Netlify, etc.)
- JavaScript environment is safe: No malicious scripts injected before pagevault loads
If any assumption is violated, security may be compromised.
Audit and Transparency
pagevault source code is open. You can:
- Review cryptography implementation
- See
src/pagevault/crypto.py for key derivation
- See
src/pagevault/template.py for browser-side decryption
- Run security tests
pytest tests/test_crypto.py -v # Cryptography tests
pytest tests/test_integration.py -v # Full encryption/decryption roundtrips
- Verify WebCrypto compatibility
- Check
templates/pagevault.js for browser-side implementation
- Uses
SubtleCrypto.decrypt() with AES-256-GCM
Viewer Plugin Security
pagevault includes a viewer plugin system for rendering wrapped files (images, PDFs, HTML, text, Markdown) in the browser after decryption. The security model for plugins follows standard Python packaging conventions:
Trust model: pip install = trust. If you install a third-party package that registers viewer plugins via the pagevault.viewers entry point group, that plugin’s JavaScript and CSS will be embedded into your encrypted HTML output. This is the same trust model as any Python package – installing a package grants it the ability to run code in your environment.
Defense-in-depth measures:
- Plugin names and MIME types are validated via regex at class definition time (
__init_subclass__) and again at the injection point
- Plugin JavaScript, CSS, and dependency strings are escaped to prevent
</script> and </style> breakout attacks
- The built-in HTML viewer uses an iframe with
sandbox="allow-same-origin" (no allow-scripts) for display-only rendering
- Plugin names are deduplicated by priority, with warnings logged on collision
Recommendation: Only install viewer plugins from packages you trust. Review third-party plugin source code before installing. The built-in viewers (image, PDF, HTML, text, Markdown) are maintained as part of the pagevault project and undergo the same review process as the core code.
Content Padding
The --pad flag (or pad: true in config) pads content to the next power-of-2 boundary before encryption. This prevents attackers from inferring content size from ciphertext length, which can be a concern when:
- Encrypted files are publicly hosted and different content lengths could reveal which document is which
- An attacker can observe ciphertext sizes over time and correlate them with known documents
Padding adds space overhead but provides stronger confidentiality guarantees. Consider enabling it for high-sensitivity deployments.
Known Limitations
- Side-channel attacks: Password might be leaked via timing analysis, power consumption, etc. (not practical for browsers)
- Rainbow tables: If attacker has dictionary of common passwords, they can precompute hashes. Use strong passwords to mitigate.
- Brute force: 310k iterations slows attackers but doesn’t eliminate risk if password is weak
- Browser bugs: Potential vulnerabilities in browser’s WebCrypto. Keep browser updated.
Reporting Security Issues
If you discover a vulnerability:
- Do not open a public GitHub issue
- Email security concerns to the maintainer privately
- Allow time for patches before public disclosure
pagevault takes security seriously and will respond quickly to legitimate concerns.
References
Summary
pagevault uses strong, standard cryptography (AES-256-GCM + PBKDF2-SHA256) suitable for protecting sensitive content on static sites.
Threats pagevault prevents:
- Casual attackers reading encrypted HTML
- Automated scrapers indexing content
- Archive crawlers capturing pages
- Passive network monitoring
Your responsibility:
- Use strong, unique passwords
- Don’t share passwords insecurely
- Keep
.pagevault.yaml out of version control
- Use HTTPS for all deployments
- Keep your browser and OS updated
For questions or concerns, see FAQ.