Security
Headlines
HeadlinesLatestCVEs

Headline

CVE-2021-34083: google-it/googleIt.js at v1.6.2 · PatNeedham/google-it

Google-it is a Node.js package which allows its users to send search queries to Google and receive the results in a JSON format. When using the ‘Open in browser’ option in versions up to 1.6.2, google-it will unsafely concat the result’s link retrieved from google to a shell command, potentially exposing the server to RCE.

CVE
#web#google#nodejs#js#git#rce

/* eslint-disable no-console */ /* eslint-disable array-callback-return */ const request = require(‘request’); const fs = require(‘fs’); const querystring = require(‘querystring’); const cheerio = require(‘cheerio’); require(‘colors’); const { exec } = require(‘child_process’); const { getDefaultRequestOptions, getTitleSelector, getLinkSelector, getSnippetSelector, getResultStatsSelector, getResultCursorSelector, logIt, saveToFile, saveResponse, } = require(‘./utils’); export function errorTryingToOpen(error, stdout, stderr) { if (error) { console.log(`Error trying to open link in browser: ${error}`); console.log(`stdout: ${stdout}`); console.log(`stderr: ${stderr}`); } } export function openInBrowser(open, results) { if (open !== undefined) { // open is the first X number of links to open results.slice(0, open).forEach((result) => { exec(`open ${result.link}`, errorTryingToOpen); }); } } export function getSnippet(elem) { // recursive function to get “all” the returned data from Google function findData(child) { if (!child.data) { return child.children.map(© => c.data || findData©); } return child.data; } // Issue with linter wanting “new” before “Array” // in this case, the casting is legit, we don’t want a new array // eslint-disable-next-line unicorn/new-for-builtins return elem.children && elem.children.length > 0 ? elem.children.map((child) => Array(findData(child)).join(‘’)).join(‘’) : '’; } export function display(results, disableConsole, onlyUrls) { logIt('\n’, disableConsole); results.forEach((result) => { if (onlyUrls) { logIt(result.link.green, disableConsole); } else if (result.title) { logIt(result.title.blue, disableConsole); logIt(result.link.green, disableConsole); logIt(result.snippet, disableConsole); logIt('\n’, disableConsole); } else { logIt(‘Result title is undefined.’); } }); } export const parseGoogleSearchResultUrl = (url) => { if (!url) { return undefined; } if (url.charAt(0) === ‘/’) { return querystring.parse(url).url; } return url; }; export function getResults({ data, noDisplay, disableConsole, onlyUrls, titleSelector, linkSelector, snippetSelector, resultStatsSelector, cursorSelector, }) { const $ = cheerio.load(data); let results = []; const titles = $(getTitleSelector(titleSelector)).contents(); titles.each((index, elem) => { if (elem.data) { results.push({ title: elem.data }); } else { results.push({ title: elem.children[0].data }); } }); $(getLinkSelector(linkSelector)).map((index, elem) => { if (index < results.length) { results[index] = Object.assign(results[index], { link: parseGoogleSearchResultUrl(elem.attribs.href), }); } }); $(getSnippetSelector(snippetSelector)).map((index, elem) => { if (index < results.length) { results[index] = Object.assign(results[index], { snippet: getSnippet(elem), }); } }); if (onlyUrls) { results = results.map(® => ({ link: r.link })); } if (!noDisplay) { display(results, disableConsole, onlyUrls); } const resultStats = $(getResultStatsSelector(resultStatsSelector)).html() || ‘’; const approximateResults = ((resultStats.split(' results’) || [‘’])[0].split('About ')[1] || ‘’).replace(‘,’, ‘’); const seconds = parseFloat((resultStats.split(' (')[1] || ‘’).split(' seconds’)[0]); const cursor = $(getResultCursorSelector(cursorSelector)).html() || '’; const page = parseInt(cursor.split(‘</span>’)[1], 10); const stats = { page, approximateResults, seconds, }; return { results, stats }; } export function getResponse({ fromFile: filePath, fromString, options, htmlFileOutputPath, query, limit, userAgent, start, includeSites, excludeSites, }) { // eslint-disable-next-line consistent-return return new Promise((resolve, reject) => { if (filePath) { fs.readFile(filePath, (err, data) => { if (err) { return reject(new Error(`Erorr accessing file at ${filePath}: ${err}`)); } return resolve({ body: data }); }); } else if (fromString) { return resolve({ body: fromString }); } const defaultOptions = getDefaultRequestOptions({ limit, query, userAgent, start, includeSites, excludeSites, }); request({ …defaultOptions, …options }, (error, response, body) => { if (error) { return reject(new Error(`Error making web request: ${error}`)); } saveResponse(response, htmlFileOutputPath); return resolve({ body, response }); }); }); } function googleIt(config) { const { output, open, returnHtmlBody, titleSelector, linkSelector, snippetSelector, resultStatsSelector, cursorSelector, start, diagnostics, } = config; return new Promise((resolve, reject) => { getResponse(config).then(({ body, response }) => { const { results, stats } = getResults({ data: body, noDisplay: config[‘no-display’], disableConsole: config.disableConsole, onlyUrls: config[‘only-urls’], titleSelector, linkSelector, snippetSelector, resultStatsSelector, cursorSelector, start, }); const { statusCode } = response; if (results.length === 0 && statusCode !== 200 && !diagnostics) { reject(new Error(`Error in response: statusCode ${statusCode}. To see the raw response object, please include the ‘diagnostics: true’ as part of the options object (or -d if using command line)`)); } saveToFile(output, results); openInBrowser(open, results); if (returnHtmlBody || diagnostics) { return resolve({ results, body, response, stats, }); } return resolve(results); }).catch(reject); }); } export default googleIt;

Related news

GHSA-7xhv-mpjw-422f: Command injection in google-it

Google-it is a Node.js package which allows its users to send search queries to Google and receive the results in a JSON format. When using the 'Open in browser' option in versions up to 1.6.2, google-it will unsafely concat the result's link retrieved from google to a shell command, potentially exposing the server to RCE.

CVE: Latest News

CVE-2023-50976: Transactions API Authorization by oleiman · Pull Request #14969 · redpanda-data/redpanda
CVE-2023-6905
CVE-2023-6903
CVE-2023-6904
CVE-2023-3907