API Reference

Most organizations that want to use ExtensionTotal, do it through their MDM. Their end goal is getting an assessment of all extensions installed on their endpoints. The way to do this is run a script through the MDM that lists all VSCode extensions, and runs each extension against ExtensionTotal's API and return a JSON response.

Example - Bash

Lets see an example for MacOS endpoints and break it down -

#!/bin/bash

loggedInUser=$(stat -f "%Su" /dev/console)
codePath="/Applications/Visual Studio Code.app/Contents/Resources/app/bin/code"
cd /Users/"$loggedInUser"
codeExtensions=$(sudo -u "$loggedInUser" "$codePath" --list-extensions)

jsonResult="{\"extensions\":["

while IFS= read -r line || [[ -n $line ]]; do
    content=$(curl -s --location 'https://app.extensiontotal.com/api/getExtensionRisk' \
    --header 'Content-Type: application/json' \
    --header 'Cookie: SameSite=None' \
    --header 'x-api-key: <YOUR_API_KEY>' \
    --data "{
      \"q\": \"$line\"
    }")
    jsonResult+="$content,"
    done < <(printf '%s' "$codeExtensions")

jsonResult=${jsonResult%,}
jsonResult+="]}"
echo "$jsonResult"

Firstly we get the endpoint user by querying the system's user state using scutil and then extracting the username using awk.

loggedInUser=$(echo "show State:/Users/ConsoleUser" | scutil | awk '/Name :/ { print $3 }')

After that we find the installed VSCode instance, in this case we are looking at MacOS endpoints, but it can easily be swapped to support any other UNIX based endpoint. Note that if VSCode is in the $PATH we can skip this and just directly list all extensions.

codePath="/Applications/Visual Studio Code.app/Contents/Resources/app/bin/code"

Lets now list all extensions

codeExtensions=$(sudo -u "$loggedInUser" "$codePath" --list-extensions)

Lastly we simply iterate on each extension in the list, and run a curl request to ExtensionTotal's API to assess the risk of the extension. Note that another way to do this is firstly collect all extensions in your organization then run them through ExtensionTotal's API to avoid duplicates. It is a bit more complicated to do so, instead we recommend to just get the Business API key or reach out for the Enterprise plan here.

Results output example:

{
  "extensions": [
    {
      "display_name": "gitignore",
      "name": "gitignore",
      "publisher_name": "codezombiech",
      "extension_id": "codezombiech.gitignore",
      "tags": [
        "gitignore",
        "multi-root ready"
      ],
      "riskLabel": "Med",
      "findings": [
        {
          "timestamp": "2024-08-04T01:10:12.569Z",
          "name": "Publisher Has Only One Extension",
          "description": "Flags publishers that publish only one extension on the marketplace, suggesting concerns about the publisher's reliability.",
          "risk": 1
        },
        {
          "timestamp": "2024-08-04T01:35:10.948Z",
          "name": "Unmaintained Extension",
          "description": "Flags extensions that are not maintained on the marketplace, suggesting concerns about the extension's reputation and the publisher's reliability.",
          "risk": 3
        },
        {
          "timestamp": "2024-08-04T01:40:11.441Z",
          "name": "Unverified Publisher",
          "description": "Publisher didn't verify their listed domain ownership. Publisher verification is a good practice to ensure the publisher is who they say they are. Yet, VS Code publisher verification process is not rigorous enough.",
          "risk": 4
        }
      ],
      "risk": 4.4728,
      "version": "0.9.0",
      "updated_at": "2024-08-04T02:10:14.336Z"
    },
    {
      "display_name": "Git History",
      "name": "githistory",
      "publisher_name": "donjayamanne",
      "extension_id": "donjayamanne.githistory",
      "tags": [
        "git",
        "keybindings"
      ],
      "riskLabel": "Med",
      "findings": [
        {
          "timestamp": "2024-08-04T01:35:10.948Z",
          "name": "Unmaintained Extension",
          "description": "Flags extensions that are not maintained on the marketplace, suggesting concerns about the extension's reputation and the publisher's reliability.",
          "risk": 3
        },
        {
          "timestamp": "2024-08-04T01:40:11.441Z",
          "name": "Unverified Publisher",
          "description": "Publisher didn't verify their listed domain ownership. Publisher verification is a good practice to ensure the publisher is who they say they are. Yet, VS Code publisher verification process is not rigorous enough.",
          "risk": 4
        }
      ],
      "risk": 4.36,
      "version": "0.6.20",
      "updated_at": "2024-08-04T02:10:14.336Z"
    },
    {
      "display_name": "GitLens — Git supercharged",
      "name": "gitlens",
      "publisher_name": "eamodio",
      "extension_id": "eamodio.gitlens",
      "tags": [
        "__web_extension",
        "annotation",
        "blame",
        "git",
        "gitlens",
        "keybindings",
        "log",
        "multi-root ready"
      ],
      "riskLabel": "Low",
      "findings": [],
      "risk": 0.2,
      "version": "2024.8.213",
      "updated_at": "2024-08-04T02:10:14.336Z"
    },
  ]
}

Example - PowerShell

For Windows users, here is a PowerShell example can be used with any MDM,SCCM etc.. The script run in the user context otherwise it won't work.

$codeExtensions = $(code --list-extensions)

Write-Output += "Found $($codeExtensions.Count) extensions to check..."
$extArray = @()

foreach ($extension in $codeExtensions) {

    $headers = @{ 
        "Content-Type" = "application/json"
        "Cookie"       = "SameSite=None"
        "X-API-Key"       = "API_KEY_HERE"
    }
    
    $payload = @{
        "q" = $extension
    }

    $response = Invoke-WebRequest -Uri 'https://app.extensiontotal.com/api/getExtensionRisk' `
                                    -Method Post `
                                    -Body $( $payload | ConvertTo-Json) `
                                    -Headers $headers
    
    $responseContent = $response.Content | ConvertFrom-Json
    $extArray += $responseContent

    Start-Sleep -Seconds 10
}

$extArray | Sort-Object -Property risk -Descending | Format-Table -Property display_name, version, risk, updated_at