From 55b5b9593b607b27981b7e8cc419f1422b1dfac3 Mon Sep 17 00:00:00 2001 From: Bill Li Date: Wed, 10 Dec 2025 00:56:27 +0000 Subject: [PATCH] fix(settings): prevent overwrites --- package-lock.json | 84 ++++++++++++------------ src/auth.ts | 47 +++++++++++-- src/ui/purl-alerts-and-scores/manager.ts | 4 +- 3 files changed, 84 insertions(+), 51 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0ff6a8c..749f175 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "vscode-socket-security", - "version": "2.0.1", + "version": "2.0.3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "vscode-socket-security", - "version": "2.0.1", + "version": "2.0.3", "license": "MIT", "dependencies": { "@babel/parser": "^7.20.7", @@ -1300,9 +1300,9 @@ } }, "node_modules/@npmcli/map-workspaces/node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", "license": "ISC", "dependencies": { "foreground-child": "^3.1.0", @@ -1396,9 +1396,9 @@ } }, "node_modules/@npmcli/package-json/node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", "license": "ISC", "dependencies": { "foreground-child": "^3.1.0", @@ -2207,9 +2207,9 @@ "license": "MIT" }, "node_modules/@textlint/linter-formatter/node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", + "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", "license": "MIT", "dependencies": { "argparse": "^1.0.7", @@ -2857,14 +2857,14 @@ ] }, "node_modules/@vscode/vsce/node_modules/glob": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.3.tgz", - "integrity": "sha512-2Nim7dha1KVkaiF4q6Dj+ngPPMdfvLJEOpZk/jKiUAkqKebpGAWQXAq9z1xu9HKu5lWfqw/FASuccEjyznjPaA==", - "license": "ISC", + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-11.1.0.tgz", + "integrity": "sha512-vuNwKSaKiqm7g0THUBu2x7ckSs3XJLXE+2ssL7/MfTGPLLcrJQ/4Uq1CjPTtO5cCIiRxqvN6Twy1qOwhL0Xjcw==", + "license": "BlueOak-1.0.0", "dependencies": { "foreground-child": "^3.3.1", "jackspeak": "^4.1.1", - "minimatch": "^10.0.3", + "minimatch": "^10.1.1", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^2.0.0" @@ -2880,10 +2880,10 @@ } }, "node_modules/@vscode/vsce/node_modules/glob/node_modules/minimatch": { - "version": "10.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.3.tgz", - "integrity": "sha512-IPZ167aShDZZUMdRk66cyQAW3qr0WzbHkPdMYa8bzZhlHhO3jALbKdxcaak7W9FfT2rZNpQuUu4Od7ILEpXSaw==", - "license": "ISC", + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.1.1.tgz", + "integrity": "sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==", + "license": "BlueOak-1.0.0", "dependencies": { "@isaacs/brace-expansion": "^5.0.0" }, @@ -3056,9 +3056,9 @@ } }, "node_modules/@yarnpkg/parsers/node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", + "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", "license": "MIT", "peer": true, "dependencies": { @@ -3481,9 +3481,9 @@ } }, "node_modules/cacache/node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", "license": "ISC", "dependencies": { "foreground-child": "^3.1.0", @@ -4812,9 +4812,9 @@ } }, "node_modules/form-data": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.3.tgz", - "integrity": "sha512-qsITQPfmvMOSAdeyZ+12I1c+CKSstAFAwu+97zrnWAbIr5u8wfsExUzCesVLC8NgHuRUqNN4Zy6UPWUTRGslcA==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", + "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", "license": "MIT", "dependencies": { "asynckit": "^0.4.0", @@ -5505,9 +5505,9 @@ "license": "MIT" }, "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", "license": "MIT", "dependencies": { "argparse": "^2.0.1" @@ -5669,12 +5669,12 @@ } }, "node_modules/jws": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", - "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.3.tgz", + "integrity": "sha512-byiJ0FLRdLdSVSReO/U4E7RoEyOCKnEnEPMjq3HxWtvzLsV08/i5RQKsFVNkCldrCaPr2vDNAOMsfs8T/Hze7g==", "license": "MIT", "dependencies": { - "jwa": "^1.4.1", + "jwa": "^1.4.2", "safe-buffer": "^5.0.1" } }, @@ -7962,9 +7962,9 @@ } }, "node_modules/tar-fs": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.3.tgz", - "integrity": "sha512-090nwYJDmlhwFwEW3QQl+vaNnxsO2yVsd45eTKRBzSzu+hlb1w2K9inVq5b0ngXuLVqQ4ApvsUHHnu/zQNkWAg==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.4.tgz", + "integrity": "sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==", "license": "MIT", "optional": true, "dependencies": { @@ -8160,9 +8160,9 @@ "peer": true }, "node_modules/tmp": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz", - "integrity": "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==", + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.5.tgz", + "integrity": "sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==", "license": "MIT", "engines": { "node": ">=14.14" diff --git a/src/auth.ts b/src/auth.ts index c6d2cf3..4f864fd 100644 --- a/src/auth.ts +++ b/src/auth.ts @@ -7,7 +7,6 @@ import https from 'node:https' import { once } from 'node:events' import { IncomingMessage } from 'node:http' import { text } from 'node:stream/consumers' -import fs from 'fs' import { randomUUID } from 'node:crypto' const { SOCKET_PUBLIC_API_TOKEN } = constants export type APIConfig = { @@ -25,6 +24,11 @@ type OrganizationsRecord = { organizations: Record } +type SettingsFile = { + apiKey?: string + [key: string]: unknown +} + async function getOrganizations(apiKey: string): Promise { const authHeader = getAuthHeader(apiKey) const orgReq = https.get('https://api.socket.dev/v0/organizations', { @@ -84,6 +88,19 @@ export async function activate(context: vscode.ExtensionContext, disposables: Ar watcher.onDidCreate(() => syncLiveSessionFromDisk()), watcher.onDidDelete(() => { syncLiveSessionFromDisk() }) ) + async function readExistingSettings(): Promise { + try { + const existingContent = await vscode.workspace.fs.readFile(vscode.Uri.file(settingsPath)) + const decoded = Buffer.from(new TextDecoder().decode(existingContent), 'base64').toString('utf8') + const parsed = JSON.parse(decoded) + if (parsed && typeof parsed === 'object' && parsed !== null) { + return parsed + } + } catch { + // File doesn't exist or is invalid + } + return {} + } async function syncLiveSessionFromDisk() { let settings_on_disk: {apiKey?: string | null} = { apiKey: null @@ -139,11 +156,14 @@ export async function activate(context: vscode.ExtensionContext, disposables: Ar if (!session || !session.accessToken || session.accessToken === SOCKET_PUBLIC_API_TOKEN) { return } - const contents = Buffer.from( - JSON.stringify({ - apiKey: session.accessToken - }) - ).toString('base64') + + // Read existing settings to preserve other fields (merge approach) + const existingSettings = await readExistingSettings() + + // Merge new apiKey into existing settings + existingSettings.apiKey = session.accessToken + + const contents = Buffer.from(JSON.stringify(existingSettings)).toString('base64') return vscode.workspace.fs.writeFile(vscode.Uri.file(settingsPath), new TextEncoder().encode(contents)) } //#endregion @@ -192,7 +212,20 @@ export async function activate(context: vscode.ExtensionContext, disposables: Ar pleaseLoginStatusBar.show() } catch {} try { - fs.unlinkSync(settingsPath) + // Read existing settings to preserve other fields + const existingSettings = await readExistingSettings() + + // Remove only the apiKey field, preserving other settings + delete existingSettings.apiKey + + // If there are other settings remaining, write them back; otherwise delete the file + if (Object.keys(existingSettings).length > 0) { + const contents = Buffer.from(JSON.stringify(existingSettings)).toString('base64') + await vscode.workspace.fs.writeFile(vscode.Uri.file(settingsPath), new TextEncoder().encode(contents)) + } else { + // No other settings, safe to delete the entire file + await vscode.workspace.fs.delete(vscode.Uri.file(settingsPath)) + } } catch {} if (session) { diskSessionsChanges.fire({ diff --git a/src/ui/purl-alerts-and-scores/manager.ts b/src/ui/purl-alerts-and-scores/manager.ts index 1cc34b5..d023a7a 100644 --- a/src/ui/purl-alerts-and-scores/manager.ts +++ b/src/ui/purl-alerts-and-scores/manager.ts @@ -160,7 +160,7 @@ export class PURLDataCache { bailPendingCacheEntries() return } - const req = https.request(`https://api.socket.dev/v0/purl?alerts=true&compact=false'`, { + const req = https.request('https://api.socket.dev/v0/purl?alerts=true&compact=false', { method: 'POST', headers: { 'content-type': 'application/json', @@ -181,7 +181,7 @@ export class PURLDataCache { purl: str })) }) - req.end(body ) + req.end(body) const [res] = (await once(req, 'response')) as unknown as [IncomingMessage] function cleanupRes() { try {