GHSA-46Q5-G3J9-WX5C

Vulnerability from github – Published: 2026-03-12 16:36 – Updated: 2026-03-13 13:35
VLAI?
Summary
ZeptoClaw: Generic webhook channel trusts caller-supplied identity fields; allowlist is checked against untrusted payload data
Details

Summary

The generic webhook channel trusts caller-supplied identity fields (sender, chat_id) from the request body and applies authorization checks to those untrusted values. Because authentication is optional and defaults to disabled (auth_token: None), an attacker who can reach POST /webhook can spoof an allowlisted sender and choose arbitrary chat_id values, enabling high-risk message spoofing and potential IDOR-style session/chat routing abuse.

Details

Relevant code paths:

  • src/channels/webhook.rs:121 sets runtime default auth_token: None.
  • src/config/types.rs:910 also defaults webhook config auth_token to None.
  • src/channels/webhook.rs:224 (validate_auth) explicitly allows requests when no token is configured.
  • src/channels/webhook.rs:128 defines WebhookPayload with identity fields fully controlled by caller input:
  • sender: String
  • chat_id: String
  • src/channels/webhook.rs:421 performs allowlist authorization using payload.sender.
  • src/channels/webhook.rs:433 and src/channels/webhook.rs:434 create InboundMessage using untrusted payload.sender and payload.chat_id.

Why this is vulnerable:

  • The system treats user-provided JSON identity as authoritative identity.
  • Allowlist enforcement does not verify sender authenticity beyond that payload value.
  • chat_id is also attacker-controlled, so routing/session association can be steered to arbitrary chats/conversations.
  • If the webhook is exposed without strong upstream authn/authz controls, spoofing is straightforward.

PoC

  1. Configure the webhook channel in a vulnerable posture (common default behavior):
  2. enabled = true
  3. bind_address = "0.0.0.0" (or any reachable interface)
  4. port = 9876
  5. path = "/webhook"
  6. auth_token = null (or omitted)
  7. allow_from = ["trusted-user-1"]
  8. deny_by_default = true
  9. Start ZeptoClaw.
  10. Send a forged request with attacker-chosen sender and chat_id, without any Authorization header:
curl -i -X POST "http://127.0.0.1:9876/webhook" \
  -H "Content-Type: application/json" \
  --data '{
    "message":"FORGED: run privileged workflow",
    "sender":"trusted-user-1",
    "chat_id":"victim-chat-42"
  }'
  1. Observe:
  2. Response is HTTP/1.1 200 OK.
  3. Message is accepted as if it originated from trusted-user-1.
  4. Message is routed under attacker-chosen chat_id (victim-chat-42).

Impact

  • Vulnerability type:
  • Authentication/authorization bypass (identity spoofing)
  • IDOR-style routing/control issue via attacker-chosen chat_id
  • Affected deployments:
  • Any deployment exposing the generic webhook endpoint without strict upstream authentication and identity binding.
  • Security consequences:
  • Forged inbound messages from spoofed trusted users.
  • Bypass of allowlist intent by injecting allowlisted sender IDs in payload.
  • Cross-chat/session contamination or hijacking by choosing arbitrary chat_id.
  • Potential unauthorized downstream agent/tool actions triggered by malicious input.
Show details on source website

