@shnitzel/plugscout 0.3.26 → 0.3.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/security/live-check.js +39 -17
- package/package.json +1 -1
|
@@ -107,6 +107,9 @@ async function checkNpmRegistry(pkg) {
|
|
|
107
107
|
}
|
|
108
108
|
async function checkVscodeMarketplace(vsixId) {
|
|
109
109
|
const checkedAt = new Date().toISOString();
|
|
110
|
+
const error = (status, text) => ({
|
|
111
|
+
result: { source: 'vscode-marketplace', label: 'VS Code Marketplace', status, findings: text ? [{ severity: 'info', text }] : [], checkedAt },
|
|
112
|
+
});
|
|
110
113
|
try {
|
|
111
114
|
const res = await fetchWithTimeout('https://marketplace.visualstudio.com/_apis/public/gallery/extensionquery', {
|
|
112
115
|
method: 'POST',
|
|
@@ -117,21 +120,28 @@ async function checkVscodeMarketplace(vsixId) {
|
|
|
117
120
|
},
|
|
118
121
|
body: JSON.stringify({
|
|
119
122
|
filters: [{ criteria: [{ filterType: 7, value: vsixId }] }],
|
|
120
|
-
|
|
123
|
+
// statistics (0x200) + assetUri (0x100) + excludeNonValidated (0x20) + versionProperties (0x10)
|
|
124
|
+
flags: 0x200 | 0x100 | 0x20 | 0x10,
|
|
121
125
|
}),
|
|
122
126
|
}, 8000);
|
|
123
|
-
if (!res.ok)
|
|
124
|
-
return
|
|
125
|
-
}
|
|
127
|
+
if (!res.ok)
|
|
128
|
+
return error('error');
|
|
126
129
|
const data = await res.json();
|
|
127
130
|
const ext = data.results?.[0]?.extensions?.[0];
|
|
128
131
|
if (!ext) {
|
|
129
132
|
return {
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
+
result: {
|
|
134
|
+
source: 'vscode-marketplace', label: 'VS Code Marketplace', status: 'unavailable',
|
|
135
|
+
findings: [{ severity: 'warn', text: 'Extension not found in marketplace — may have been removed' }],
|
|
136
|
+
checkedAt,
|
|
137
|
+
},
|
|
133
138
|
};
|
|
134
139
|
}
|
|
140
|
+
// Extract GitHub repository URL from version properties
|
|
141
|
+
const props = ext.versions?.[0]?.properties ?? [];
|
|
142
|
+
const repoProp = props.find(p => p.key === 'Microsoft.VisualStudio.Services.Links.Source' ||
|
|
143
|
+
p.key === 'Microsoft.VisualStudio.Services.Links.GitHub');
|
|
144
|
+
const repositoryUrl = repoProp?.value?.includes('github.com') ? repoProp.value : undefined;
|
|
135
145
|
const findings = [];
|
|
136
146
|
const verified = ext.publisher.isDomainVerified ?? false;
|
|
137
147
|
const latest = ext.versions?.[0];
|
|
@@ -147,13 +157,16 @@ async function checkVscodeMarketplace(vsixId) {
|
|
|
147
157
|
findings.push({ severity: 'info', text: `${installs.toLocaleString()} installs` });
|
|
148
158
|
}
|
|
149
159
|
return {
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
160
|
+
result: {
|
|
161
|
+
source: 'vscode-marketplace', label: 'VS Code Marketplace',
|
|
162
|
+
status: verified ? 'clean' : 'flagged',
|
|
163
|
+
findings, checkedAt,
|
|
164
|
+
},
|
|
165
|
+
repositoryUrl,
|
|
153
166
|
};
|
|
154
167
|
}
|
|
155
168
|
catch {
|
|
156
|
-
return
|
|
169
|
+
return error('error', 'Check timed out');
|
|
157
170
|
}
|
|
158
171
|
}
|
|
159
172
|
function extractGithubOwnerRepo(url) {
|
|
@@ -258,15 +271,24 @@ export async function runLiveChecks(item, opts = {}) {
|
|
|
258
271
|
checks.push(checkOsv(npmPkg));
|
|
259
272
|
checks.push(checkNpmRegistry(npmPkg));
|
|
260
273
|
}
|
|
274
|
+
// cursor-extension: marketplace first (to extract repo URL), then github check if found
|
|
275
|
+
const cursorMarketplaceResults = [];
|
|
261
276
|
if (item.kind === 'cursor-extension') {
|
|
262
277
|
const vsixId = typeof meta.vsixId === 'string' ? meta.vsixId : null;
|
|
263
278
|
if (vsixId) {
|
|
264
|
-
|
|
279
|
+
const mkt = await checkVscodeMarketplace(vsixId);
|
|
280
|
+
cursorMarketplaceResults.push(mkt.result);
|
|
281
|
+
const ghOwnerRepo = mkt.repositoryUrl ? extractGithubOwnerRepo(mkt.repositoryUrl) : findGithubOwnerRepo(item, meta);
|
|
282
|
+
if (ghOwnerRepo) {
|
|
283
|
+
checks.push(checkGithubRepo(ghOwnerRepo));
|
|
284
|
+
}
|
|
265
285
|
}
|
|
266
286
|
}
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
287
|
+
else {
|
|
288
|
+
const ghOwnerRepo = findGithubOwnerRepo(item, meta);
|
|
289
|
+
if (ghOwnerRepo) {
|
|
290
|
+
checks.push(checkGithubRepo(ghOwnerRepo));
|
|
291
|
+
}
|
|
270
292
|
}
|
|
271
293
|
if (item.kind === 'claude-plugin' || item.kind === 'claude-connector') {
|
|
272
294
|
const installUrl = item.install.url;
|
|
@@ -274,9 +296,9 @@ export async function runLiveChecks(item, opts = {}) {
|
|
|
274
296
|
checks.push(checkUrlHealth(installUrl));
|
|
275
297
|
}
|
|
276
298
|
}
|
|
277
|
-
|
|
299
|
+
const results = [...cursorMarketplaceResults, ...(checks.length > 0 ? await Promise.all(checks) : [])];
|
|
300
|
+
if (results.length === 0)
|
|
278
301
|
return [];
|
|
279
|
-
const results = await Promise.all(checks);
|
|
280
302
|
await writeCache(item.id, results);
|
|
281
303
|
return results;
|
|
282
304
|
}
|
package/package.json
CHANGED