Security
PDFPipe is built with security as a foundational requirement. This page describes the measures we have in place to protect your data.
For questions about our data processing practices, see our Data Processing Agreement. To report a security concern, email security@pdfpipe.dev.
Encryption
- All API traffic is encrypted in transit with TLS 1.2+ (HTTPS only). HTTP connections are rejected. The .dev TLD enforces HSTS by default.
- Data at rest is encrypted in DynamoDB using AWS-managed encryption keys (AES-256).
- PDF files stored in S3 are encrypted with server-side encryption (SSE-S3 minimum, SSE-KMS preferred).
API Key Security
- API keys are stored as bcrypt hashes - the raw key is only shown once at creation and never stored.
- Key lookup uses a SHA-256 hash prefix for fast retrieval without exposing the full key.
- Keys can be scoped to specific IP addresses via an allowlist when creating a key in the dashboard, blocking requests from unauthorised origins.
- Keys can be revoked instantly from the dashboard, and revoked keys are rejected immediately.
Authentication & Sessions
- Dashboard sessions use signed JWT tokens with a 24-hour expiry.
- JWT tokens contain only the minimum claims needed (userId, accountId, memberRole).
- Suspended accounts are blocked at the authentication middleware layer before any processing occurs.
Ephemeral Data Storage
- Converted PDF output is stored temporarily in S3 and served via presigned URLs scoped to the exact object path.
- Download access is limited to your plan's retention window from request creation; the API will not issue new result URLs after that period.
- S3 lifecycle rules automatically remove result objects after a fixed maximum age (longest tier retention plus a short buffer).
- Presigned URL expiry per request is tier-based - 1 hour (Free), 24 hours (Starter), 7 days (Pro), 30 days (Business).
- There is no long-term storage of PDF content. PDFPipe does not retain your documents.
Data Isolation
- Every request is assigned a unique UUID v4 request ID.
- S3 objects are namespaced to /{userId}/{requestId}/ - cross-user access is impossible by design.
- Presigned URLs are scoped to the exact S3 object path and cannot be used to access other objects.
- DynamoDB records are partitioned by user/account with composite keys preventing cross-tenant queries.
Input Validation & SSRF Prevention
- All incoming requests are validated at the API boundary using Zod schemas. Invalid requests are rejected before processing.
- Request body size is limited to 64 KB to prevent abuse.
- URL validation blocks private and reserved IP ranges (10.x, 172.16-31.x, 192.168.x, 127.x, 169.254.x) to prevent SSRF attacks.
- Only HTTP and HTTPS protocols are accepted - no file://, ftp://, or other schemes.
- URLs are limited to 2,048 characters.
Infrastructure
- Hosted on AWS EU (London) - eu-west-2 - using SST v3 (Ion) with infrastructure-as-code. All resources are defined declaratively and version-controlled.
- Compute runs on AWS Lambda with IAM least-privilege policies - each function has only the permissions it needs.
- The S3 bucket has no public access. All file access goes through presigned URLs.
- Processing queues use AWS SQS FIFO with dead letter queues (DLQ). Failed jobs are retried up to 3 times before moving to the DLQ.
- API Gateway enforces a 30-second timeout and CORS policies restricting origins to production domains.
- CloudFront CDN serves the web application globally from edge locations, with the origin in eu-west-2.
Monitoring & Audit
- Structured JSON logging with request ID, hashed user ID, tier, duration, and outcome for every request.
- Admin audit logging tracks all administrative actions (account suspension, tier changes, etc.).
- AWS CloudWatch captures Lambda invocation logs, errors, and latency metrics.
Responsible Disclosure
If you discover a security vulnerability, please email security@pdfpipe.dev with details. We will acknowledge receipt within 48 hours and provide an initial assessment within 5 business days.