Engineering

Sub2API Billing Vulnerability and Fix Verification

A Sub2API billing vulnerability can leave upstream API usage uncharged when an API key is deleted while a request is still running. In the affected billing logic, a key quota or rate-limit counter update returns ErrAPIKeyNotFound, causing the entire billing transaction to roll back. That rollback can undo the user balance debit or subscription usage update even though the upstream provider has already processed the request. The upstream fix handles the missing key locally so that billing can continue. Sub2API v0.2.17 contains this fix, as confirmed by the fix commit and the billing code in that release.

On October 22, 2026, a low gross-margin email alert from the 3API monitoring dashboard prompted an investigation into an anonymized deployment. After correlating request activity, billing records, and API key events, the internal review concluded that the older billing flaw had been repeatedly exploited.

The incident findings come from that internal review. The public repository establishes the technical failure and its fix; it does not independently establish exploitation at a particular service. The affected deployment remains anonymous, and llmapi.pro is the publishing brand for this analysis.

How a gross margin alert exposed a billing discrepancy

A gross-margin drop signals a gap between revenue and cost. Changes in model traffic, pricing, cache accounting, or reporting delays can all produce that gap. Failed billing is another possible cause, so an alert should start an investigation rather than determine its conclusion.

In this case, reviewers compared three records on the same timeline: upstream usage, the user balance debit or subscription usage entry, and the lifecycle of the API key associated with the request. Billing failures and repeated behavior patterns provided the additional context behind the internal finding of exploitation.

3API supplied the alert that initiated the review. Fixing the billing engine requires deploying the relevant Sub2API code change and verifying the resulting accounting behavior.

Why ErrAPIKeyNotFound can roll back Sub2API billing

Completed usage survives the deletion of an API key

An API key authorizes requests and supports usage tracking and limits. Once a request has been authorized and sent upstream, deleting its local key does not reverse the computation already performed. The gateway still needs to account for that usage.

In this billing path, subscription usage, the user balance, key counters, and applicable upstream account quota updates share a database transaction. An error returned before commit rolls back the local changes. It cannot undo the upstream work. See the transaction and update order.

A missing key turns a counter failure into a billing failure

Both key quota and rate-limit counter updates require an active key record with deleted_at IS NULL. After a key is soft-deleted, the quota update maps its missing result to ErrAPIKeyNotFound; the rate-limit update returns the same error when it affects zero rows. The counter implementation shows those conditions.

Before the fix, either error could propagate out of the billing function and abort the whole transaction. The result was upstream consumption without the corresponding committed user charge or subscription usage entry.

This requires the vulnerable error handling to be present, deletion to occur while the request is in progress, and billing to enter an applicable key quota or rate-limit update branch. An older version number or a deleted key alone does not establish exposure or exploitation.

The subscription terminology also matters. In this path, SubscriptionCost increments daily, weekly, and monthly subscription usage. It does not collect or refund the subscription purchase price. Account quota updates are gateway accounting records, not the upstream provider's invoice. See the subscription usage update.

How the upstream fix preserves billing

Commit c2d5bbd93edfb3a14f7da28d2e62c9216f0bbc86 changes error handling in both key counter paths. The relevant condition is:

if err != nil && !errors.Is(err, service.ErrAPIKeyNotFound) {
    return err
}

A missing key no longer aborts billing. Its own counters remain unchanged, while the transaction can continue processing the user balance, subscription usage, and applicable account quota. Other errors still propagate and preserve the transaction's failure behavior. See the upstream patch.

The accounting principle is straightforward: deleting an access credential should not erase consumption that has already occurred. Handling one expected missing-record condition should also preserve failure handling for unrelated database errors.

The added tests cover successful balance charging after key deletion and continued failure on other key-counter database errors. Integration coverage checks that deleted-key counters stay unchanged and that the billing deduplication record is committed. These are useful acceptance criteria for deployment validation; test results still need to be established in the operator's own build and database environment. See the unit tests and integration tests in the fix commit.

How to verify the fix in Sub2API v0.2.17

The timeline separates the upstream repair from the later incident review:

Date Event What it establishes
October 2, 2026 The upstream billing fix was committed The patch addresses billing rollback after key deletion
October 16, 2026 Sub2API v0.2.17 was released The tag and its source provide a release that contains the fix
October 22, 2026 The anonymized incident was investigated The internal review date does not establish when the flaw or exploitation began

The v0.2.17 release page confirms the release. The comparison from the fix commit to v0.2.17 reports status: ahead and behind_by: 0, with the fix commit as the merge base. Both error-handling changes are also present in the tagged source.

The supported conclusion is that v0.2.17 includes the fix. This does not identify the first fixed release, establish a complete affected-version range, or recommend v0.2.17 as the latest release.

For a source build, these read-only commands check ancestry in a repository that has the relevant Git history:

git merge-base --is-ancestor c2d5bbd93edfb3a14f7da28d2e62c9216f0bbc86 v0.2.17
git merge-base --is-ancestor c2d5bbd93edfb3a14f7da28d2e62c9216f0bbc86 HEAD

The first command checks the release tag; the second checks the current checkout. Exit code 0 confirms the ancestry relationship, 1 means it is absent, and other errors require checking the available objects and history. Shallow clones may lack history, and a backported patch may have a different commit ID.

Inspect the actual code as well: a later change could revert an earlier fix. Finally, map the checked source to the binary or container image that is actually running.

How to upgrade and validate the billing fix

