Vulnerabilities in pkg:npm/@geolens/sdk

PACKAGE
Advisory Identifier: GHSA-p23g-mvhj-jh3j
Advisory Summary

CVE-2026-55178 is a HIGH (CVSS 7.5) cross-dataset authorization bypass discloses private vulnerability (CWE-639: Authorization Bypass Through User-Controlled Key) affecting GeoLens libraries in the npm ecosystem. The issue involves cross-dataset authorization bypass discloses private dataset metadata, schema, sample values, table rows, and raster/vector tile data. Remediation is available by upgrading affected packages to version 1.2.3.

1 Known Advisory Record(s)
Package Vulnerability Intelligence

pkg:npm/@geolens/sdk

1 Known Advisory Record(s)

Vulnerability advisories affecting package pkg:npm/@geolens/sdk. Select an advisory below to view technical details or fixes.

Advisory ID CVE / NVD Severity Summary
GHSA-p23g-mvhj-jh3j CVE-2026-55178 HIGH GeoLens: Cross-dataset authorization bypass discloses private dataset metadata, schema, sample values, table rows, and raster/vector tile data

CVE-2026-55178 at a Glance

CVE Identifier CVE-2026-55178
GHSA Identifier GHSA-p23g-mvhj-jh3j
Severity HIGH
CVSS v3.1 Base Score 7.5
CWE Classification CWE-639: Authorization Bypass Through User-Controlled Key
Affected Product GeoLens
Package Ecosystem npm
Published Date
Last Updated

Security Impact

CVSS: 7.5

The security impact metrics below are parsed directly from the CVSS v3.1 vector string (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N).

Attack Vector Network (AV:N)
Attack Complexity Low (AC:L)
Privileges Required None (PR:N)
User Interaction None (UI:N)
Scope Unchanged (S:U)
Confidentiality High (C:H)
Integrity None (I:N)
Availability None (A:N)

How to Fix CVE-2026-55178

To remediate this vulnerability, upgrade all affected GeoLens dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.

@geolens/sdk fixed: 1.2.3
npm install @geolens/sdk@1.2.3
geolens-cli fixed: 1.2.3
pip install geolens-cli>=1.2.3
geolens fixed: 1.2.3
pip install geolens>=1.2.3
Verify Direct and Transitive Dependencies

Run the following command in your project directory to verify that all resolved dependencies use the patched release:

npm ls @geolens/sdk

How to Check if You Are Affected

To determine whether your Node.js application is affected by CVE-2026-55178, inspect your project dependencies using npm:

npm ls @geolens/sdk

Analyze the terminal output to locate any version of GeoLens in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than 1.2.3), your application is affected.

Note: The npm ls @geolens/sdk command inspects dependencies declared in your package.json and lockfile; it does not perform automated runtime dynamic scanning.

Technical Details

Vulnerability Mechanism & Technical Analysis

This vulnerability is classified under CWE-639: Authorization Bypass Through User-Controlled Key, where the system's authorization functionality does not prevent one user from gaining access to another user's data or record by modifying the key value identifying the data. In GeoLens, software state validation or input boundaries are circumvented during processing. Review the official source advisory statement below for specific affected components, classes, and reproduction details.

Source Advisory Statement

