Skip to content

feat(mint): remove deprecated v0 HTTP API#957

Open
b-l-u-e wants to merge 1 commit into
cashubtc:mainfrom
b-l-u-e:feat/mint-remove-deprecated-v0-HTTP-API
Open

feat(mint): remove deprecated v0 HTTP API#957
b-l-u-e wants to merge 1 commit into
cashubtc:mainfrom
b-l-u-e:feat/mint-remove-deprecated-v0-HTTP-API

Conversation

@b-l-u-e

@b-l-u-e b-l-u-e commented Mar 30, 2026

Copy link
Copy Markdown
Contributor

Here is what was done for #953 - remove deprecated mint v0 API:

Removed

  • cashu/mint/router_deprecated.py - root-level routes (/info, /keys, /mint, /melt, /split, /check, /restore, etc.) that duplicated the old pre-v1 surface.
  • tests/mint/test_mint_api_deprecated.py - already fully skipped; removed.
  • tests/fuzz/test_fuzz_mint_api_deprecated.py - fuzzing only the removed routes; removed.

Mint app

  • cashu/mint/app.py - mounts only the v1 router (no deprecated router). The file on disk already matched this after the edits.

Settings

  • debug_mint_only_deprecated removed from cashu/core/settings.py. It only toggled “deprecated-only” vs “v1 + deprecated”; with v0 gone it has no use.

Tests & helpers

  • tests/helpers.py - dropped is_deprecated_api_only.
  • All tests that branched on debug_mint_only_deprecated / is_deprecated_api_only were simplified (always exercise v1 behavior, or drop obsolete skipif / pytest.skip).
  • tests/mint/test_mint_melt.py - skip reason is now “only FakeWallet”; condition is not is_fake only.

CI / docs

  • .github/workflows/tests.yml, ci.yml, tests_redis_cache.yml - removed mint-only-deprecated input, matrix dimension, and DEBUG_MINT_ONLY_DEPRECATED env.
  • CONTRIBUTING.md - removed the “V0 API only” / DEBUG_MINT_ONLY_DEPRECATED subsection.

Not removed

  • Pydantic *_deprecated models in cashu/core/models.py and PostMeltResponse_deprecated usage in cashu/wallet/v1_api.py stay for interoperability with older mint JSON, not for serving the removed routes.

@github-project-automation github-project-automation Bot moved this to Backlog in nutshell Mar 30, 2026
@b-l-u-e b-l-u-e marked this pull request as draft March 30, 2026 06:07
@codecov

codecov Bot commented Mar 30, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 75.37%. Comparing base (85c959e) to head (84a8dd1).
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #957      +/-   ##
==========================================
+ Coverage   74.92%   75.37%   +0.45%     
==========================================
  Files         111      110       -1     
  Lines       12065    11941     -124     
==========================================
- Hits         9040     9001      -39     
+ Misses       3025     2940      -85     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@b-l-u-e b-l-u-e closed this Mar 31, 2026
@github-project-automation github-project-automation Bot moved this from Backlog to Done in nutshell Mar 31, 2026
@b-l-u-e

b-l-u-e commented Mar 31, 2026

Copy link
Copy Markdown
Contributor Author

CI failed tests shows error

tests/mint/test_mint_melt.py:779: in <module>
    @pytest.mark.skipif(is_deprecated_api_only, reason="Can't run on the deprecated API")
E   NameError: name 'is_deprecated_api_only' is not defined

current workspace file ends at line 767 and has no line 779

@b-l-u-e b-l-u-e reopened this Mar 31, 2026
@b-l-u-e b-l-u-e marked this pull request as ready for review March 31, 2026 11:28
@a1denvalu3

Copy link
Copy Markdown
Collaborator

title: "Accidental Revert of Pydantic List String DoS Protection during Deprecated API Removal"
slug: reverted-pydantic-list-str-dos-protection
date: 2026-05-19
status: confirmed
severity: high
target: [cashubtc/nutshell]
nuts: []

Summary

During the removal of the deprecated v0 HTTP API in this PR branch (feat/mint-remove-deprecated-v0-HTTP-API), the cashu/core/models.py file was inadvertently restored to an older monolithic version (reverting the modularization done previously). This reversion completely removed multiple critical security and stability fixes from main, most notably the fix for a Denial of Service (DoS) vulnerability where Pydantic list string fields were not correctly bounded by max_length.

Root Cause

In Python's Pydantic V2, using Field(..., max_length=N) on a List[str] applies the max_length restriction to the number of elements in the list, not the length of the strings within the list.

This bug was previously fixed in main (in PR #987) by updating list string fields to use Annotated[str, Field(max_length=...)] so both the list size and string sizes are correctly bounded. Additionally, the models were modularized under cashu/core/models/ in main (in PR #960).

Because cashu/core/models.py was mistakenly restored to its pre-modularized monolithic state in this PR branch (feat/mint-remove-deprecated-v0-HTTP-API), this DoS protection was removed. For example, in the current branch's cashu/core/models.py:

class PostCheckStateRequest(BaseModel):
    Ys: List[str] = Field(..., max_length=settings.mint_max_request_length)

This allows an attacker to send an arbitrarily long string as an element in the Ys list, causing massive memory consumption during JSON parsing and Pydantic validation, potentially leading to a DoS condition on the mint API server.

Attack Steps

  1. An attacker identifies an endpoint that accepts a list of strings, such as POST /v1/checkstate which takes a PostCheckStateRequest.
  2. The attacker constructs a JSON payload where Ys is a list containing a single, extremely large string (e.g., 100MB of 'A's): {"Ys": ["A" * 100_000_000]}.
  3. The attacker sends this payload to the POST /v1/checkstate endpoint.
  4. Because the max_length constraint on the Ys field applies only to the list length (which is 1), Pydantic attempts to allocate and process the 100MB string.
  5. Sending multiple such concurrent requests easily exhausts the server's memory, leading to an Out of Memory (OOM) crash and Denial of Service.

Impact

An unauthenticated attacker can crash the mint server by sending excessively large strings in list fields, causing a Denial of Service (DoS) through memory exhaustion.

Test Results

A PoC script confirming that the Pydantic model successfully accepts arbitrarily long strings inside list structures on this branch:

from cashu.core.models import PostCheckStateRequest
from pydantic import ValidationError

try:
    payload = {"Ys": ["A" * 100_000_000]}
    req = PostCheckStateRequest(**payload)
    print("VULNERABLE: Parsed successfully without length validation on string elements!")
except ValidationError as e:
    print("SECURE: Validation failed!")

Output on PR branch:

VULNERABLE: Parsed successfully without length validation on string elements!

Proposed Fix

Do not revert the modularization of cashu/core/models/. Instead, apply the deprecation removals to the newly modularized files in cashu/core/models/ (e.g., deleting cashu/core/models/info.py's deprecated models and cashu/core/models/check.py's deprecated models). Revert the monolithic cashu/core/models.py back to the modularized structure found in main to restore the DoS protections and other bug fixes.

Signed-off-by: b-l-u-e <8102260+blue@users.noreply.github.com>
@b-l-u-e b-l-u-e force-pushed the feat/mint-remove-deprecated-v0-HTTP-API branch from e49be1a to 84a8dd1 Compare May 21, 2026 20:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

2 participants