Security and operations for NextPDF Connect
At a glance
Section titled “At a glance”NextPDF Connect authenticates networked transports with an API key bearer token. It treats the local Model Context Protocol (MCP) transport as a trusted subprocess. It gates every high-risk tool behind explicit human confirmation. This page explains the authentication model, transport security, and threat model.
Install
Section titled “Install”composer require nextpdf/serverConceptual overview
Section titled “Conceptual overview”The server has three trust boundaries, one per transport.
The MCP stdio transport is a subprocess launched by a local client. It reads JSON-RPC on standard input and writes responses on standard output. This transport has no network listener and no API key. It inherits trust from the operating-system process boundary, which is the trust model the MCP specification defines for stdio. Logging goes to standard error, so it never corrupts the protocol stream.
The REST transport and the gRPC transport are networked. Both
require an API key bearer token on every request except unauthenticated
health probes. The same key store, key format, and constant-time
validation support both transports. The gRPC transport reads the token
from call metadata. REST reads it from the Authorization header.
Incorrect authentication is the failure that the OWASP Application Programming Interface (API) Security Top 10 identifies as API2:2023 Broken Authentication. Flaws in this area compromise the API’s ability to identify the caller and therefore compromise API security overall (OWASP API Security Top 10, API2:2023). Weak or predictable tokens are also called out as a broken-auth anti-pattern (same source, vulnerability list). The design below addresses both risks.
API surface
Section titled “API surface”API key format and validation
Section titled “API key format and validation”A key is npk_live_{kid}_{secret}. The kid is an eight-character
identifier used for O(1) record lookup, and the secret carries the entropy.
The store never keeps the raw key. It stores a SHA-256 digest of the full
key material. On each request, the server hashes the presented token and
compares it with the stored digest by using a constant-time comparison
(hash_equals), so a wrong key reveals nothing through timing. A disabled
or expired key is rejected after the hash check, not before.
The REST and gRPC validators share this logic. The REST middleware reads
Authorization: Bearer npk_live_…. The gRPC authenticator reads the same
bearer token from the gRPC authorization call metadata, which is carried
as HTTP/2 headers. It fails the call with the gRPC UNAUTHENTICATED
status.
Both transports also apply an anti-automation throttle to
pre-authentication traffic: excessive attempts from one client identity are
rate-limited and rejected — 429 Too Many Requests on REST, and the gRPC
RESOURCE_EXHAUSTED status on gRPC. This control is active by default, so
it protects a deployment that has not separately configured a rate-limit
store. Clients should back off rather than retry immediately.
Unauthorized responses
Section titled “Unauthorized responses”A REST request with a missing, malformed, disabled, or expired key receives
401 Unauthorized with a problem-details body and a
WWW-Authenticate: Bearer response header. This matches the HTTP
requirement that a 401 response MUST carry a WWW-Authenticate header
field with at least one challenge (RFC 9110 §11.6.1). That requirement
follows from the rule that a request with omitted or invalid credentials
should receive 401 plus a WWW-Authenticate challenge (RFC 9110 §11.6).
Key entitlement
Section titled “Key entitlement”Each key record carries a maximum product tier. The REST pipeline attaches the authenticated client’s identity and tier to the request, so downstream authorization can enforce capability and payload ceilings by tier. A core-tier key cannot run a Pro or Enterprise operation, even when those packages are installed.
Edge cases and gotchas
Section titled “Edge cases and gotchas”-
The MCP transport has no API key. That is intentional and correct for a local subprocess. Do not expose the MCP server through a network shim. If a networked agent needs the tools, put it in front of the REST or gRPC transport, which authenticate.
-
Health probes are anonymous on purpose.
/healthzand/readyzbypass authentication so orchestrators can probe liveness and readiness without a credential. They return only a status. They expose no tool data or document data. -
A confirmation token is single-use and short-lived. The human-in-the-loop gate issues a token bound to the tool name with a 300-second lifetime. The token is consumed on first use. It is not an authentication credential and does not replace an API key.
Performance
Section titled “Performance”Authentication is a single hash plus a constant-time comparison per request. That cost is negligible compared with the cost of a render. The hot-reloading key store re-reads the key file when it changes, so rotation does not require a restart and adds no per-request cost.
Security notes
Section titled “Security notes”The human-in-the-loop gate
Section titled “The human-in-the-loop gate”Every tool declares a risk level. Tools at the highest level,
ApprovalRequired, do not run on first call. The confirmation gate returns
a challenge that contains a single-use token. The agent must show the
challenge to a human and re-invoke the tool with the token. This is a
deliberate control at the point where automated action introduces risk. It
is the point that IEC 31010 identifies for controlling risk introduced
through human (here, agent) action, at or near the point of introduction
(IEC 31010:2019). Configuration cannot weaken the gate: a config override
may only raise a tool’s risk, never lower an ApprovalRequired tool. See
/connect/hitl-risk-tiers/.
Transport security configuration
Section titled “Transport security configuration”The networked transports do not terminate Transport Layer Security (TLS) themselves; TLS is a deployment concern. The reference combined deployment runs the gRPC transport with mutual TLS, with the key, certificate, and client CA supplied as deployment secrets. Under mutual TLS, the server presents a certificate and requires and verifies a client certificate. Run the REST transport behind a TLS terminator (reverse proxy or service mesh), and never expose a plaintext listener on an untrusted network. Configuration specifics are in /connect/deployment/. This is a posture statement, not a turnkey guarantee, and secure transport requires correct deployment configuration.
Output path containment
Section titled “Output path containment”File-writing tools resolve the requested path against the configured base
directory, canonicalize it, and reject null bytes, protocol wrappers, and
.. traversal. They refuse any path that resolves outside the base. Keep
the base directory on a dedicated volume with least-privilege filesystem
permissions.
Data residency and PII mitigations
Section titled “Data residency and PII mitigations”The server holds documents only in the in-memory document store for the
configured time to live (TTL) (default 1800 seconds) and bounded count
(default 50). It does not persist document content to disk unless you
explicitly invoke a file-output tool and the path passes containment. The
server makes no outbound network call to render or inspect a document, so
document bytes do not leave the deployment unless a tool is explicitly
configured to fetch a remote resource. For stateless, residency-sensitive
deployments, disable file output (allow_file_output: false) and restrict
enabled_tools to the minimum set.
Safe telemetry and log scrubbing
Section titled “Safe telemetry and log scrubbing”Audit logging records tool executions at the Caution risk level and
above, plus every issued confirmation challenge. The audit record carries
the tool name, the risk level, and the success flag. Treat tool arguments
as potentially sensitive: route logs to a sink with access controls, and
do not raise the global log level to a verbosity that echoes argument
payloads in shared environments. The MCP transport writes logs to standard
error so log content never enters the protocol stream on standard output.
Conformance
Section titled “Conformance”| Claim | Source | reference_id |
|---|---|---|
| Broken authentication compromises API security | OWASP API Security Top 10, API2:2023 | |
| Weak/predictable tokens are a broken-auth anti-pattern | OWASP API Security Top 10, API2:2023 | |
401 MUST carry a WWW-Authenticate challenge | RFC 9110 §11.6.1 | |
Missing/invalid credentials → 401 + challenge | RFC 9110 §11.6 | |
| Control risk at the point of (human) introduction | IEC 31010:2019 |
The Model Context Protocol stdio trust model follows the official MCP
specification, revision 2025-06-18. Its URL is recorded on
/transports/mcp/ because the MCP specification is not part of the gated
standards corpus.
Commercial context
Section titled “Commercial context”Signing, redaction, compliance, and forensic tools are present only when
nextpdf/premium is installed alongside the server. Their presence does
not change the authentication model. Their risk tier still places
destructive tools behind the human-in-the-loop gate.
See also
Section titled “See also”- /connect/hitl-risk-tiers/ — the risk model and confirmation envelope in detail
- /connect/deployment/ — TLS, mutual TLS, secrets, and worker tuning
- /transports/rest/ — the REST middleware pipeline and OpenAPI security scheme
- /transports/grpc/ — gRPC metadata authentication and status codes
- /connect/configuration/ —
enabled_tools, key store selection, risk overrides