imagemagick-nodejs
Advanced tools
| #!/usr/bin/env node | ||
| const https = require('https'); | ||
| const fs = require('fs'); | ||
| const path = require('path'); | ||
| const { execSync } = require('child_process'); | ||
| const tar = require('tar'); | ||
| function findPackageRoot(startDir) { | ||
| let current = startDir; | ||
| while (true) { | ||
| if (fs.existsSync(path.join(current, 'package.json'))) return current; | ||
| const parent = path.dirname(current); | ||
| if (parent === current) return current; | ||
| current = parent; | ||
| } | ||
| } | ||
| const PACKAGE_ROOT = findPackageRoot(__dirname); | ||
| const VENDOR_DIR = path.join(PACKAGE_ROOT, 'vendor'); | ||
| const BIN_DIR = path.join(VENDOR_DIR, 'bin'); | ||
| const GITHUB_REPO = 'iqbal-rashed/imagemagick-nodejs'; | ||
| const RELEASE_TAG = 'bin-main'; | ||
| const ALLOWED_DOMAINS = [ | ||
| 'github.com', | ||
| 'api.github.com', | ||
| 'objects.githubusercontent.com', | ||
| 'codeload.github.com', | ||
| 'raw.githubusercontent.com', | ||
| 'release-assets.githubusercontent.com', | ||
| ]; | ||
| function isMusl() { | ||
| if (process.platform !== 'linux') return false; | ||
| try { | ||
| if (execSync('ldd --version 2>&1 || true', { encoding: 'utf8' }).toLowerCase().includes('musl')) | ||
| return true; | ||
| if (fs.existsSync('/etc/alpine-release')) return true; | ||
| if (fs.readdirSync('/lib').filter((f) => f.startsWith('libc.musl')).length > 0) return true; | ||
| } catch {} | ||
| return false; | ||
| } | ||
| function getPlatformId() { | ||
| const platform = process.platform; | ||
| const arch = process.arch; | ||
| if (platform === 'win32') { | ||
| if (arch === 'x64') return 'windows-x64'; | ||
| if (arch === 'ia32') return 'windows-x86'; | ||
| throw new Error(`Unsupported Windows architecture: ${arch}`); | ||
| } | ||
| if (platform === 'darwin') { | ||
| if (arch === 'arm64') return 'macos-arm64'; | ||
| if (arch === 'x64') return 'macos-x64'; | ||
| throw new Error(`Unsupported macOS architecture: ${arch}`); | ||
| } | ||
| if (platform === 'linux') { | ||
| const libc = isMusl() ? 'musl' : 'glibc'; | ||
| if (arch === 'x64') return `linux-${libc}-amd64`; | ||
| if (arch === 'arm64') return `linux-${libc}-arm64`; | ||
| throw new Error(`Unsupported Linux architecture: ${arch}`); | ||
| } | ||
| throw new Error(`Unsupported platform: ${platform}`); | ||
| } | ||
| function validateUrl(url) { | ||
| try { | ||
| const hostname = new URL(url).hostname.toLowerCase(); | ||
| return ALLOWED_DOMAINS.some((d) => hostname === d || hostname.endsWith(`.${d}`)); | ||
| } catch { | ||
| return false; | ||
| } | ||
| } | ||
| function fetchJson(url) { | ||
| return new Promise((resolve, reject) => { | ||
| const parsed = new URL(url); | ||
| const headers = { | ||
| 'User-Agent': 'imagemagick-nodejs', | ||
| Accept: 'application/vnd.github.v3+json', | ||
| }; | ||
| if (process.env.GITHUB_TOKEN) headers.Authorization = `Bearer ${process.env.GITHUB_TOKEN}`; | ||
| https | ||
| .get({ hostname: parsed.hostname, path: parsed.pathname + parsed.search, headers }, (res) => { | ||
| if (res.statusCode === 302 || res.statusCode === 301) { | ||
| const location = res.headers.location; | ||
| if (!location) return reject(new Error('Redirect without location header')); | ||
| if (!validateUrl(location)) | ||
| return reject(new Error(`Redirect to disallowed domain: ${location}`)); | ||
| return fetchJson(location).then(resolve).catch(reject); | ||
| } | ||
| if (res.statusCode !== 200) | ||
| return reject(new Error(`Failed to fetch release: ${res.statusCode}`)); | ||
| let data = ''; | ||
| res.on('data', (chunk) => (data += chunk.toString())); | ||
| res.on('end', () => { | ||
| try { | ||
| resolve(JSON.parse(data)); | ||
| } catch (e) { | ||
| reject(new Error(`Failed to parse JSON: ${e}`)); | ||
| } | ||
| }); | ||
| }) | ||
| .on('error', reject); | ||
| }); | ||
| } | ||
| function downloadFile(url, destPath) { | ||
| return new Promise((resolve, reject) => { | ||
| const file = fs.createWriteStream(destPath); | ||
| const request = (downloadUrl) => { | ||
| const parsed = new URL(downloadUrl); | ||
| const headers = { 'User-Agent': 'imagemagick-nodejs' }; | ||
| if (process.env.GITHUB_TOKEN && parsed.hostname.includes('github')) { | ||
| headers.Authorization = `Bearer ${process.env.GITHUB_TOKEN}`; | ||
| } | ||
| https | ||
| .get( | ||
| { hostname: parsed.hostname, path: parsed.pathname + parsed.search, headers }, | ||
| (res) => { | ||
| if (res.statusCode === 302 || res.statusCode === 301) { | ||
| const location = res.headers.location; | ||
| if (!location) return reject(new Error('Redirect without location header')); | ||
| if (!validateUrl(location)) | ||
| return reject(new Error(`Redirect to disallowed domain: ${location}`)); | ||
| return request(location); | ||
| } | ||
| if (res.statusCode !== 200) | ||
| return reject(new Error(`Download failed: ${res.statusCode}`)); | ||
| const totalSize = parseInt(res.headers['content-length'] ?? '0', 10); | ||
| let downloadedSize = 0; | ||
| res.on('data', (chunk) => { | ||
| downloadedSize += chunk.length; | ||
| if (totalSize > 0) | ||
| process.stdout.write( | ||
| `\r Downloading: ${((downloadedSize / totalSize) * 100).toFixed(1)}%` | ||
| ); | ||
| }); | ||
| res.pipe(file); | ||
| file.on('finish', () => { | ||
| file.close(); | ||
| console.log(' Done!'); | ||
| resolve(); | ||
| }); | ||
| } | ||
| ) | ||
| .on('error', (err) => { | ||
| fs.unlink(destPath, () => {}); | ||
| reject(err); | ||
| }); | ||
| }; | ||
| request(url); | ||
| }); | ||
| } | ||
| async function extractTarGz(tarPath, destDir) { | ||
| await tar.extract({ file: tarPath, cwd: destDir, strip: 1 }); | ||
| console.log(` Extracted to ${destDir}`); | ||
| } | ||
| function makeExecutable(binaryPath) { | ||
| if (process.platform !== 'win32') { | ||
| try { | ||
| fs.chmodSync(binaryPath, 0o755); | ||
| } catch (err) { | ||
| console.warn(`Warning: Could not make binary executable: ${err}`); | ||
| } | ||
| } | ||
| } | ||
| async function install() { | ||
| console.log('[imagemagick-nodejs] Installing ImageMagick binary...'); | ||
| if (process.env.IMAGEMAGICK_SKIP_DOWNLOAD) { | ||
| console.log(' Skipping download (IMAGEMAGICK_SKIP_DOWNLOAD is set)'); | ||
| return; | ||
| } | ||
| const binaryName = process.platform === 'win32' ? 'magick.exe' : 'magick'; | ||
| const binaryPath = path.join(BIN_DIR, binaryName); | ||
| if (fs.existsSync(binaryPath)) { | ||
| console.log(' Binary already exists, skipping download'); | ||
| return; | ||
| } | ||
| try { | ||
| const platformId = getPlatformId(); | ||
| console.log(` Platform: ${platformId}`); | ||
| console.log(' Fetching release info...'); | ||
| const release = await fetchJson( | ||
| `https://api.github.com/repos/${GITHUB_REPO}/releases/tags/${RELEASE_TAG}` | ||
| ); | ||
| const assetPattern = new RegExp(`imagemagick-.*-${platformId}\\.tar\\.gz$`); | ||
| const asset = release.assets.find((a) => assetPattern.test(a.name)); | ||
| if (!asset) { | ||
| console.error(` ERROR: No binary available for ${platformId}`); | ||
| console.error(' Available assets:', release.assets.map((a) => a.name).join(', ')); | ||
| console.error(' You may need to install ImageMagick manually.'); | ||
| process.exit(0); | ||
| } | ||
| console.log(` Found asset: ${asset.name}`); | ||
| fs.mkdirSync(BIN_DIR, { recursive: true }); | ||
| const tarPath = path.join(VENDOR_DIR, asset.name); | ||
| await downloadFile(asset.browser_download_url, tarPath); | ||
| console.log(' Extracting...'); | ||
| await extractTarGz(tarPath, VENDOR_DIR); | ||
| fs.unlinkSync(tarPath); | ||
| makeExecutable(binaryPath); | ||
| if (fs.existsSync(binaryPath)) { | ||
| console.log(` ✓ ImageMagick installed to ${BIN_DIR}`); | ||
| } else { | ||
| throw new Error('Binary not found after extraction'); | ||
| } | ||
| } catch (err) { | ||
| console.error(` ERROR: ${err}`); | ||
| console.error(' ImageMagick binary download failed.'); | ||
| console.error(' The package will still work if ImageMagick is installed on your system.'); | ||
| process.exit(0); | ||
| } | ||
| } | ||
| install() | ||
| .catch((err) => { | ||
| console.error('Installation failed:', err); | ||
| }) | ||
| .finally(() => process.exit(0)); |
+5
-6
| { | ||
| "name": "imagemagick-nodejs", | ||
| "version": "0.2.1", | ||
| "version": "0.2.2", | ||
| "description": "A comprehensive Node.js wrapper for ImageMagick CLI", | ||
@@ -18,3 +18,3 @@ "author": { | ||
| "import": { | ||
| "types": "./dist/index.d.mts", | ||
| "types": "./dist/index.d.ts", | ||
| "default": "./dist/index.mjs" | ||
@@ -29,3 +29,4 @@ }, | ||
| "files": [ | ||
| "dist" | ||
| "dist", | ||
| "scripts" | ||
| ], | ||
@@ -45,5 +46,3 @@ "engines": { | ||
| "test:run": "vitest run", | ||
| "download": "tsx ./src/scripts/install.ts", | ||
| "download:prod": "node ./dist/install.js", | ||
| "postinstall": "node -e \"process.env.INIT_CWD !== process.cwd() && require('child_process').execSync('npm run download:prod', { stdio: 'inherit' });\"", | ||
| "postinstall": "node ./scripts/install.js", | ||
| "prepublishOnly": "npm run build" | ||
@@ -50,0 +49,0 @@ }, |
-300
| 'use strict'; | ||
| var fs2 = require('fs'); | ||
| var path = require('path'); | ||
| var https = require('https'); | ||
| var child_process = require('child_process'); | ||
| var tar = require('tar'); | ||
| function _interopNamespace(e) { | ||
| if (e && e.__esModule) return e; | ||
| var n = Object.create(null); | ||
| if (e) { | ||
| Object.keys(e).forEach(function (k) { | ||
| if (k !== 'default') { | ||
| var d = Object.getOwnPropertyDescriptor(e, k); | ||
| Object.defineProperty(n, k, d.get ? d : { | ||
| enumerable: true, | ||
| get: function () { return e[k]; } | ||
| }); | ||
| } | ||
| }); | ||
| } | ||
| n.default = e; | ||
| return Object.freeze(n); | ||
| } | ||
| var fs2__namespace = /*#__PURE__*/_interopNamespace(fs2); | ||
| var path__namespace = /*#__PURE__*/_interopNamespace(path); | ||
| var https__namespace = /*#__PURE__*/_interopNamespace(https); | ||
| var tar__namespace = /*#__PURE__*/_interopNamespace(tar); | ||
| var __getOwnPropNames = Object.getOwnPropertyNames; | ||
| var __esm = (fn, res) => function __init() { | ||
| return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res; | ||
| }; | ||
| var __commonJS = (cb, mod) => function __require() { | ||
| return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports; | ||
| }; | ||
| // node_modules/tsup/assets/cjs_shims.js | ||
| var init_cjs_shims = __esm({ | ||
| "node_modules/tsup/assets/cjs_shims.js"() { | ||
| } | ||
| }); | ||
| function findPackageRoot(startDir) { | ||
| let current = startDir; | ||
| while (true) { | ||
| if (fs2__namespace.existsSync(path__namespace.join(current, "package.json"))) { | ||
| return current; | ||
| } | ||
| const parent = path__namespace.dirname(current); | ||
| if (parent === current) { | ||
| return startDir; | ||
| } | ||
| current = parent; | ||
| } | ||
| } | ||
| var PACKAGE_ROOT, VENDOR_DIR, BIN_DIR; | ||
| var init_paths = __esm({ | ||
| "src/utils/paths.ts"() { | ||
| init_cjs_shims(); | ||
| PACKAGE_ROOT = findPackageRoot(__dirname); | ||
| VENDOR_DIR = path__namespace.join(PACKAGE_ROOT, "vendor"); | ||
| BIN_DIR = path__namespace.join(VENDOR_DIR, "bin"); | ||
| path__namespace.join(PACKAGE_ROOT, "package.json"); | ||
| } | ||
| }); | ||
| var require_install = __commonJS({ | ||
| "src/scripts/install.ts"() { | ||
| init_cjs_shims(); | ||
| init_paths(); | ||
| var GITHUB_REPO = "iqbal-rashed/imagemagick-nodejs"; | ||
| var RELEASE_TAG = "bin-main"; | ||
| function isMusl() { | ||
| if (process.platform !== "linux") return false; | ||
| try { | ||
| const lddOutput = child_process.execSync("ldd --version 2>&1 || true", { encoding: "utf8" }); | ||
| if (lddOutput.toLowerCase().includes("musl")) return true; | ||
| if (fs2__namespace.existsSync("/etc/alpine-release")) return true; | ||
| const libDir = fs2__namespace.readdirSync("/lib").filter((f) => f.startsWith("libc.musl")); | ||
| if (libDir.length > 0) return true; | ||
| } catch { | ||
| } | ||
| return false; | ||
| } | ||
| function getPlatformId() { | ||
| const platform = process.platform; | ||
| const arch = process.arch; | ||
| if (platform === "win32") { | ||
| if (arch === "x64") return "windows-x64"; | ||
| if (arch === "ia32") return "windows-x86"; | ||
| throw new Error(`Unsupported Windows architecture: ${arch}`); | ||
| } | ||
| if (platform === "darwin") { | ||
| if (arch === "arm64") return "macos-arm64"; | ||
| if (arch === "x64") return "macos-x64"; | ||
| throw new Error(`Unsupported macOS architecture: ${arch}`); | ||
| } | ||
| if (platform === "linux") { | ||
| const libc = isMusl() ? "musl" : "glibc"; | ||
| if (arch === "x64") return `linux-${libc}-amd64`; | ||
| if (arch === "arm64") return `linux-${libc}-arm64`; | ||
| throw new Error(`Unsupported Linux architecture: ${arch}`); | ||
| } | ||
| throw new Error(`Unsupported platform: ${platform}`); | ||
| } | ||
| var ALLOWED_REDIRECT_DOMAINS = [ | ||
| "github.com", | ||
| "api.github.com", | ||
| "objects.githubusercontent.com", | ||
| "codeload.github.com", | ||
| "raw.githubusercontent.com", | ||
| "release-assets.githubusercontent.com" | ||
| ]; | ||
| function validateRedirectUrl(url) { | ||
| try { | ||
| const parsed = new URL(url); | ||
| const hostname = parsed.hostname.toLowerCase(); | ||
| return ALLOWED_REDIRECT_DOMAINS.some( | ||
| (domain) => hostname === domain || hostname.endsWith(`.${domain}`) | ||
| ); | ||
| } catch { | ||
| return false; | ||
| } | ||
| } | ||
| function fetchJson(url) { | ||
| return new Promise((resolve, reject) => { | ||
| const parsedUrl = new URL(url); | ||
| const headers = { | ||
| "User-Agent": "imagemagick-nodejs", | ||
| Accept: "application/vnd.github.v3+json" | ||
| }; | ||
| const token = process.env.GITHUB_TOKEN; | ||
| if (token) { | ||
| headers["Authorization"] = `Bearer ${token}`; | ||
| } | ||
| const options = { | ||
| hostname: parsedUrl.hostname, | ||
| path: parsedUrl.pathname + parsedUrl.search, | ||
| headers | ||
| }; | ||
| https__namespace.get(options, (res) => { | ||
| if (res.statusCode === 302 || res.statusCode === 301) { | ||
| const location = res.headers.location; | ||
| if (location) { | ||
| if (!validateRedirectUrl(location)) { | ||
| reject(new Error(`Redirect to disallowed domain: ${location}`)); | ||
| return; | ||
| } | ||
| fetchJson(location).then(resolve).catch(reject); | ||
| } else { | ||
| reject(new Error("Redirect without location header")); | ||
| } | ||
| return; | ||
| } | ||
| if (res.statusCode !== 200) { | ||
| reject(new Error(`Failed to fetch release: ${res.statusCode}`)); | ||
| return; | ||
| } | ||
| let data = ""; | ||
| res.on("data", (chunk) => data += chunk.toString()); | ||
| res.on("end", () => { | ||
| try { | ||
| resolve(JSON.parse(data)); | ||
| } catch (e) { | ||
| reject(new Error(`Failed to parse JSON: ${e}`)); | ||
| } | ||
| }); | ||
| }).on("error", reject); | ||
| }); | ||
| } | ||
| function downloadFile(url, destPath) { | ||
| return new Promise((resolve, reject) => { | ||
| const file = fs2__namespace.createWriteStream(destPath); | ||
| const request = (downloadUrl) => { | ||
| const parsedUrl = new URL(downloadUrl); | ||
| const headers = { | ||
| "User-Agent": "imagemagick-nodejs" | ||
| }; | ||
| const token = process.env.GITHUB_TOKEN; | ||
| if (token && parsedUrl.hostname.includes("github")) { | ||
| headers["Authorization"] = `Bearer ${token}`; | ||
| } | ||
| const options = { | ||
| hostname: parsedUrl.hostname, | ||
| path: parsedUrl.pathname + parsedUrl.search, | ||
| headers | ||
| }; | ||
| https__namespace.get(options, (res) => { | ||
| if (res.statusCode === 302 || res.statusCode === 301) { | ||
| const location = res.headers.location; | ||
| if (location) { | ||
| if (!validateRedirectUrl(location)) { | ||
| reject(new Error(`Redirect to disallowed domain: ${location}`)); | ||
| return; | ||
| } | ||
| request(location); | ||
| } else { | ||
| reject(new Error("Redirect without location header")); | ||
| } | ||
| return; | ||
| } | ||
| if (res.statusCode !== 200) { | ||
| reject(new Error(`Download failed: ${res.statusCode}`)); | ||
| return; | ||
| } | ||
| const totalSize = parseInt(res.headers["content-length"] ?? "0", 10); | ||
| let downloadedSize = 0; | ||
| res.on("data", (chunk) => { | ||
| downloadedSize += chunk.length; | ||
| if (totalSize > 0) { | ||
| const percent = (downloadedSize / totalSize * 100).toFixed(1); | ||
| process.stdout.write(`\r Downloading: ${percent}%`); | ||
| } | ||
| }); | ||
| res.pipe(file); | ||
| file.on("finish", () => { | ||
| file.close(); | ||
| console.log(" Done!"); | ||
| resolve(); | ||
| }); | ||
| }).on("error", (err) => { | ||
| fs2__namespace.unlink(destPath, () => { | ||
| }); | ||
| reject(err); | ||
| }); | ||
| }; | ||
| request(url); | ||
| }); | ||
| } | ||
| async function extractTarGz(tarPath, destDir) { | ||
| await tar__namespace.extract({ | ||
| file: tarPath, | ||
| cwd: destDir, | ||
| strip: 1 | ||
| }); | ||
| console.log(` Extracted to ${destDir}`); | ||
| } | ||
| function makeExecutable(binaryPath) { | ||
| if (process.platform === "win32") return; | ||
| try { | ||
| fs2__namespace.chmodSync(binaryPath, 493); | ||
| } catch (err) { | ||
| console.warn(`Warning: Could not make binary executable: ${err}`); | ||
| } | ||
| } | ||
| async function install() { | ||
| console.log("[imagemagick-nodejs] Installing ImageMagick binary..."); | ||
| if (process.env["IMAGEMAGICK_SKIP_DOWNLOAD"]) { | ||
| console.log(" Skipping download (IMAGEMAGICK_SKIP_DOWNLOAD is set)"); | ||
| return; | ||
| } | ||
| const binaryName = process.platform === "win32" ? "magick.exe" : "magick"; | ||
| const binaryPath = path__namespace.join(BIN_DIR, binaryName); | ||
| if (fs2__namespace.existsSync(binaryPath)) { | ||
| console.log(" Binary already exists, skipping download"); | ||
| return; | ||
| } | ||
| try { | ||
| const platformId = getPlatformId(); | ||
| console.log(` Platform: ${platformId}`); | ||
| console.log(" Fetching release info..."); | ||
| const releaseUrl = `https://api.github.com/repos/${GITHUB_REPO}/releases/tags/${RELEASE_TAG}`; | ||
| const release = await fetchJson(releaseUrl); | ||
| const assetPattern = new RegExp(`imagemagick-.*-${platformId}\\.tar\\.gz$`); | ||
| const asset = release.assets.find((a) => assetPattern.test(a.name)); | ||
| if (!asset) { | ||
| console.error(` ERROR: No binary available for ${platformId}`); | ||
| console.error(" Available assets:", release.assets.map((a) => a.name).join(", ")); | ||
| console.error(" You may need to install ImageMagick manually."); | ||
| process.exit(0); | ||
| } | ||
| console.log(` Found asset: ${asset.name}`); | ||
| fs2__namespace.mkdirSync(BIN_DIR, { recursive: true }); | ||
| const tarPath = path__namespace.join(VENDOR_DIR, asset.name); | ||
| await downloadFile(asset.browser_download_url, tarPath); | ||
| console.log(" Extracting..."); | ||
| await extractTarGz(tarPath, VENDOR_DIR); | ||
| fs2__namespace.unlinkSync(tarPath); | ||
| makeExecutable(binaryPath); | ||
| if (fs2__namespace.existsSync(binaryPath)) { | ||
| console.log(` \u2713 ImageMagick installed to ${BIN_DIR}`); | ||
| } else { | ||
| throw new Error("Binary not found after extraction"); | ||
| } | ||
| } catch (err) { | ||
| console.error(` ERROR: ${err}`); | ||
| console.error(" ImageMagick binary download failed."); | ||
| console.error(" The package will still work if ImageMagick is installed on your system."); | ||
| process.exit(0); | ||
| } | ||
| } | ||
| install().catch((err) => { | ||
| console.error("Installation failed:", err); | ||
| }).finally(() => process.exit(0)); | ||
| } | ||
| }); | ||
| var install = require_install(); | ||
| module.exports = install; |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Install scripts
Supply chain riskInstall scripts are run when the package is installed or built. Malicious packages often use scripts that run automatically to execute payloads or fetch additional code.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 2 instances in 1 package
Shell access
Supply chain riskThis module accesses the system shell. Accessing the system shell increases the risk of executing arbitrary code.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 6 instances in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
AI-detected potential code anomaly
Supply chain riskAI has identified unusual behaviors that may pose a security risk.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
Install scripts
Supply chain riskInstall scripts are run when the package is installed or built. Malicious packages often use scripts that run automatically to execute payloads or fetch additional code.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 2 instances in 1 package
Shell access
Supply chain riskThis module accesses the system shell. Accessing the system shell increases the risk of executing arbitrary code.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 6 instances in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
23
-37.84%195023
-38.87%3148
-72.8%3
200%