Documentation

Security

Authentication, rate limiting, input validation and CORS.

Source: api.packr.blueforge.studio/-/docs/security

Security Documentation

1. Security Overview

The Packr registry has been hardened against the OWASP Top 10 and common npm registry attack vectors, including tarball path traversal, package hijacking, brute-force credential attacks, webhook SSRF, and denial-of-service via large uploads or high request volume. This document describes the security controls in place.


2. Authentication & Authorization

EndpointAuth MethodDescription
/-/v1/loginNone (public)User login / registration (disabled by default)
PUT / (publish)JWT Bearer tokenPackage publishing
/-/v1/deprecateJWT Bearer tokenDeprecate package versions
/-/v1/unpublishJWT Bearer tokenUnpublish package versions
/api/v1/admin/sessionsX-Internal-Secret headerCreate admin session (Next.js -> Go)
/api/v1/admin/*Session cookie or Bearer tokenAdmin dashboard API
/-/search/, /agent/None (public)Package search and agent endpoints

3. Rate Limiting

RouteLimitWindowPurpose
/-/v1/login10 req1 min / IPPrevent brute-force
/-/v1/password-reset10 req1 min / IPPrevent abuse
PUT / (publish)30 req1 min / IPPrevent flooding
/api/v1/admin/*60 req1 min / IPPrevent admin abuse
/-/search/, /agent/30 req1 min / IPPrevent DoS

IP extraction uses the Fly-Client-IP header, which is unforgeable behind the Fly.io proxy. If that header is absent, the implementation falls back to the last IP in X-Forwarded-For.


4. Resource Limits

ResourceLimitConfigurable
Tokens per user20Code constant (maxTokensPerUser)
Webhooks per user10Code constant (maxWebhooksPerUser)
Tarball size5 MBMAX_TARBALL_SIZE env var
Request body (login/admin)1 MBSmallBodyLimit
Request body (publish)50 MBLargeBodyLimit
JWT token expiry30 daysCode constant
Session expiry7 daysCode constant

5. Password Requirements

Passwords are validated on registration and password reset. Requirements:

  • Minimum 10 characters
  • Maximum 128 characters
  • At least one uppercase letter
  • At least one lowercase letter
  • At least one digit
  • At least one special character (!@#$%^&* etc.)

6. Input Validation

InputValidationPurpose
Username3-64 chars, alphanumeric + ._-, must start/end alphanumericPrevent injection
Package scopeMust start with @, lowercase alphanumeric + ._-Prevent path traversal
Package nameLowercase alphanumeric + ._-, start with alphanumericPrevent path traversal
VersionStrict semver (X.Y.Z or X.Y.Z-prerelease)Prevent path traversal
Tarball pathContainment check — must stay within data directoryPrevent filesystem escape

7. Package Ownership

  • First publish: any authenticated user with a valid token can publish a new package.
  • Subsequent publishes: only package owners can publish new versions.
  • Ownership is enforced on: publish, deprecate, unpublish, and dist-tag changes.
  • Package owners are set automatically on first publish.

8. Session Security

  • Sessions are HMAC-SHA256 signed tokens.
  • Session cookies are set with HttpOnly, Secure, and SameSite=strict attributes.
  • Sessions expire after 7 days.
  • Session creation requires the INTERNAL_API_SECRET shared between the Next.js dashboard and the Go backend.

9. CORS Policy

RouteCORS Origin
/api/v1/admin/*DASHBOARD_ORIGIN only (default: https://packr.blueforge.studio)
All other routes* (wildcard — required for npm CLI compatibility)

10. Webhook Security

  • Payloads are signed with HMAC-SHA256 and delivered with the header X-Packr-Signature: sha256=....
  • SSRF protection is applied at both DNS resolution and TCP connect time, blocking private IP ranges.
  • Webhooks targeting unresolvable hostnames are blocked.
  • Webhook secrets are redacted in list API responses and are only shown at creation time.
  • Webhook delivery has a 10-second timeout.

11. Infrastructure Security

  • The Docker container runs as a non-root user (packr).
  • HTTP server timeouts: ReadTimeout 30s, WriteTimeout 120s, IdleTimeout 60s.
  • ReadHeaderTimeout is set to 10s; MaxHeaderBytes is limited to 1 MB.
  • Token hashing uses full SHA-256 with no truncation.
  • Secrets (JWT_SECRET, SESSION_SECRET) are generated randomly at startup if not configured, with a warning logged. Random secrets are ephemeral and do not persist across restarts.

12. Environment Variables

VariableRequiredDefaultDescription
JWT_SECRETYes (prod)Random (ephemeral)JWT token signing key
SESSION_SECRETYes (prod)Random (ephemeral)Session HMAC signing key
INTERNAL_API_SECRETYes (dashboard)Empty (disabled)Shared secret for session creation
ALLOW_REGISTRATIONNofalseEnable self-registration
DASHBOARD_ORIGINNohttps://packr.blueforge.studioAllowed CORS origin for admin API
MAX_TARBALL_SIZENo5242880 (5 MB)Max tarball upload size in bytes
RATE_LIMIT_LOGINNo10Login attempts per minute per IP
RATE_LIMIT_PUBLISHNo30Publish requests per minute per IP

13. OAuth Device Flow Security

The OAuth device flow (RFC 8628) is implemented with the following security controls:

ControlDetail
Code expiryDevice codes and user codes expire after 15 minutes. This limits the phishing window.
Rate limitingPOST /-/v1/device/authorize is rate-limited to 5 requests/min/IP to prevent code enumeration.
Single-use codesOnce a device code is exchanged for a token, it is immediately invalidated. Replaying the code returns expired_token.
State parameterEach authorization request includes a random 32-byte state token to prevent CSRF.
Account linking by emailOAuth identities are linked to Packr accounts by verified email address. Accounts are not created for unverified emails.

14. Keychain Credential Storage

The CLI can store tokens in the system keychain rather than a plain file:

  • macOS: macOS Keychain (encrypted, locked to user session)
  • Windows: Windows Credential Manager
  • Linux: libsecret (GNOME Keyring, KWallet)

Keychain storage is recommended for developer workstations. The file-based store (~/.packr/credentials.json) is created with mode 0600 and is acceptable for CI environments where keychain access is unavailable.


15. Scope-Based Access Control

Tokens carry optional scope restrictions in their JWT claims. When scope restrictions are present:

  • The token can only be used for packages within the listed scopes.
  • Attempts to publish to, unpublish from, or deprecate packages outside the listed scopes are rejected with 403 Forbidden.
  • Read operations (install, metadata fetch) respect scope restrictions for private scopes.

Empty scope list means the token applies to all packages (backward compatible with tokens created before the permission system).


16. Token Permission Enforcement

The RequirePermission middleware enforces permissions on every protected route. Permission checks happen after JWT validation:

Request → JWT validation → Permission check → Scope check → Handler
  • Missing JWT: 401 Unauthorized
  • Valid JWT, wrong permission: 403 Forbidden
  • Valid JWT, scope mismatch: 403 Forbidden
  • Valid JWT, no permissions claim (legacy): 200 OK (backward compatible)

Permission types: read, publish, unpublish, admin.


17. Account Linking Security

When a user logs in via OAuth, the registry links the OAuth identity to a Packr account by verified email address:

  • Only provider-verified emails are used for linking (GitHub: only primary verified email; Google: always verified; GitLab: only verified primary email).
  • If no existing Packr account has the email, a new account is created automatically.
  • If a Packr account exists with that email, the OAuth identity is linked to it. The user can then log in via password or OAuth interchangeably.
  • A single Packr account can have multiple linked OAuth identities (e.g., GitHub + Google with the same email).
  • Admins can unlink OAuth identities via the dashboard.

18. Security Audit History

DateScopeFindingsStatus
April 2026Comprehensive audit of registry, dashboard, and infrastructure24 findings: 4 CRITICAL, 6 HIGH, 8 MEDIUM, 6 LOWAll remediated

The April 2026 audit covered authentication flows, authorization enforcement, input validation, rate limiting, webhook security, session management, CORS configuration, resource limits, infrastructure hardening, OAuth device flow, and token permission enforcement. All findings have been addressed and verified.