### Summary Multiple GeoLens read/link endpoints authorized only the resource named in the request URL (a map, a VRT, a source dataset, an AI request) and failed to re-authorize a **second, caller-influenced dataset** that the request reached through a relationship, layer reference, mosaic source, or request body. This "authorize the URL resource, read a *different* dataset un-re-authorized" pattern let callers read data from datasets they have no access to. The most severe instances require **no authentication at all** (anonymous, network-only). Others require only the **default `editor` role** that any self-service signup / upload user receives. All issues are fixed in **1.2.3**. There is no complete configuration workaround — upgrading is the only full remediation. ### Impact Depending on the endpoint, an attacker can read, for datasets they cannot otherwise access: - the dataset's **vector tile data** (actual feature geometries/attributes), - the dataset's **raster pixels**, - backing-table **rows**, - and **metadata** — table name, column schema, feature count, extent, source URL/filename, contacts, and **sampled row values**. ### Affected versions All versions **prior to 1.2.3** (includes the published 1.0.0, 1.2.0, and 1.2.2 releases and their PyPI/npm/GHCR artifacts). Fixed in **1.2.3**. ### Findings **1. Anonymous metadata + private vector-tile disclosure via public maps (PR #235)** `GET /maps/{id}` and `GET /maps/{id}/style.json` authorized the map but not each layer's backing dataset. A public map that references a private dataset leaked that dataset's table name, column schema, feature count, extent, and sampled values to anonymous callers. `style.json` additionally returned a vector-tile URL carrying an HMAC signature bound to **neither user nor map**, which the tile endpoint accepts for non-public datasets with no user check — so the signature is **replayable** to read the private dataset's actual vector tiles. *(Anonymous · High)* **2. Anonymous private-row disclosure via dataset relationships (PR #234)** The dataset FK-relationship APIs authorized only the source dataset from the URL, never the relationship target. A public dataset with a relationship to a private dataset let an anonymous caller enumerate the relationship (obtaining the private target's id/title and the relationship id) and then call the related-record endpoint to read **rows from the private target's backing table**. *(Anonymous · High)* **3. Anonymous metadata disclosure via OGC `externalId` lookup (PR #236)** `GET /collections/datasets/items?externalId=<uuid>` resolved the dataset by id and returned the full OGC catalog record (title, summary, bbox, keywords, contacts, distributions, source org) with **no visibility check** — the user was never threaded into the lookup. An anonymous caller could read any private, restricted, or unpublished dataset's metadata by UUID. *(Anonymous · High)* **4. Cross-tenant raster pixel disclosure via VRT mosaics — SEC-C (PR #237)** An authenticated user with the default `editor` upload permission could mosaic another user's **private raster** into a VRT they own, then read the victim's **pixels** back through raster tile / quicklook / COG endpoints that authorize only the attacker-owned VRT. VRT member pixels are compiled into one served asset and cannot be filtered at read time, so the fix authorizes every source dataset at write/link time. *(Authenticated `editor` · High)* **5. Cross-tenant metadata/sample-data disclosure via AI metadata endpoints — SEC-D (PR #238)** The `POST /ai/metadata/{summary,keywords,lineage,quality-statement}` endpoints were gated only by the `use_ai_chat` permission (held by the default `editor` role). The attacker-controlled `dataset_id` in the request body flowed into the LLM prompt context with no visibility filter, rendering **any** dataset's title, summary, source URL, filename, column schema, and **sample values** into the response. *(Authenticated `editor` · High)* **6. Residual VRT member disclosure for legacy links — SEC-E (PR #237)** Link-time authorization (finding 4) does not re-authorize pre-existing `vrt_source_links`, so legacy or authorization-drift links still leaked member metadata and health via the VRT source-listing/status endpoints until a per-member read filter was added. *(Medium)* ### Patches Fixed in **1.2.3** by, in order: - `31a103b9` — fix(catalog): authorize relationship targets in related-record endpoints (#234) - `01bc87da` — fix(maps): re-authorize each layer's dataset on anonymous map read endpoints (#235) - `407c0688` — fix(ogc): enforce dataset visibility on the externalId OGC item lookup (#236) - `2c031da8` — fix(vrt): authorize VRT source datasets at link time + filter unauthorized members on read (#237) - `07dfb1c6` — fix(ai): authorize the requested dataset on AI metadata endpoints (#238) The fixes follow the codebase's established per-dataset re-authorization pattern (`can_access_dataset` / `check_dataset_access_or_anonymous`), filtering at read time and authorizing cross-dataset references at link/write time. ### Workarounds There is **no complete configuration workaround**; the anonymous findings require only network access to the API. Operators who cannot upgrade immediately should restrict network exposure of the API and avoid co-locating private datasets with public maps/relationships, but **upgrading to 1.2.3 is the only full remediation**. ### Remediation Upgrade to GeoLens **1.2.3**: - Container images: `ghcr.io/geolens-io/geolens-api:1.2.3` (+ worker/frontend) - Python SDK: `geolens==1.2.3` · CLI: `geolens-cli==1.2.3` · npm: `@geolens/sdk@1.2.3`

CVE-2026-55178 Affected GeoLens Versions

3 component(s)
Fixed Versions:
1.2.3
Product / Package Ecosystem Affected Versions Fixed Version
@geolens/sdk
npm
< 1.2.3
1.2.3
geolens-cli
PyPI
< 1.2.3
1.2.3
geolens
PyPI
< 1.2.3
1.2.3

References

Frequently Asked Questions

