nginx/nginx · error

NGX_LOG_ALERT

NGX_LOG_ALERT

Error message

quic token buffer is too small

What it means

ngx_quic_new_token() encrypts the token plaintext (20-byte address hash, time_t expiry, retry flag, ODCID length + bytes, all bounded by NGX_QUIC_MAX_TOKEN_SIZE = 64) with AES-256-GCM into a caller-provided buffer; before touching crypto it verifies that IV (12 bytes) + plaintext + GCM tag (16 bytes) fits token->len, else it logs this ALERT and returns NGX_ERROR, which fails NEW_TOKEN / retry-token generation. Stock callers in ngx_event_quic_output.c pass a buffer of NGX_QUIC_TOKEN_BUF_SIZE (12 + 64 + 16 = 92), so a hit means a custom caller passed a smaller buffer, local patches changed sizes, or an unusual ABI (e.g. larger time_t).

Solutions

  1. Size token buffers to NGX_QUIC_TOKEN_BUF_SIZE and set token->len = NGX_QUIC_TOKEN_BUF_SIZE before the call
  2. Do not shrink or reshape token fields (time_t size, ODCID length cap) in local patches
  3. If stock nginx hits this on your platform, report it with ABI details (sizeof(time_t), NGX_QUIC_MAX_TOKEN_SIZE)

Example fix

/* before */
u_char  buf[32];
ngx_str_t  token = { 32, buf };

/* after */
u_char  buf[NGX_QUIC_TOKEN_BUF_SIZE];
ngx_str_t  token = { NGX_QUIC_TOKEN_BUF_SIZE, buf };
Defensive patterns

Strategy: validation

Validate before calling

if (token.len < (size_t) (NGX_QUIC_AES_256_GCM_IV_LEN + 20 + sizeof(time_t) + 2 + NGX_QUIC_MAX_CID_LEN + NGX_QUIC_AES_256_GCM_TAG_LEN)) {
    /* grow the buffer before calling ngx_quic_new_token() */
}

Type guard

#define ngx_quic_token_buf_ok(t) ((t)->len >= (size_t) NGX_QUIC_TOKEN_BUF_SIZE)

Try / catch

rc = ngx_quic_new_token(log, sa, socklen, key, &token, &odcid, exp, is_retry);
if (rc != NGX_OK) { /* logged as ALERT; skip NEW_TOKEN/retry for this connection */ }

Prevention

When it happens

Trigger: Third-party or patched code calling ngx_quic_new_token() with token->len < 12 + 20 + sizeof(time_t) + 2 + odcid->len + 16; local patches enlarging the ODCID or expiry fields; platforms with sizeof(time_t) > 8.

Common situations: Custom modules built into nginx that generate tokens; forks that resized token fields without resizing the buffer.

Related errors


AI-assisted analysis of nginx/nginx@3f6f7824d4 (2026-08-22). Data as JSON: /api/errors/608fa86dd7ce0b8c. Report an issue: GitHub.

Appendix: source

Thrown at src/event/quic/ngx_event_quic_tokens.c:75

    p = ngx_cpymem(p, &exp, sizeof(time_t));

    *p++ = is_retry ? 1 : 0;

    if (odcid) {
        *p++ = odcid->len;
        p = ngx_cpymem(p, odcid->data, odcid->len);

    } else {
        *p++ = 0;
    }

    len = p - in;

    cipher = EVP_aes_256_gcm();
    iv_len = NGX_QUIC_AES_256_GCM_IV_LEN;

    if ((size_t) (iv_len + len + NGX_QUIC_AES_256_GCM_TAG_LEN) > token->len) {
        ngx_log_error(NGX_LOG_ALERT, log, 0, "quic token buffer is too small");
        return NGX_ERROR;
    }

    ctx = EVP_CIPHER_CTX_new();
    if (ctx == NULL) {
        return NGX_ERROR;
    }

    iv = token->data;

    if (RAND_bytes(iv, iv_len) <= 0
        || !EVP_EncryptInit_ex(ctx, cipher, NULL, key, iv))
    {
        EVP_CIPHER_CTX_free(ctx);
        return NGX_ERROR;
    }

    token->len = iv_len;

View on GitHub (pinned to 3f6f7824d4)