CVE-2026-48076
Full vulnerability record from the local CVENow database.
Description
OpenReception's appointment booking software provides an end-to-end encrypted appointment booking platform. The new-client booking flow in versions 1.0.1 and prior consists of three calls: `bootstrap-challenge` (returns a 16-bit PoW challenge with `difficulty=4` leading hex zeroes), `bootstrap-verify` (validates the PoW and issues a Bearer booking access token), and `create-new-client` (consumes the token and creates the tunnel and first appointment). The token correctly binds to `tenantId`, `tunnelId`, `clientPublicKey`, and `emailHash`, but never to `channelId`. The `bootstrap-challenge` request schema does not even accept a `channelId`, and the issued token's payload contains no channel information. Independently, the service function `createNewClientWithAppointment` checks only `channel.archived = false`. The `channel.isPublic` check that protects `addAppointmentToTunnel` is missing in the new-client path. The combination means: an attacker completes the bootstrap flow normally (16-bit PoW, completes in well under one second on commodity hardware, no rate limiting beyond the throttle store), receives a valid booking access token, and then submits the `create-new-client` payload with `channelId` pointing to a private (`isPublic = false`) channel. The booking lands as `CONFIRMED` if the target channel has `requiresConfirmation = false` (the default), otherwise as `NEW`. The patient-facing UI does not list private channels in its picker (`/api/public/channels` correctly filters `isPublic = true`), so the channel ID must be obtained out of band. The companion finding V-10 (schedule endpoint discloses private channels) provides exactly that: a single unauthenticated GET reveals every private channel ID for any tenant. V-10 plus V-11 together make private channels fully reachable to anonymous attackers. As of time of publication, no known patched versions are available.
View original CVE JSON
{
"id": "CVE-2026-48076",
"sourceIdentifier": "[email protected]",
"published": "2026-08-06T22:17:10.127",
"lastModified": "2026-10-23T21:10:00.157",
"vulnStatus": "Deferred",
"cveTags": [],
"descriptions": [
{
"lang": "en",
"value": "OpenReception's appointment booking software provides an end-to-end encrypted appointment booking platform. The new-client booking flow in versions 1.0.1 and prior consists of three calls: `bootstrap-challenge` (returns a 16-bit PoW challenge with `difficulty=4` leading hex zeroes), `bootstrap-verify` (validates the PoW and issues a Bearer booking access token), and `create-new-client` (consumes the token and creates the tunnel and first appointment). The token correctly binds to `tenantId`, `tunnelId`, `clientPublicKey`, and `emailHash`, but never to `channelId`. The `bootstrap-challenge` request schema does not even accept a `channelId`, and the issued token's payload contains no channel information. Independently, the service function `createNewClientWithAppointment` checks only `channel.archived = false`. The `channel.isPublic` check that protects `addAppointmentToTunnel` is missing in the new-client path. The combination means: an attacker completes the bootstrap flow normally (16-bit PoW, completes in well under one second on commodity hardware, no rate limiting beyond the throttle store), receives a valid booking access token, and then submits the `create-new-client` payload with `channelId` pointing to a private (`isPublic = false`) channel. The booking lands as `CONFIRMED` if the target channel has `requiresConfirmation = false` (the default), otherwise as `NEW`. The patient-facing UI does not list private channels in its picker (`/api/public/channels` correctly filters `isPublic = true`), so the channel ID must be obtained out of band. The companion finding V-10 (schedule endpoint discloses private channels) provides exactly that: a single unauthenticated GET reveals every private channel ID for any tenant. V-10 plus V-11 together make private channels fully reachable to anonymous attackers. As of time of publication, no known patched versions are available."
},
{
"lang": "es",
"value": "El software de reserva de citas de OpenReception proporciona una plataforma de reserva de citas cifrada de extremo a extremo. El flujo de reserva de nuevo cliente en las versiones 1.0.1 y anteriores consta de tres llamadas: “bootstrap-challenge” (devuelve un desafío PoW de 16 bits con “difficulty=4” ceros hexadecimales iniciales), “bootstrap-verify” (valida el PoW y emite un token de acceso de reserva Bearer), y “create-new-client” (consume el token y crea el túnel y la primera cita). El token se vincula correctamente a “tenantId”, “tunnelId”, “clientPublicKey”, y “emailHash”, pero nunca a “channelId”. El esquema de solicitud de “bootstrap-challenge” ni siquiera acepta un “channelId”, y la carga útil del token emitido no contiene información de canal. Independientemente, la función de servicio “createNewClientWithAppointment” solo verifica “channel.archived = false”. La verificación de “channel.isPublic” que protege “addAppointmentToTunnel” falta en la ruta de nuevo cliente. La combinación significa: un atacante completa el flujo de arranque normalmente (PoW de 16 bits, se completa en bastante menos de un segundo en hardware comercial, sin limitación de velocidad más allá del almacén de aceleración), recibe un token de acceso de reserva válido, y luego envía la carga útil de “create-new-client” con “channelId” apuntando a un canal privado (“isPublic = false”). La reserva se registra como “CONFIRMED” si el canal de destino tiene “requiresConfirmation = false” (el valor predeterminado), de lo contrario, como “NEW”. La interfaz de usuario orientada al paciente no lista canales privados en su selector (“/api/public/channels” filtra correctamente “isPublic = true”), por lo que el ID del canal debe obtenerse fuera de banda. El hallazgo complementario V-10 (el endpoint de programación revela canales privados) proporciona exactamente eso: una única solicitud GET no autenticada revela cada ID de canal privado para cualquier inquilino. V-10 más V-11 juntos hacen que los canales privados sean totalmente accesibles para atacantes anónimos. A partir del momento de la publicación, no hay versiones parcheadas conocidas disponibles."
}
],
"affected": [
{
"source": "[email protected]",
"affectedData": [
{
"vendor": "open-reception",
"product": "appointment-booking-software",
"versions": [
{
"version": "<= 1.0.1",
"status": "affected"
}
]
}
]
}
],
"metrics": {
"cvssMetricV31": [
{
"source": "[email protected]",
"type": "Secondary",
"cvssData": {
"version": "3.1",
"vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:L",
"baseScore": 6.5,
"baseSeverity": "MEDIUM",
"attackVector": "NETWORK",
"attackComplexity": "LOW",
"privilegesRequired": "NONE",
"userInteraction": "NONE",
"scope": "UNCHANGED",
"confidentialityImpact": "NONE",
"integrityImpact": "LOW",
"availabilityImpact": "LOW"
},
"exploitabilityScore": 3.9,
"impactScore": 2.5
}
],
"ssvcV203": [
{
"source": "134c704f-9b21-4f2e-91b3-4a467353bcc0",
"ssvcData": {
"timestamp": "2026-08-07T14:34:15.376977Z",
"id": "CVE-2026-48076",
"options": [
{
"exploitation": "poc"
},
{
"automatable": "yes"
},
{
"technicalImpact": "partial"
}
],
"role": "CISA Coordinator",
"version": "2.0.3"
}
}
]
},
"weaknesses": [
{
"source": "[email protected]",
"type": "Secondary",
"description": [
{
"lang": "en",
"value": "CWE-863"
}
]
}
],
"references": [
{
"url": "https://github.com/open-reception/appointment-booking-software/security/advisories/GHSA-3658-3j75-p5j3",
"source": "[email protected]"
},
{
"url": "https://github.com/open-reception/appointment-booking-software/security/advisories/GHSA-3658-3j75-p5j3",
"source": "134c704f-9b21-4f2e-91b3-4a467353bcc0"
}
]
}