Record the version, build commit, or image digest of the running deployment. Select a compatible release whose code includes the fix, then review its release notes and migration requirements. v0.2.17 is the verified reference used here.

  1. Back up data and configuration with a tested recovery path. Preserve a consistent database backup, configuration, and required secrets. The deployment documentation describes forward database migrations; reverting may require restoring a backup rather than simply switching to an older image.
  2. Validate billing in an isolated environment. Use synthetic records and a mocked upstream to confirm that a missing key still permits correct user accounting and applicable account quota updates. Cover balance and subscription billing, as well as both key-counter paths.
  3. Check error handling and duplicate submissions. Other database errors should still fail correctly, and repeated settlement of the same request should not create a second charge. Extend the public tests to cover subscription, account, and custom billing paths used by the deployment.
  4. Update every instance that handles requests or billing. For Docker, pin a verified image version or digest and recreate the application containers. For binary deployments, install the appropriate build and restart the service through the existing deployment process. Verify that all active instances run the intended code.
  5. Reconcile accounting after deployment. Match request usage to balance changes or subscription counters, applicable account usage, and final billing status. Watch billing failures and unexplained discrepancies after the rollout.

Use the Sub2API deployment documentation for the commands and data layout applicable to the deployment. Updating the software changes future billing behavior. Historical discrepancies need a separate review; replaying model requests creates new usage and is not an accounting repair.

How to audit potentially missed charges

Start with requests that have upstream usage but no matching completed user billing entry. Then correlate key lifecycle events and transaction results. A deleted key or a missing row in one reporting table is insufficient on its own.

Normalize time zones, request identifiers, models, upstream channels, and the pricing rules applicable at the time. Check:

  • Whether upstream usage maps to the local request, including retries or multiple upstream attempts.
  • Whether billing ultimately committed and the balance debit or subscription usage entry already exists.
  • Whether key deletion, the failure reason, and the request timeline are consistent with this failure mode.
  • Whether normal delays, free allowances, refunds, manual adjustments, or pricing configuration explain the discrepancy.

The billing deduplication table is not a complete ledger by itself. This implementation writes the deduplication record and billing changes within the same transaction. A rollback removes both, and archival behavior can change where records are stored. See the transaction and deduplication code.

Prepare a reconciliation record with the request reference, calculation basis, and amount already posted before making any historical adjustment. Resolve possible duplicates first, use the established accounting process, and leave requests with incomplete evidence pending review.

Distinguishing upstream cost from financial loss

Usage, accounting cost, estimated missed revenue, and cash loss measure different things. Adding them together can count the same event more than once.

Measure What it represents What to verify
Upstream usage Tokens, requests, or other consumed units Usage is an input to cost calculation, not a monetary loss by itself
Accounting cost The value assigned under the applicable cost rules Dashboard estimates, prepaid credit consumption, and final provider invoices may differ
Estimated uncollected charges The difference between expected and posted user charges Exclude free usage, discounts, refunds, and duplicates; subscription usage needs its own treatment
Cash loss Loss established through payment records and subsequent recovery or adjustments Reconcile payments, prepaid balances, refunds, and recoveries without counting costs or missed charges twice

A subscription may already have been paid for even when a request fails to consume its allowance. That weakens quota enforcement and cost control, but it does not mean another subscription payment was missed. Likewise, an omitted balance debit does not automatically equal a cash outflow in the same reporting period.

For usage-based billing, the LLM API pay-as-you-go pricing guide explains the relationship between usage and charges. Historical reconciliation should use the prices and rules that applied when each request occurred.

Monitoring API billing after the fix

Gross-margin alerts help identify aggregate discrepancies. Request-level billing signals help locate the failure responsible for them.

Signal Operational value
Billing failures and transaction rollbacks Identify persistent failures by error category
Upstream usage without completed user accounting Detect usage and billing mismatches after the normal settlement delay
Key deletions correlated with billing failures Provide a review signal that requires context before attributing abuse
Gross margin by model and upstream channel Separate traffic and pricing changes from billing failures
Running build versions and remaining discrepancies Identify missed instances and historical issues that still need review

Set thresholds around the deployment's settlement delay, request volume, and billing model. HTTP success rates measure request availability; confirming that usage was posted correctly requires separate accounting checks. The 429 Retry-After engineering guide covers related rate-limit and retry behavior.

For developers using an API service, begin by matching the API key to its billing mode and ledger, then check usage from a small set of requests. LLM API provides model access for Claude Code, Codex CLI, and compatible applications, with separate allowance or balance rules for subscription and pay-as-you-go use. Start with the API key and integration documentation, then review subscription allowances or pay-as-you-go channel pricing.

Frequently asked questions

Does Sub2API v0.2.17 include the billing fix

Yes. The public commit history and tagged billing source confirm that v0.2.17 contains it. Operators should still verify the code in their running build; this finding does not identify the first fixed release or the latest available release.

Does ErrAPIKeyNotFound prove that the vulnerability was exploited

No. Establish the cause using upstream usage, final billing status, key lifecycle events, and the request timeline. A single error or key deletion does not prove exploitation.

Does upgrading automatically recover historical missed charges

No automatic recovery should be assumed. This patch changes billing execution; it does not provide an automatic historical reconciliation procedure. Review past discrepancies separately and prevent duplicate charges.

Can a 3API gross margin alert fix the Sub2API billing engine

No. In this case, the alert prompted investigation and reconciliation. Repairing the engine requires deploying code that contains the fix and validating its billing behavior.

Is the cost shown on a dashboard the same as actual loss

No. Reconcile upstream usage, cost calculations, expected user charges, posted entries, and actual financial adjustments separately. In particular, missing subscription usage cannot simply be priced at a pay-as-you-go rate and labeled cash loss.

分享这篇文章

开始使用 LLM API

免费套餐可用。Claude Code 一行配置。

免费开始