05 / Security
Security
Publication content is treated as untrusted.
Imported EPUB/PDF files are inspected before persistence. EPUB ZIP traversal, duplicate/encrypted entries, excessive expansion or compression ratios, unsupported encryption, remote publication resources, oversized metadata/covers, and uninspectably large text resources are rejected with bounded errors. PDF encryption and active actions such as JavaScript, launch, submit/import, remote-go-to, rendition, and rich-media actions are rejected.
EPUB documents are sanitized before rendering. Publisher scripts, active embedded frames/objects, refresh redirects, event-handler attributes, JavaScript URLs, and remote resource-bearing attributes are removed. Each rendered EPUB document receives a deny-by-default content security policy: publication script, frame, worker, connection, object, and form execution is disabled; local archive assets are limited to reader-created blob/data resources.
The PDF reader uses PDF.js as a custom canvas/text integration with evaluation disabled. It does not mount the stock PDF scripting/annotation application layer. Personal book bytes are always stored locally in IndexedDB and are excluded from ordinary JSON backups and CI evidence; an optional separate Account permission may additionally place eligible personal book bytes in owner-scoped private cloud storage for cross-device continuity.
Account and sync
THIEPN Account owns the interactive Google sign-in. Library never signs into Google directly: it is a registered first-party OAuth 2.1 public client using Authorization Code + PKCE and its own app-local access/refresh tokens. A silent Account-origin probe exposes only signed-in eligibility, never tokens or profile data, so an existing THIEPN Account session can attach Library automatically while a signed-out visitor remains a guest. Cloud reading state is isolated by auth.uid() row-level security plus the registered Library client_id; writes use an owner-scoped revision compare-and-swap RPC so concurrent devices cannot silently overwrite one another. Unknown/delegated OAuth clients remain denied. Destructive cloud-data deletion is managed by THIEPN Account with a recent-session check and planned-revision guard. Personal EPUB/PDF bytes are never part of the account snapshot. Optional Personal book cloud uses a separate private Storage bucket, content-addressed SHA-256 object names, owner-path RLS, a distinct sensitive Account grant, and no public object URLs. Whole-cloud deletion remains mediated by THIEPN Account rather than the Library reader.
Site policy
The application ships a restrictive HTML content security policy and a no-referrer policy. GitHub Pages is the current HTML host and does not provide a repository-controlled arbitrary response-header layer, so the application does not claim header-only controls such as frame-ancestors or Permissions-Policy unless the production host actually serves them. The release verifier checks the policy that is truly present in live HTML rather than treating an unused source header file as evidence.
Dependencies and CI
Production dependencies are lockfile-controlled, package build scripts are explicitly allowed or denied, new package releases have a minimum age before routine resolution, high/critical production advisories block the security gate, license inventory and a CycloneDX SBOM are generated, and third-party GitHub Actions are pinned to full commit SHAs.