Claude-code-plugins-plus documenso-security-basics
install
source · Clone the upstream repo
git clone https://github.com/jeremylongshore/claude-code-plugins-plus-skills
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/jeremylongshore/claude-code-plugins-plus-skills "$T" && mkdir -p ~/.claude/skills && cp -r "$T/plugins/saas-packs/documenso-pack/skills/documenso-security-basics" ~/.claude/skills/jeremylongshore-claude-code-plugins-plus-documenso-security-basics && rm -rf "$T"
manifest:
plugins/saas-packs/documenso-pack/skills/documenso-security-basics/SKILL.mdsource content
Documenso Security Basics
Overview
Essential security practices for Documenso integrations: API key management, webhook verification, document access control, and self-hosted signing certificate configuration.
Prerequisites
- Documenso account with API access
- Understanding of environment variables and secret management
- Completed
setupdocumenso-install-auth
Instructions
Step 1: API Key Security
// NEVER hardcode keys const BAD = new Documenso({ apiKey: "api_abc123..." }); // Exposed in source // ALWAYS use environment variables const GOOD = new Documenso({ apiKey: process.env.DOCUMENSO_API_KEY! });
Key management rules:
- Store in
(never committed) or a secrets manager (Vault, AWS Secrets Manager).env - Use team-scoped keys for team resources, personal keys for personal documents
- Rotate keys on employee offboarding -- revoke in dashboard immediately
- CI/CD: use masked/encrypted secrets (GitHub Secrets, GitLab CI variables)
# .gitignore — always include .env .env.* !.env.example
Step 2: Key Rotation with Zero Downtime
// Support dual keys during rotation function getApiKey(): string { // Try primary first, fall back to secondary during rotation return process.env.DOCUMENSO_API_KEY_PRIMARY ?? process.env.DOCUMENSO_API_KEY_SECONDARY ?? (() => { throw new Error("No Documenso API key configured"); })(); } // Rotation procedure: // 1. Generate new key in Documenso dashboard // 2. Set as DOCUMENSO_API_KEY_SECONDARY, deploy // 3. Verify secondary key works // 4. Move secondary to PRIMARY, deploy // 5. Revoke old key in dashboard
Step 3: Webhook Secret Verification
import { timingSafeEqual } from "crypto"; function verifyWebhookSecret(req: Request): boolean { const received = req.headers["x-documenso-secret"] as string; const expected = process.env.DOCUMENSO_WEBHOOK_SECRET!; if (!received || !expected) return false; // Use constant-time comparison to prevent timing attacks return timingSafeEqual( Buffer.from(received, "utf8"), Buffer.from(expected, "utf8") ); }
# Python equivalent import hmac, os from flask import request def verify_webhook(req): received = req.headers.get("X-Documenso-Secret", "") expected = os.environ["DOCUMENSO_WEBHOOK_SECRET"] return hmac.compare_digest(received, expected)
Step 4: Document Access Control
// Principle of least privilege with API keys // Personal keys: only YOUR documents // Team keys: all documents in the team // Restrict document access by checking ownership async function getDocumentSecure(documentId: number, userId: string) { const doc = await client.documents.getV0(documentId); // Verify the requesting user is the owner or a recipient const isOwner = doc.userId === parseInt(userId); const isRecipient = doc.recipients?.some(r => r.email === userEmail); if (!isOwner && !isRecipient) { throw new Error("Access denied: not authorized for this document"); } return doc; }
Step 5: Signing Certificate Security (Self-Hosted)
Self-hosted Documenso requires a
.p12 signing certificate for legally valid digital signatures.
# Generate a self-signed certificate (development only) openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes openssl pkcs12 -export -out signing-cert.p12 -inkey key.pem -in cert.pem # Mount into Docker container docker run -v $(pwd)/signing-cert.p12:/opt/documenso/cert.p12 \ -e NEXT_PRIVATE_SIGNING_LOCAL_FILE_PATH=/opt/documenso/cert.p12 \ -e NEXT_PRIVATE_SIGNING_PASSPHRASE=your-passphrase \ documenso/documenso:latest
For production, use a certificate from a trusted CA (e.g., GlobalSign, DigiCert).
Step 6: Self-Hosted Production Secrets
# Generate cryptographically secure secrets openssl rand -hex 32 # NEXTAUTH_SECRET openssl rand -hex 32 # NEXT_PRIVATE_ENCRYPTION_KEY openssl rand -hex 32 # NEXT_PRIVATE_ENCRYPTION_SECONDARY_KEY # Never reuse secrets across environments # Never use default values in production
Security Checklist
- API key stored in environment variable, never in source code
-
in.env.gitignore - CI secrets use masked/encrypted storage
- Team keys rotated on employee offboarding
- Webhook secret uses constant-time comparison
- Self-hosted: HTTPS with valid TLS certificates
- Self-hosted: signing certificate from trusted CA
- Self-hosted: secrets generated with
openssl rand -hex 32 - No API keys or secrets in logs (sanitize before logging)
- Key rotation procedure documented and tested
Error Handling
| Security Issue | Indicator | Response |
|---|---|---|
| Invalid API key | 401 errors | Rotate key immediately |
| Webhook spoofing | Invalid secret header | Reject request, alert team |
| Key exposed in git | GitHub secret scanning alert | Revoke key, rotate, audit access |
| Brute force | Many 401s from same IP | Rate limit by IP at reverse proxy |
Resources
Next Steps
For production deployment, see
documenso-prod-checklist.