UNPKG

vulnmatter-extension

Version:

VS Code extension for CVE vulnerability analysis using the VulnMatter API with X-API-Key. See CHANGELOG.md for release notes.

390 lines (359 loc) 14.1 kB
/******/ (() => { // webpackBootstrap /******/ "use strict"; /******/ var __webpack_modules__ = ([ /* 0 */ /***/ (function(__unused_webpack_module, exports, __webpack_require__) { var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", ({ value: true })); exports.activate = activate; exports.getStoredApiKey = getStoredApiKey; exports.deactivate = deactivate; // The module 'vscode' contains the VS Code extensibility API // Import the module and reference it with the alias vscode in your code below const vscode = __importStar(__webpack_require__(1)); // This method is called when your extension is activated // Your extension is activated the very first time the command is executed function activate(context) { // Use the console to output diagnostic information (console.log) and errors (console.error) // This line of code will only be executed once when your extension is activated console.log('Congratulations, your extension "vulnmatter-cli" is now active!'); // The command has been defined in the package.json file // Now provide the implementation of the command with registerCommand // The commandId parameter must match the command field in package.json const disposable = vscode.commands.registerCommand('vulnmatter-cli.helloWorld', () => { // The code you place here will be executed every time your command is executed // Display a message box to the user vscode.window.showInformationMessage('Hello World from Mi Primera Extension!'); }); // Command to configure API Key const configureApiKeyDisposable = vscode.commands.registerCommand('vulnmatter-cli.configureApiKey', () => { createApiKeyConfigPanel(context); }); // Command to test MCP connection (example usage of stored API key) const testMcpConnectionDisposable = vscode.commands.registerCommand('vulnmatter-cli.testMcpConnection', async () => { const apiKey = await getStoredApiKey(context); if (apiKey) { vscode.window.showInformationMessage(`MCP Connection Test: API Key found (${apiKey.substring(0, 8)}...)`); // Here you would implement the actual MCP connection logic console.log('API Key available for MCP connection:', apiKey.substring(0, 8) + '...'); } else { const result = await vscode.window.showWarningMessage('No API Key configured. Would you like to configure it now?', 'Configure API Key'); if (result === 'Configure API Key') { vscode.commands.executeCommand('vulnmatter-cli.configureApiKey'); } } }); context.subscriptions.push(disposable); context.subscriptions.push(configureApiKeyDisposable); context.subscriptions.push(testMcpConnectionDisposable); } function createApiKeyConfigPanel(context) { // Create and show a new webview panel const panel = vscode.window.createWebviewPanel('apiKeyConfig', // Identifies the type of the webview 'Configure X-API-Key', // Title of the panel displayed to the user vscode.ViewColumn.One, // Editor column to show the new webview panel in { // Enable scripts in the webview enableScripts: true, // Restrict the webview to only load content from our extension's directory localResourceRoots: [context.extensionUri] }); // Set the HTML content for the webview with strict CSP and nonce panel.webview.html = getWebviewContent(panel.webview); // Handle messages from the webview panel.webview.onDidReceiveMessage(async (message) => { switch (message.command) { case 'saveApiKey': if (message.apiKey && message.apiKey.trim()) { // Store the API key securely await context.secrets.store('vulnmatter.x-api-key', message.apiKey.trim()); vscode.window.showInformationMessage('X-API-Key saved successfully!'); panel.dispose(); } else { vscode.window.showErrorMessage('Please enter a valid API key'); } break; case 'loadApiKey': // Load existing API key (if any) and send it to the webview const existingKey = await context.secrets.get('vulnmatter.x-api-key'); panel.webview.postMessage({ command: 'displayApiKey', apiKey: existingKey || '' }); break; case 'clearApiKey': await context.secrets.delete('vulnmatter.x-api-key'); vscode.window.showInformationMessage('X-API-Key cleared successfully!'); panel.webview.postMessage({ command: 'displayApiKey', apiKey: '' }); break; case 'ready': // Send existing API key to webview when it's ready const readyKey = await context.secrets.get('vulnmatter.x-api-key'); panel.webview.postMessage({ command: 'displayApiKey', apiKey: readyKey || '' }); break; } }, undefined, context.subscriptions); } function getWebviewContent(webview) { const nonce = getNonce(); const cspSource = webview.cspSource; return ` <!DOCTYPE html> <html lang="es"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="Content-Security-Policy" content="default-src 'none'; img-src ${cspSource} https:; style-src ${cspSource} 'unsafe-inline'; script-src 'nonce-${nonce}';"> <title>Configure X-API-Key</title> <style> body { font-family: var(--vscode-font-family); color: var(--vscode-foreground); background-color: var(--vscode-editor-background); padding: 20px; max-width: 600px; } h1 { color: var(--vscode-titleBar-activeForeground); margin-bottom: 20px; } .form-group { margin-bottom: 20px; } label { display: block; margin-bottom: 8px; font-weight: bold; } input[type="password"], input[type="text"] { width: 100%; padding: 8px 12px; border: 1px solid var(--vscode-input-border); background-color: var(--vscode-input-background); color: var(--vscode-input-foreground); border-radius: 3px; font-size: 14px; box-sizing: border-box; } input[type="password"]:focus, input[type="text"]:focus { outline: none; border-color: var(--vscode-focusBorder); } .button-group { display: flex; gap: 10px; margin-top: 20px; } button { padding: 8px 16px; border: none; border-radius: 3px; cursor: pointer; font-size: 14px; background-color: var(--vscode-button-background); color: var(--vscode-button-foreground); } button:hover { background-color: var(--vscode-button-hoverBackground); } .secondary-button { background-color: var(--vscode-button-secondaryBackground) !important; color: var(--vscode-button-secondaryForeground) !important; } .secondary-button:hover { background-color: var(--vscode-button-secondaryHoverBackground) !important; } .danger-button { background-color: var(--vscode-inputValidation-errorBackground) !important; color: var(--vscode-inputValidation-errorForeground) !important; } .info { background-color: var(--vscode-editorWidget-background); border: 1px solid var(--vscode-editorWidget-border); padding: 15px; margin: 20px 0; border-radius: 3px; font-size: 13px; } .toggle-container { display: flex; align-items: center; gap: 10px; margin-top: 10px; } .toggle-container input[type="checkbox"] { width: auto; } </style> </head> <body> <h1>🔐 Configure X-API-Key</h1> <div class="info"> <strong>ℹ️ Información:</strong><br> Esta clave API se almacenará de forma segura en tu sistema y será utilizada para conectar con servicios MCP (Model Context Protocol). </div> <div class="form-group"> <label for="apiKeyInput">X-API-Key:</label> <input type="password" id="apiKeyInput" placeholder="Ingresa tu clave API..." /> <div class="toggle-container"> <input type="checkbox" id="showPassword" /> <label for="showPassword">Mostrar clave</label> </div> </div> <div class="button-group"> <button id="saveButton">💾 Guardar Clave</button> <button id="testButton" class="secondary-button">🧪 Probar Conexión</button> <button id="clearButton" class="danger-button">🗑️ Limpiar</button> </div> <script nonce="${nonce}"> const vscode = acquireVsCodeApi(); const apiKeyInput = document.getElementById('apiKeyInput'); const showPasswordCheckbox = document.getElementById('showPassword'); const saveButton = document.getElementById('saveButton'); const testButton = document.getElementById('testButton'); const clearButton = document.getElementById('clearButton'); // Toggle password visibility showPasswordCheckbox.addEventListener('change', function() { apiKeyInput.type = this.checked ? 'text' : 'password'; }); // Save API key saveButton.addEventListener('click', () => { const apiKey = apiKeyInput.value; if (apiKey.trim()) { vscode.postMessage({ command: 'saveApiKey', apiKey }); } else { alert('Por favor, ingresa una clave API válida.'); } }); // Test connection (placeholder for future implementation) testButton.addEventListener('click', () => { const apiKey = apiKeyInput.value.trim(); if (apiKey) { alert('Funcionalidad de prueba: Próximamente se implementará la verificación de conectividad MCP.'); } else { alert('Por favor, ingresa una clave API para probar.'); } }); // Clear API key clearButton.addEventListener('click', () => { if (confirm('¿Estás seguro de que deseas eliminar la clave API almacenada?')) { vscode.postMessage({ command: 'clearApiKey' }); } }); // Listen for messages from the extension window.addEventListener('message', event => { const message = event.data; if (message?.command === 'displayApiKey') { apiKeyInput.value = message.apiKey || ''; } }); // Notify extension that webview is ready vscode.postMessage({ command: 'ready' }); // Allow Enter key to save apiKeyInput.addEventListener('keypress', function(event) { if (event.key === 'Enter') { saveButton.click(); } }); </script> </body> </html> `; } // Helper function to get stored API key (for use in other parts of the extension) async function getStoredApiKey(context) { return await context.secrets.get('vulnmatter.x-api-key'); } // This method is called when your extension is deactivated function deactivate() { } // Generate a nonce for Content Security Policy function getNonce() { let text = ''; const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; for (let i = 0; i < 32; i++) { text += possible.charAt(Math.floor(Math.random() * possible.length)); } return text; } /***/ }), /* 1 */ /***/ ((module) => { module.exports = require("vscode"); /***/ }) /******/ ]); /************************************************************************/ /******/ // The module cache /******/ var __webpack_module_cache__ = {}; /******/ /******/ // The require function /******/ function __webpack_require__(moduleId) { /******/ // Check if module is in cache /******/ var cachedModule = __webpack_module_cache__[moduleId]; /******/ if (cachedModule !== undefined) { /******/ return cachedModule.exports; /******/ } /******/ // Create a new module (and put it into the cache) /******/ var module = __webpack_module_cache__[moduleId] = { /******/ // no module.id needed /******/ // no module.loaded needed /******/ exports: {} /******/ }; /******/ /******/ // Execute the module function /******/ __webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__); /******/ /******/ // Return the exports of the module /******/ return module.exports; /******/ } /******/ /************************************************************************/ /******/ /******/ // startup /******/ // Load entry module and return exports /******/ // This entry module is referenced by other modules so it can't be inlined /******/ var __webpack_exports__ = __webpack_require__(0); /******/ module.exports = __webpack_exports__; /******/ /******/ })() ; //# sourceMappingURL=extension.js.map