Back to Blog
critical SEVERITY6 min read

How Missing Authentication on DELETE Endpoints Happens in Python aiohttp and How to Fix It

A critical missing authentication vulnerability in `pz_minimax.py` allowed any network-connected user to delete stored MiniMax prompts via the `DELETE /pz_easyuse/minimax-prompts/{index}` endpoint without any access control. An attacker could enumerate sequential indices to wipe all user-created prompts from the shared JSON file. The fix restricts the DELETE endpoint to localhost-only requests by checking `request.remote` against loopback addresses.

O
By Orbis AppSec
•Technically reviewed by Anupam Mediratta•Published September 6, 2026•Reviewed September 6, 2026

Answer Summary

This is a missing authentication / broken access control vulnerability (CWE-306) in a Python aiohttp web route within `pz_minimax.py`, a ComfyUI plugin file. The `delete_minimax_prompt` function at line 79 accepted DELETE requests from any network client without verifying the caller's identity or origin. The fix adds a `_is_local_request()` guard that returns HTTP 403 Forbidden for any request not originating from `127.0.0.1` or `::1`, restricting destructive operations to the local machine.

Vulnerability at a Glance

cweCWE-306
fixAdded a localhost-only guard (`_is_local_request`) that rejects non-loopback requests with HTTP 403
riskAny network user can delete all stored prompts without authentication
languagePython (aiohttp)
root causeThe DELETE route handler had no access control check before performing destructive file operations
vulnerabilityMissing Authentication on Destructive Endpoint

Introduction

The pz_minimax.py file handles MiniMax prompt management for a ComfyUI plugin, exposing HTTP endpoints that let users create, update, and delete prompts stored in a shared JSON file. But a flaw in the delete_minimax_prompt function at line 79 created a serious security risk: the DELETE /pz_easyuse/minimax-prompts/{index} route had zero authentication or access control, meaning any device on the same network could silently delete every stored prompt.

This isn't a theoretical concern. ComfyUI instances are frequently exposed on local networks — and sometimes the open internet — for collaborative AI workflows. A single unauthenticated DELETE endpoint turns a productivity tool into a target for data destruction.

The Vulnerability Explained

What the code did (before the fix)

Here's the vulnerable endpoint as it existed at line 79 of pz_minimax.py:

@PromptServer.instance.routes.delete("/pz_easyuse/minimax-prompts/{index}")
async def delete_minimax_prompt(request):
    try:
        index = int(request.match_info["index"])
    except ValueError:
        ...

The function immediately parses the {index} path parameter and proceeds to delete the prompt at that position from a shared JSON file. There is no check on:

  • Who is making the request (no authentication)
  • Where the request originates (no IP filtering)
  • Whether the caller owns the prompt (no ownership verification)

How an attacker exploits this

The attack is trivially simple and requires no special tools — just curl or a basic script:

# Enumerate and delete all prompts by sequential index
for i in $(seq 0 100); do
  curl -X DELETE http://<comfyui-host>:8188/pz_easyuse/minimax-prompts/$i
done

Because prompts are stored in a shared JSON file and indices are sequential integers starting from 0, an attacker can:

  1. Enumerate all prompts by sending DELETE requests with incrementing indices
  2. Destroy every stored prompt in seconds
  3. Repeat the attack silently — there's no logging or rate limiting

This is a classic 2-step exploitation chain: network access → data destruction. The scanner flagged it as "Likely exploitable" because the endpoint is directly reachable over HTTP with no intervening middleware.

Real-world impact

For ComfyUI users, MiniMax prompts represent carefully crafted AI generation configurations. Losing them means:

  • Lost work: Hours of prompt engineering wiped out
  • No recovery: If no external backup exists, the prompts are gone permanently
  • Silent attack: Users may not realize prompts were deleted until they try to use them
  • Lateral risk: If this endpoint lacks auth, other endpoints in the same plugin may also be unprotected

The Fix

The PR introduces a focused, minimal change: a localhost-only guard function that blocks all non-local requests to the DELETE endpoint.

New helper function

A new _is_local_request function was added at line 79:

def _is_local_request(request):
    return request.remote in ("127.0.0.1", "::1")