What is CVE-2026-55178?
CVE-2026-55178 is a security vulnerability in GeoLens involving Cross-dataset authorization bypass discloses private dataset metadata, schema, sample values, table rows, and raster/vector tile data under CWE-639: Authorization Bypass Through User-Controlled Key.
Which GeoLens versions are affected?
Affected versions include releases prior to 1.2.3 across affected packages: @geolens/sdk, geolens-cli, geolens.
What version fixes CVE-2026-55178?
Upgrading to 1.2.3 (or the latest patched release for your respective branch) resolves the vulnerability.
Is @geolens/sdk affected?
Yes, @geolens/sdk is affected in releases prior to 1.2.3. Upgrade your dependency to 1.2.3 or later.
Is geolens-cli affected?
Yes, geolens-cli is affected in releases prior to 1.2.3. Upgrade your dependency to 1.2.3 or later.
What is the CVSS score of CVE-2026-55178?
CVE-2026-55178 has a CVSS v3.1 base score of 7.5 (HIGH) with vector string CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N.
What CWE is associated with CVE-2026-55178?
CVE-2026-55178 is classified under CWE-639: Authorization Bypass Through User-Controlled Key (The system's authorization functionality does not prevent one user from gaining access to another user's data or record by modifying the key value identifying the data.).
How can I check npm dependencies for CVE-2026-55178?
Run the dependency tree command: 'npm ls @geolens/sdk'. This command lists direct and transitive dependencies in your build configuration so you can verify if a vulnerable version is resolved.
Machine-readable OSV JSON OSV v1.5 Schema
Normalized schema output
{
  "schema_version" : "1.4.0",
  "id" : "GHSA-p23g-mvhj-jh3j",
  "modified" : "2026-08-18T18:00:08Z",
  "published" : "2026-08-18T18:00:07Z",
  "aliases" : [ "CVE-2026-55178" ],
  "summary" : "GeoLens: Cross-dataset authorization bypass discloses private dataset metadata, schema, sample values, table rows, and raster/vector tile data",
  "details" : "### Summary\n\nMultiple GeoLens read/link endpoints authorized only the resource named in the\nrequest URL (a map, a VRT, a source dataset, an AI request) and failed to\nre-authorize a **second, caller-influenced dataset** that the request reached\nthrough a relationship, layer reference, mosaic source, or request body. This\n\"authorize the URL resource, read a *different* dataset un-re-authorized\"\npattern let callers read data from datasets they have no access to.\n\nThe most severe instances require **no authentication at all** (anonymous,\nnetwork-only). Others require only the **default `editor` role** that any\nself-service signup / upload user receives.\n\nAll issues are fixed in **1.2.3**. There is no complete configuration\nworkaround — upgrading is the only full remediation.\n\n### Impact\n\nDepending on the endpoint, an attacker can read, for datasets they cannot\notherwise access:\n\n- the dataset's **vector tile data** (actual feature geometries/attributes),\n- the dataset's **raster pixels**,\n- backing-table **rows**,\n- and **metadata** — table name, column schema, feature count, extent, source\n  URL/filename, contacts, and **sampled row values**.\n\n### Affected versions\n\nAll versions **prior to 1.2.3** (includes the published 1.0.0, 1.2.0, and\n1.2.2 releases and their PyPI/npm/GHCR artifacts). Fixed in **1.2.3**.\n\n### Findings\n\n**1. Anonymous metadata + private vector-tile disclosure via public maps (PR #235)**\n`GET /maps/{id}` and `GET /maps/{id}/style.json` authorized the map but not\neach layer's backing dataset. A public map that references a private dataset\nleaked that dataset's table name, column schema, feature count, extent, and\nsampled values to anonymous callers. `style.json` additionally returned a\nvector-tile URL carrying an HMAC signature bound to **neither user nor map**,\nwhich the tile endpoint accepts for non-public datasets with no user check —\nso the signature is **replayable** to read the private dataset's actual vector\ntiles. *(Anonymous · High)*\n\n**2. Anonymous private-row disclosure via dataset relationships (PR #234)**\nThe dataset FK-relationship APIs authorized only the source dataset from the\nURL, never the relationship target. A public dataset with a relationship to a\nprivate dataset let an anonymous caller enumerate the relationship (obtaining\nthe private target's id/title and the relationship id) and then call the\nrelated-record endpoint to read **rows from the private target's backing\ntable**. *(Anonymous · High)*\n\n**3. Anonymous metadata disclosure via OGC `externalId` lookup (PR #236)**\n`GET /collections/datasets/items?externalId=<uuid>` resolved the dataset by id\nand returned the full OGC catalog record (title, summary, bbox, keywords,\ncontacts, distributions, source org) with **no visibility check** — the user\nwas never threaded into the lookup. An anonymous caller could read any\nprivate, restricted, or unpublished dataset's metadata by UUID. *(Anonymous ·\nHigh)*\n\n**4. Cross-tenant raster pixel disclosure via VRT mosaics — SEC-C (PR #237)**\nAn authenticated user with the default `editor` upload permission could mosaic\nanother user's **private raster** into a VRT they own, then read the victim's\n**pixels** back through raster tile / quicklook / COG endpoints that authorize\nonly the attacker-owned VRT. VRT member pixels are compiled into one served\nasset and cannot be filtered at read time, so the fix authorizes every source\ndataset at write/link time. *(Authenticated `editor` · High)*\n\n**5. Cross-tenant metadata/sample-data disclosure via AI metadata endpoints — SEC-D (PR #238)**\nThe `POST /ai/metadata/{summary,keywords,lineage,quality-statement}` endpoints\nwere gated only by the `use_ai_chat` permission (held by the default `editor`\nrole). The attacker-controlled `dataset_id` in the request body flowed into the\nLLM prompt context with no visibility filter, rendering **any** dataset's\ntitle, summary, source URL, filename, column schema, and **sample values** into\nthe response. *(Authenticated `editor` · High)*\n\n**6. Residual VRT member disclosure for legacy links — SEC-E (PR #237)**\nLink-time authorization (finding 4) does not re-authorize pre-existing\n`vrt_source_links`, so legacy or authorization-drift links still leaked member\nmetadata and health via the VRT source-listing/status endpoints until a\nper-member read filter was added. *(Medium)*\n\n### Patches\n\nFixed in **1.2.3** by, in order:\n\n- `31a103b9` — fix(catalog): authorize relationship targets in related-record endpoints (#234)\n- `01bc87da` — fix(maps): re-authorize each layer's dataset on anonymous map read endpoints (#235)\n- `407c0688` — fix(ogc): enforce dataset visibility on the externalId OGC item lookup (#236)\n- `2c031da8` — fix(vrt): authorize VRT source datasets at link time + filter unauthorized members on read (#237)\n- `07dfb1c6` — fix(ai): authorize the requested dataset on AI metadata endpoints (#238)\n\nThe fixes follow the codebase's established per-dataset re-authorization pattern\n(`can_access_dataset` / `check_dataset_access_or_anonymous`), filtering at read\ntime and authorizing cross-dataset references at link/write time.\n\n### Workarounds\n\nThere is **no complete configuration workaround**; the anonymous findings\nrequire only network access to the API. Operators who cannot upgrade\nimmediately should restrict network exposure of the API and avoid co-locating\nprivate datasets with public maps/relationships, but **upgrading to 1.2.3 is\nthe only full remediation**.\n\n### Remediation\n\nUpgrade to GeoLens **1.2.3**:\n- Container images: `ghcr.io/geolens-io/geolens-api:1.2.3` (+ worker/frontend)\n- Python SDK: `geolens==1.2.3` · CLI: `geolens-cli==1.2.3` · npm: `@geolens/sdk@1.2.3`",
  "severity" : [ {
    "type" : "CVSS_V3",
    "score" : "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N"
  } ],
  "affected" : [ {
    "package" : {
      "ecosystem" : "npm",
      "name" : "@geolens/sdk"
    },
    "ranges" : [ {
      "type" : "ECOSYSTEM",
      "events" : [ {
        "introduced" : "0"
      }, {
        "fixed" : "1.2.3"
      } ]
    } ]
  }, {
    "package" : {
      "ecosystem" : "PyPI",
      "name" : "geolens-cli"
    },
    "ranges" : [ {
      "type" : "ECOSYSTEM",
      "events" : [ {
        "introduced" : "0"
      }, {
        "fixed" : "1.2.3"
      } ]
    } ]
  }, {
    "package" : {
      "ecosystem" : "PyPI",
      "name" : "geolens"
    },
    "ranges" : [ {
      "type" : "ECOSYSTEM",
      "events" : [ {
        "introduced" : "0"
      }, {
        "fixed" : "1.2.3"
      } ]
    } ]
  } ],
  "references" : [ {
    "type" : "WEB",
    "url" : "https://github.com/geolens-io/geolens/security/advisories/GHSA-p23g-mvhj-jh3j"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/geolens-io/geolens/pull/234"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/geolens-io/geolens/pull/235"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/geolens-io/geolens/pull/236"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/geolens-io/geolens/pull/237"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/geolens-io/geolens/pull/238"
  }, {
    "type" : "PACKAGE",
    "url" : "https://github.com/geolens-io/geolens"
  } ],
  "database_specific" : {
    "cwe_ids" : [ "CWE-200", "CWE-639", "CWE-862" ],
    "severity" : "HIGH",
    "github_reviewed" : true,
    "github_reviewed_at" : "2026-08-18T18:00:07Z",
    "nvd_published_at" : null
  }
}