{
  "affected": [
    {
      "database_specific": {
        "last_known_affected_version_range": "\u003c= 0.7.5"
      },
      "package": {
        "ecosystem": "crates.io",
        "name": "zeptoclaw"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "0.7.6"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-32231"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-306",
      "CWE-345"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-03-12T16:36:48Z",
    "nvd_published_at": "2026-03-12T19:16:17Z",
    "severity": "HIGH"
  },
  "details": "### Summary\nThe generic webhook channel trusts caller-supplied identity fields (`sender`, `chat_id`) from the request body and applies authorization checks to those untrusted values. Because authentication is optional and defaults to disabled (`auth_token: None`), an attacker who can reach `POST /webhook` can spoof an allowlisted sender and choose arbitrary `chat_id` values, enabling high-risk message spoofing and potential IDOR-style session/chat routing abuse.\n\n### Details\nRelevant code paths:\n\n- `src/channels/webhook.rs:121` sets runtime default `auth_token: None`.\n- `src/config/types.rs:910` also defaults webhook config `auth_token` to `None`.\n- `src/channels/webhook.rs:224` (`validate_auth`) explicitly allows requests when no token is configured.\n- `src/channels/webhook.rs:128` defines `WebhookPayload` with identity fields fully controlled by caller input:\n  - `sender: String`\n  - `chat_id: String`\n- `src/channels/webhook.rs:421` performs allowlist authorization using `payload.sender`.\n- `src/channels/webhook.rs:433` and `src/channels/webhook.rs:434` create `InboundMessage` using untrusted `payload.sender` and `payload.chat_id`.\n\nWhy this is vulnerable:\n\n- The system treats user-provided JSON identity as authoritative identity.\n- Allowlist enforcement does not verify sender authenticity beyond that payload value.\n- `chat_id` is also attacker-controlled, so routing/session association can be steered to arbitrary chats/conversations.\n- If the webhook is exposed without strong upstream authn/authz controls, spoofing is straightforward.\n\n### PoC\n1. Configure the webhook channel in a vulnerable posture (common default behavior):\n   - `enabled = true`\n   - `bind_address = \"0.0.0.0\"` (or any reachable interface)\n   - `port = 9876`\n   - `path = \"/webhook\"`\n   - `auth_token = null` (or omitted)\n   - `allow_from = [\"trusted-user-1\"]`\n   - `deny_by_default = true`\n2. Start ZeptoClaw.\n3. Send a forged request with attacker-chosen `sender` and `chat_id`, without any `Authorization` header:\n\n```bash\ncurl -i -X POST \"http://127.0.0.1:9876/webhook\" \\\n  -H \"Content-Type: application/json\" \\\n  --data \u0027{\n    \"message\":\"FORGED: run privileged workflow\",\n    \"sender\":\"trusted-user-1\",\n    \"chat_id\":\"victim-chat-42\"\n  }\u0027\n```\n\n4. Observe:\n   - Response is `HTTP/1.1 200 OK`.\n   - Message is accepted as if it originated from `trusted-user-1`.\n   - Message is routed under attacker-chosen `chat_id` (`victim-chat-42`).\n\n### Impact\n- Vulnerability type:\n  - Authentication/authorization bypass (identity spoofing)\n  - IDOR-style routing/control issue via attacker-chosen `chat_id`\n- Affected deployments:\n  - Any deployment exposing the generic webhook endpoint without strict upstream authentication and identity binding.\n- Security consequences:\n  - Forged inbound messages from spoofed trusted users.\n  - Bypass of allowlist intent by injecting allowlisted sender IDs in payload.\n  - Cross-chat/session contamination or hijacking by choosing arbitrary `chat_id`.\n  - Potential unauthorized downstream agent/tool actions triggered by malicious input.",
  "id": "GHSA-46q5-g3j9-wx5c",
  "modified": "2026-03-13T13:35:55Z",
  "published": "2026-03-12T16:36:48Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/qhkm/zeptoclaw/security/advisories/GHSA-46q5-g3j9-wx5c"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-32231"
    },
    {
      "type": "WEB",
      "url": "https://github.com/qhkm/zeptoclaw/pull/324"
    },
    {
      "type": "WEB",
      "url": "https://github.com/qhkm/zeptoclaw/commit/bf004a20d3687a0c1a9e052ec79536e30d6de134"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/qhkm/zeptoclaw"
    },
    {
      "type": "WEB",
      "url": "https://github.com/qhkm/zeptoclaw/releases/tag/v0.7.6"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:H/A:N",
      "type": "CVSS_V3"
    }
  ],
  "summary": "ZeptoClaw: Generic webhook channel trusts caller-supplied identity fields; allowlist is checked against untrusted payload data"
}


Log in or create an account to share your comment.




Tags
Taxonomy of the tags.


Loading…

Loading…

Loading…

Sightings

Author Source Type Date

Nomenclature

  • Seen: The vulnerability was mentioned, discussed, or observed by the user.
  • Confirmed: The vulnerability has been validated from an analyst's perspective.
  • Published Proof of Concept: A public proof of concept is available for this vulnerability.
  • Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
  • Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
  • Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
  • Not confirmed: The user expressed doubt about the validity of the vulnerability.
  • Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.


Loading…

Detection rules are retrieved from Rulezet.

Loading…

Loading…