This checks the request.remote property (which aiohttp populates with the client's IP address) against the IPv4 loopback (127.0.0.1) and IPv6 loopback (::1) addresses.

Before vs. After

Before (vulnerable):

@PromptServer.instance.routes.delete("/pz_easyuse/minimax-prompts/{index}")
async def delete_minimax_prompt(request):
    try:
        index = int(request.match_info["index"])
    except ValueError:
        ...

After (fixed):

def _is_local_request(request):
    return request.remote in ("127.0.0.1", "::1")


@PromptServer.instance.routes.delete("/pz_easyuse/minimax-prompts/{index}")
async def delete_minimax_prompt(request):
    if not _is_local_request(request):
        return web.json_response({"error": "Forbidden"}, status=403)

    try:
        index = int(request.match_info["index"])
    except ValueError:
        ...

Why this works

  1. Early rejection: The guard runs before any business logic, so unauthorized requests never reach the prompt deletion code
  2. HTTP 403 response: Returns a proper Forbidden status code with a JSON error body, maintaining API consistency
  3. Covers both IP versions: Checks both 127.0.0.1 (IPv4) and ::1 (IPv6) to handle dual-stack configurations
  4. Minimal blast radius: The change is scoped to exactly one file and one code path — the destructive DELETE endpoint — preserving all existing behavior for legitimate local users
  5. Reusable guard: The _is_local_request helper is extracted as a standalone function, making it easy to apply to other sensitive endpoints in the same file

Design consideration

For a local development tool like ComfyUI, localhost restriction is an appropriate security boundary. The tool is designed to run on a user's machine, so restricting destructive operations to local requests prevents network-based attacks while maintaining the expected user experience.

Key Takeaways

  • The delete_minimax_prompt function at line 79 of pz_minimax.py had no access control, allowing any network client to delete prompts by guessing sequential integer indices — a trivially exploitable pattern.
  • Sequential integer IDs as the sole resource identifier make enumeration attacks effortless — an attacker doesn't need to know anything about the data to delete all of it.
  • Localhost-only restriction via request.remote checking is an effective baseline for local development tools, but should be combined with additional controls for any network-exposed deployment.
  • Extracting the _is_local_request helper as a reusable function makes it easy to consistently apply the same guard to other sensitive endpoints like update_minimax_prompt.
  • Destructive operations (DELETE) deserve the strictest access controls — they should be the first endpoints audited in any security review.

How Orbis AppSec Detected This

  • Source: HTTP DELETE request from any network-connected client to /pz_easyuse/minimax-prompts/{index}, with the {index} path parameter as attacker-controlled input
  • Sink: The prompt deletion logic inside delete_minimax_prompt() in pz_minimax.py:79, which removes entries from the shared JSON prompt store
  • Missing control: No authentication, no IP-based access restriction, and no ownership verification before executing the destructive delete operation
  • CWE: CWE-306 — Missing Authentication for Critical Function
  • Fix: Added a _is_local_request() guard that checks request.remote against loopback addresses and returns HTTP 403 Forbidden for all non-local requests

Orbis AppSec automatically detected this vulnerability and opened a pull request with the fix. Try Orbis AppSec on your repositories to find and fix issues like this automatically.

Conclusion

This vulnerability is a textbook example of how a single missing access control check can turn a useful feature into an attack vector. The delete_minimax_prompt endpoint in pz_minimax.py did exactly what it was supposed to do — delete prompts — but it did it for anyone who asked, not just authorized users.

The fix is small (6 lines of code) but meaningful: it establishes a security boundary that didn't exist before. For developers building similar local-first tools with HTTP APIs, the lesson is clear: every state-changing endpoint needs explicit access control, even if you think the tool is only used locally. Networks are shared, ports get forwarded, and assumptions about who can reach your service are often wrong.

Prevention and further reading

View the Security Fix

Check out the pull request that fixed this vulnerability

View PR #2

Related Articles

critical

Discord Bot Auto-Role CWE-269: Privilege Escalation via role.position

A Discord.js bot's auto-role feature allowed privilege escalation where any user with ManageRoles permission could add Administrator roles to automatic assignment lists, regardless of their own role hierarchy. The vulnerability existed because role.position validation checked only the bot's permissions, not the invoking user's role hierarchy relative to the target role.

high

CVE-2026-54290: hono cors() Reflects Any Origin With Credentials

The `hono` CORS middleware, as resolved in this service at 4.12.8, reflected the caller's `Origin` header back in `Access-Control-Allow-Origin` while also emitting `Access-Control-Allow-Credentials: true` whenever the `origin` option was left at its `'*'` default. That combination makes any website a trusted origin for credentialed cross-origin reads. The dependency range was raised from `^4.7.1` to `^4.13.5`, moving the installed copy from 4.12.8 to 4.13.5.

critical

POST /api/generate Lacks Authentication, Allowing Unauthenticated

A resume generation endpoint in a Node.js backend accepted requests from any caller with network access, allowing attackers to consume OpenAI API quota without restriction. The vulnerability stemmed from missing authentication middleware on a cost-bearing endpoint. The fix adds mandatory API key validation via HTTP headers before processing any generation requests.

critical

SchedulePush.disableReminder Missing Authorization Check in push.js

The `disableReminder` method in the `SchedulePush` class allowed any user to disable push notification reminders for arbitrary user IDs by manipulating the `e.user_id` event parameter. The fix adds a `checkFriend()` authorization gate that verifies the requesting user has a valid friendship relationship with the bot before modifying subscription state.

critical

How Broken Object-Level Authorization happens in Express.js and how to fix it

A critical authorization flaw in `src/v1/routes/index.js` allowed any authenticated API key holder to access arbitrary budgets by manipulating the `budgetSyncId` URL parameter. The fix introduces an environment-based allowlist that validates budget access before processing requests.

high

How Missing Rate Limiting Enables Denial of Service Attacks in Node.js and How to Fix It

The k-skill-proxy server exposed multiple public API endpoints (`/health`, `/v1/vworld/search`, `/v1/fine-dust/report`, `/v1/assembly/bills`) without consistent rate limiting middleware, leaving them vulnerable to denial-of-service attacks. A `buildRateLimiter` function existed but wasn't applied to all endpoints. This fix ensures rate limiting is enforced on all public endpoints, preventing resource exhaustion attacks.