Skip to content

GitHub Security Lab (GHSL) Vulnerability Report, codeium-chrome: GHSL-2024-027

Moderate
fortenforge published GHSA-8c7j-2h97-q63p Mar 7, 2024

Package

codeium-chrome

Affected versions

v1.2.52

Patched versions

1.8.0+

Description

GitHub Security Lab (GHSL) Vulnerability Report, codeium-chrome: GHSL-2024-027

The GitHub Security Lab team has identified potential security vulnerabilities in codeium-chrome.

We are committed to working with you to help resolve these issues. In this report you will find everything you need to effectively coordinate a resolution of these issues with the GHSL team.

If at any point you have concerns or questions about this process, please do not hesitate to reach out to us at [email protected] (please include GHSL-2024-027 as a reference). See also this blog post written by GitHub's Advisory Curation team which explains what CVEs and advisories are, why they are important to track vulnerabilities and keep downstream users informed, the CVE assigning process, and how they are used to keep open source software secure.

If you are NOT the correct point of contact for this report, please let us know!

Summary

The service worker of the codeium-chrome extension doesn't check the sender when receiving an external message. This allows an attacker to host a website that will steal the user's Codeium api-key, and thus impersonate the user on the backend autocomplete server.

Project

codeium-chrome

Tested Version

v1.2.52

Details

Issue: Private information leakage in serviceWorker.ts (GHSL-2024-027)

The service worker of the codeium-chrome extension doesn't check the sender when receiving an external message. This allows any website to query the onMessageExternal listener and leak the user's name, api_key and other miscellaneous settings.

serviceWorker.ts

// The only external messages:
//  - website auth
//  - request for api key
//  - set icon and error message
chrome.runtime.onMessageExternal.addListener((message, sender, sendResponse) => {
  if (message.type === 'user') {
    (async () => {
      const user = await getStorageItem('user');
      sendResponse(user);
      if (user?.apiKey === undefined) {
        await loggedOut();
      }
    })().catch((e) => {
      console.error(e);
    });
    return true;
  }
  if (message.type === 'clientSettings') {
    (async () => {
      const storageItems = await getStorageItems(['user', 'enterpriseDefaultModel']);
      const clientSettings: ClientSettings = {
        apiKey: storageItems.user?.apiKey,
        defaultModel: storageItems.enterpriseDefaultModel,
      };
      sendResponse(clientSettings);
    })().catch((e) => {
      console.error(e);
    });
    return true;
  }
  if (message.type === 'allowlist') {
    (async () => {
      const allowlist = await getStorageItem('allowlist');
      sendResponse(allowlist);
    })().catch((e) => {
      console.error(e);
    });
    return true;
  }
  if (message.type == 'error') {
    unhealthy(message.message).catch((e) => {
      console.error(e);
    });
    // No response needed.
    return;
  }
  if (message.type == 'success') {
    loggedIn().catch((e) => {
      console.error(e);
    });
    // No response needed.
    return;
  }
  if (typeof message.token !== 'string' || typeof message.state !== 'string') {
    console.log('Unexpected message:', message);
    return;
  }
  (async () => {
    const typedMessage = message as { token: string; state: string };
    const user = await getStorageItem('user');
    if (user?.apiKey === undefined) {
      await login(typedMessage.token);
    }
  })().catch((e) => {
    console.error(e);
  });
});

manifest.json

 "externally_connectable": {
    "matches": ["<all_urls>"]
  }

Impact

This issue may lead to Information Disclosure. An attacker can use the API key for the Codeium autocomplete server that is meant for another user. They can use this api key to make queries to the backend autocomplete server as the other user.

Remediation

  1. Compare the sender of the message to the user-defined allowlist before returning private information. In order to do so, check the sender.origin or the sender.url first.
  2. Limit access to the chrome extension in the manifest file by changing <all_urls> to a regex of domains manually.

Proof of Concept

 chrome.runtime.sendMessage(receiverExtensionID, {type: "user"},function (response) {
        if (response) alert(response);
    });

Host an html page with the above javascript code, which will send a message to the codeium-chrome extension and show the api-key and username in an alert.

GitHub Security Advisories

We recommend you create a private GitHub Security Advisory for these findings. This also allows you to invite the GHSL team to collaborate and further discuss these findings in private before they are published.

Credit

These issues were discovered and reported by GHSL team member @Kwstubbs (Kevin Stubbings).

Contact

You can contact the GHSL team at [email protected], please include a reference to GHSL-2024-027 in any communication regarding these issues.

Disclosure Policy

This report is subject to a 90-day disclosure deadline, as described in more detail in our coordinated disclosure policy.

Severity

Moderate

CVSS overall score

This score calculates overall vulnerability severity from 0 to 10 and is based on the Common Vulnerability Scoring System (CVSS).
/ 10

CVSS v3 base metrics

Attack vector
Network
Attack complexity
Low
Privileges required
None
User interaction
Required
Scope
Unchanged
Confidentiality
None
Integrity
High
Availability
None

CVSS v3 base metrics

Attack vector: More severe the more the remote (logically and physically) an attacker can be in order to exploit the vulnerability.
Attack complexity: More severe for the least complex attacks.
Privileges required: More severe if no privileges are required.
User interaction: More severe when no user interaction is required.
Scope: More severe when a scope change occurs, e.g. one vulnerable component impacts resources in components beyond its security scope.
Confidentiality: More severe when loss of data confidentiality is highest, measuring the level of data access available to an unauthorized user.
Integrity: More severe when loss of data integrity is the highest, measuring the consequence of data modification possible by an unauthorized user.
Availability: More severe when the loss of impacted component availability is highest.
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:N

CVE ID

CVE-2024-28120

Weaknesses

Improper Access Control

The product does not restrict or incorrectly restricts access to a resource from an unauthorized actor. Learn more on MITRE.

Credits