@vercel/backends
Advanced tools
+226
-8
@@ -6,3 +6,3 @@ import { builtinModules, createRequire } from "node:module"; | ||
| import { lstat, readFile, rm, stat } from "node:fs/promises"; | ||
| import { dirname as dirname$1, extname as extname$1, isAbsolute, join as join$1, relative } from "node:path"; | ||
| import { basename, dirname as dirname$1, extname as extname$1, isAbsolute, join as join$1, relative } from "node:path"; | ||
| import { build as build$2 } from "rolldown"; | ||
@@ -678,2 +678,163 @@ import { exports } from "resolve.exports"; | ||
| //#endregion | ||
| //#region src/service-vc-init.ts | ||
| async function applyServiceVcInit(args) { | ||
| const { format, extension } = await resolveShimFormat(args); | ||
| const handlerDir = dirname$1(args.handler); | ||
| const vcInitName = `${basename(args.handler, extname$1(args.handler))}.__vc_service_vc_init${extension}`; | ||
| const vcInitHandler = handlerDir === "." ? vcInitName : join$1(handlerDir, vcInitName); | ||
| const handlerImportPath = `./${basename(args.handler)}`; | ||
| const vcInitSource = format === "esm" ? createEsmServiceVcInit(handlerImportPath) : createCjsServiceVcInit(handlerImportPath); | ||
| return { | ||
| handler: vcInitHandler, | ||
| files: { | ||
| ...args.files, | ||
| [vcInitHandler]: new FileBlob({ | ||
| data: vcInitSource, | ||
| mode: 420 | ||
| }) | ||
| } | ||
| }; | ||
| } | ||
| async function resolveShimFormat(args) { | ||
| const { format } = await resolveEntrypointAndFormat({ | ||
| entrypoint: args.handler, | ||
| workPath: args.workPath | ||
| }); | ||
| return { | ||
| format, | ||
| extension: extname$1(args.handler) || (format === "esm" ? ".mjs" : ".cjs") | ||
| }; | ||
| } | ||
| const sharedShimPrelude = String.raw` | ||
| const PATCH_SYMBOL = Symbol.for('vc.service.route-prefix-strip.patch') | ||
| function normalizeServiceRoutePrefix(rawPrefix) { | ||
| if (!rawPrefix) { | ||
| return '' | ||
| } | ||
| let prefix = String(rawPrefix).trim() | ||
| if (!prefix) { | ||
| return '' | ||
| } | ||
| if (!prefix.startsWith('/')) { | ||
| prefix = '/' + prefix | ||
| } | ||
| if (prefix !== '/') { | ||
| prefix = prefix.replace(/\/+$/, '') | ||
| } | ||
| return prefix === '/' ? '' : prefix | ||
| } | ||
| function getServiceRoutePrefix() { | ||
| const enabled = String( | ||
| process.env.VERCEL_SERVICE_ROUTE_PREFIX_STRIP || '' | ||
| ).toLowerCase() | ||
| if (enabled !== '1' && enabled !== 'true') { | ||
| return '' | ||
| } | ||
| return normalizeServiceRoutePrefix(process.env.VERCEL_SERVICE_ROUTE_PREFIX || '') | ||
| } | ||
| function stripServiceRoutePrefix(requestUrl, prefix) { | ||
| if (typeof requestUrl !== 'string' || requestUrl === '*') { | ||
| return requestUrl | ||
| } | ||
| const queryIndex = requestUrl.indexOf('?') | ||
| const rawPath = | ||
| queryIndex === -1 ? requestUrl : requestUrl.slice(0, queryIndex) | ||
| const query = queryIndex === -1 ? '' : requestUrl.slice(queryIndex) | ||
| let path = rawPath || '/' | ||
| if (!path.startsWith('/')) { | ||
| path = '/' + path | ||
| } | ||
| if (!prefix) { | ||
| return path + query | ||
| } | ||
| if (path === prefix) { | ||
| return '/' + query | ||
| } | ||
| if (path.startsWith(prefix + '/')) { | ||
| return path.slice(prefix.length) + query | ||
| } | ||
| return path + query | ||
| } | ||
| function patchServerRequestUrl(ServerCtor) { | ||
| const prefix = getServiceRoutePrefix() | ||
| if (!prefix || globalThis[PATCH_SYMBOL]) { | ||
| return | ||
| } | ||
| globalThis[PATCH_SYMBOL] = true | ||
| const originalEmit = ServerCtor.prototype.emit | ||
| ServerCtor.prototype.emit = function patchedEmit(event, request, ...args) { | ||
| if (event === 'request' && request && typeof request.url === 'string') { | ||
| request.url = stripServiceRoutePrefix(request.url, prefix) | ||
| } | ||
| return originalEmit.call(this, event, request, ...args) | ||
| } | ||
| } | ||
| `; | ||
| function createEsmServiceVcInit(handlerImportPath) { | ||
| return ` | ||
| import { Server } from 'node:http' | ||
| ${sharedShimPrelude} | ||
| // Patch the HTTP server before loading user code so apps that attach request | ||
| // listeners during module evaluation see the stripped service-relative URL. | ||
| patchServerRequestUrl(Server) | ||
| const originalModule = await import(${JSON.stringify(handlerImportPath)}) | ||
| /** | ||
| * Match the Node serverless loader behavior: TS/CJS/ESM interop can leave us | ||
| * with nested \`.default\` wrappers, so peel off a few layers to recover the | ||
| * actual user entrypoint shape. | ||
| */ | ||
| function unwrapDefaultExport(value) { | ||
| let current = value | ||
| for (let i = 0; i < 5; i++) { | ||
| if (current && typeof current === 'object' && 'default' in current && current.default) { | ||
| current = current.default | ||
| } else { | ||
| break | ||
| } | ||
| } | ||
| return current | ||
| } | ||
| const entrypoint = unwrapDefaultExport(originalModule) | ||
| // Re-export the resolved entrypoint so the surrounding runtime still sees the | ||
| // same handler shape after this service bootstrap runs. | ||
| export default typeof entrypoint === 'undefined' ? originalModule : entrypoint | ||
| `.trimStart(); | ||
| } | ||
| function createCjsServiceVcInit(handlerImportPath) { | ||
| return ` | ||
| const { Server } = require('node:http') | ||
| ${sharedShimPrelude} | ||
| patchServerRequestUrl(Server) | ||
| module.exports = require(${JSON.stringify(handlerImportPath)}) | ||
| `.trimStart(); | ||
| } | ||
| //#endregion | ||
| //#region src/rolldown/nft.ts | ||
@@ -1480,6 +1641,19 @@ const nft = async (args) => { | ||
| }); | ||
| const serviceRoutePrefix = normalizeServiceRoutePrefix(args.config?.routePrefix ?? args.service?.routePrefix); | ||
| const shouldStripServiceRoutePrefix = !!serviceRoutePrefix && (typeof args.config?.serviceName === "string" || !!args.service); | ||
| let lambdaFiles = files; | ||
| let lambdaHandler = handler; | ||
| if (shouldStripServiceRoutePrefix) { | ||
| const shimmedLambda = await applyServiceVcInit({ | ||
| files, | ||
| handler, | ||
| workPath: nftWorkPath | ||
| }); | ||
| lambdaFiles = shimmedLambda.files; | ||
| lambdaHandler = shimmedLambda.handler; | ||
| } | ||
| const lambda = new NodejsLambda({ | ||
| runtime: nodeVersion.runtime, | ||
| handler, | ||
| files, | ||
| handler: lambdaHandler, | ||
| files: lambdaFiles, | ||
| framework: rolldownResult.framework, | ||
@@ -1492,14 +1666,31 @@ shouldAddHelpers: false, | ||
| }); | ||
| if (shouldStripServiceRoutePrefix && serviceRoutePrefix) lambda.environment = { | ||
| ...lambda.environment, | ||
| VERCEL_SERVICE_ROUTE_PREFIX: serviceRoutePrefix, | ||
| VERCEL_SERVICE_ROUTE_PREFIX_STRIP: "1" | ||
| }; | ||
| const serviceName = typeof args.config?.serviceName === "string" && args.config.serviceName !== "" ? args.config.serviceName : void 0; | ||
| const internalServiceFunctionPath = typeof serviceName === "string" && serviceName !== "" ? `/_svc/${serviceName}/index` : void 0; | ||
| const internalServiceOutputPath = internalServiceFunctionPath?.slice(1); | ||
| const remapRouteDestination = (route) => { | ||
| const prefixedRoute = maybePrefixServiceRouteSource(route, serviceRoutePrefix); | ||
| if (!internalServiceFunctionPath || !route.dest) return prefixedRoute; | ||
| return { | ||
| ...prefixedRoute, | ||
| dest: internalServiceFunctionPath | ||
| }; | ||
| }; | ||
| const routes = [ | ||
| { handle: "filesystem" }, | ||
| ...introspectionResult.routes, | ||
| ...introspectionResult.routes.map(remapRouteDestination), | ||
| { | ||
| src: "/(.*)", | ||
| dest: "/" | ||
| src: getServiceCatchallSource(serviceRoutePrefix), | ||
| dest: internalServiceFunctionPath ?? "/" | ||
| } | ||
| ]; | ||
| const output = { index: lambda }; | ||
| const output = internalServiceOutputPath ? { [internalServiceOutputPath]: lambda } : { index: lambda }; | ||
| for (const route of routes) if (route.dest) { | ||
| if (route.dest === "/") continue; | ||
| output[route.dest] = lambda; | ||
| const outputPath = route.dest === internalServiceFunctionPath && internalServiceOutputPath ? internalServiceOutputPath : route.dest; | ||
| output[outputPath] = lambda; | ||
| } | ||
@@ -1516,4 +1707,31 @@ return { | ||
| const normalizeArray = (value) => Array.isArray(value) ? value : value ? [value] : []; | ||
| const normalizeServiceRoutePrefix = (routePrefix) => { | ||
| if (typeof routePrefix !== "string" || routePrefix === "" || routePrefix === ".") return; | ||
| let normalized = routePrefix.startsWith("/") ? routePrefix : `/${routePrefix}`; | ||
| if (normalized !== "/" && normalized.endsWith("/")) normalized = normalized.slice(0, -1); | ||
| return normalized === "/" ? void 0 : normalized; | ||
| }; | ||
| const maybePrefixServiceRouteSource = (route, routePrefix) => { | ||
| if (!routePrefix || typeof route.dest !== "string" || !route.dest.startsWith("/")) return route; | ||
| return { | ||
| ...route, | ||
| src: getPrefixedRouteSource(route.src, route.dest, routePrefix) | ||
| }; | ||
| }; | ||
| const getPrefixedRouteSource = (routeSource, routePath, routePrefix) => { | ||
| if (!routeSource) return routeSource; | ||
| if (routePath === routePrefix || routePath.startsWith(`${routePrefix}/`)) return routeSource; | ||
| const escapedRoutePrefix = toRegexSource(routePrefix); | ||
| if (routeSource.startsWith("^(?:")) return `^(?:${escapedRoutePrefix}${routeSource.slice(4)}`; | ||
| if (routeSource.startsWith("^")) return `^${escapedRoutePrefix}${routeSource.slice(1)}`; | ||
| return `${escapedRoutePrefix}${routeSource}`; | ||
| }; | ||
| const getServiceCatchallSource = (routePrefix) => { | ||
| if (!routePrefix) return "/(.*)"; | ||
| return `^${escapeForRegex(routePrefix)}(?:/(.*))?$`; | ||
| }; | ||
| const escapeForRegex = (value) => value.replace(/[|\\{}()[\]^$+*?.]/g, "\\$&"); | ||
| const toRegexSource = (value) => escapeForRegex(value).replaceAll("/", "\\/"); | ||
| //#endregion | ||
| export { build, build$1 as cervelBuild, serve as cervelServe, findEntrypoint, findEntrypointOrThrow, getBuildSummary, introspectApp, nodeFileTrace, prepareCache, srvxOptions, version }; |
+226
-8
@@ -6,3 +6,3 @@ import { builtinModules, createRequire } from "node:module"; | ||
| import { lstat, readFile, rm, stat } from "node:fs/promises"; | ||
| import { dirname as dirname$1, extname as extname$1, isAbsolute, join as join$1, relative } from "node:path"; | ||
| import { basename, dirname as dirname$1, extname as extname$1, isAbsolute, join as join$1, relative } from "node:path"; | ||
| import { build as build$2 } from "rolldown"; | ||
@@ -678,2 +678,163 @@ import { exports } from "resolve.exports"; | ||
| //#endregion | ||
| //#region src/service-vc-init.ts | ||
| async function applyServiceVcInit(args) { | ||
| const { format, extension } = await resolveShimFormat(args); | ||
| const handlerDir = dirname$1(args.handler); | ||
| const vcInitName = `${basename(args.handler, extname$1(args.handler))}.__vc_service_vc_init${extension}`; | ||
| const vcInitHandler = handlerDir === "." ? vcInitName : join$1(handlerDir, vcInitName); | ||
| const handlerImportPath = `./${basename(args.handler)}`; | ||
| const vcInitSource = format === "esm" ? createEsmServiceVcInit(handlerImportPath) : createCjsServiceVcInit(handlerImportPath); | ||
| return { | ||
| handler: vcInitHandler, | ||
| files: { | ||
| ...args.files, | ||
| [vcInitHandler]: new FileBlob({ | ||
| data: vcInitSource, | ||
| mode: 420 | ||
| }) | ||
| } | ||
| }; | ||
| } | ||
| async function resolveShimFormat(args) { | ||
| const { format } = await resolveEntrypointAndFormat({ | ||
| entrypoint: args.handler, | ||
| workPath: args.workPath | ||
| }); | ||
| return { | ||
| format, | ||
| extension: extname$1(args.handler) || (format === "esm" ? ".mjs" : ".cjs") | ||
| }; | ||
| } | ||
| const sharedShimPrelude = String.raw` | ||
| const PATCH_SYMBOL = Symbol.for('vc.service.route-prefix-strip.patch') | ||
| function normalizeServiceRoutePrefix(rawPrefix) { | ||
| if (!rawPrefix) { | ||
| return '' | ||
| } | ||
| let prefix = String(rawPrefix).trim() | ||
| if (!prefix) { | ||
| return '' | ||
| } | ||
| if (!prefix.startsWith('/')) { | ||
| prefix = '/' + prefix | ||
| } | ||
| if (prefix !== '/') { | ||
| prefix = prefix.replace(/\/+$/, '') | ||
| } | ||
| return prefix === '/' ? '' : prefix | ||
| } | ||
| function getServiceRoutePrefix() { | ||
| const enabled = String( | ||
| process.env.VERCEL_SERVICE_ROUTE_PREFIX_STRIP || '' | ||
| ).toLowerCase() | ||
| if (enabled !== '1' && enabled !== 'true') { | ||
| return '' | ||
| } | ||
| return normalizeServiceRoutePrefix(process.env.VERCEL_SERVICE_ROUTE_PREFIX || '') | ||
| } | ||
| function stripServiceRoutePrefix(requestUrl, prefix) { | ||
| if (typeof requestUrl !== 'string' || requestUrl === '*') { | ||
| return requestUrl | ||
| } | ||
| const queryIndex = requestUrl.indexOf('?') | ||
| const rawPath = | ||
| queryIndex === -1 ? requestUrl : requestUrl.slice(0, queryIndex) | ||
| const query = queryIndex === -1 ? '' : requestUrl.slice(queryIndex) | ||
| let path = rawPath || '/' | ||
| if (!path.startsWith('/')) { | ||
| path = '/' + path | ||
| } | ||
| if (!prefix) { | ||
| return path + query | ||
| } | ||
| if (path === prefix) { | ||
| return '/' + query | ||
| } | ||
| if (path.startsWith(prefix + '/')) { | ||
| return path.slice(prefix.length) + query | ||
| } | ||
| return path + query | ||
| } | ||
| function patchServerRequestUrl(ServerCtor) { | ||
| const prefix = getServiceRoutePrefix() | ||
| if (!prefix || globalThis[PATCH_SYMBOL]) { | ||
| return | ||
| } | ||
| globalThis[PATCH_SYMBOL] = true | ||
| const originalEmit = ServerCtor.prototype.emit | ||
| ServerCtor.prototype.emit = function patchedEmit(event, request, ...args) { | ||
| if (event === 'request' && request && typeof request.url === 'string') { | ||
| request.url = stripServiceRoutePrefix(request.url, prefix) | ||
| } | ||
| return originalEmit.call(this, event, request, ...args) | ||
| } | ||
| } | ||
| `; | ||
| function createEsmServiceVcInit(handlerImportPath) { | ||
| return ` | ||
| import { Server } from 'node:http' | ||
| ${sharedShimPrelude} | ||
| // Patch the HTTP server before loading user code so apps that attach request | ||
| // listeners during module evaluation see the stripped service-relative URL. | ||
| patchServerRequestUrl(Server) | ||
| const originalModule = await import(${JSON.stringify(handlerImportPath)}) | ||
| /** | ||
| * Match the Node serverless loader behavior: TS/CJS/ESM interop can leave us | ||
| * with nested \`.default\` wrappers, so peel off a few layers to recover the | ||
| * actual user entrypoint shape. | ||
| */ | ||
| function unwrapDefaultExport(value) { | ||
| let current = value | ||
| for (let i = 0; i < 5; i++) { | ||
| if (current && typeof current === 'object' && 'default' in current && current.default) { | ||
| current = current.default | ||
| } else { | ||
| break | ||
| } | ||
| } | ||
| return current | ||
| } | ||
| const entrypoint = unwrapDefaultExport(originalModule) | ||
| // Re-export the resolved entrypoint so the surrounding runtime still sees the | ||
| // same handler shape after this service bootstrap runs. | ||
| export default typeof entrypoint === 'undefined' ? originalModule : entrypoint | ||
| `.trimStart(); | ||
| } | ||
| function createCjsServiceVcInit(handlerImportPath) { | ||
| return ` | ||
| const { Server } = require('node:http') | ||
| ${sharedShimPrelude} | ||
| patchServerRequestUrl(Server) | ||
| module.exports = require(${JSON.stringify(handlerImportPath)}) | ||
| `.trimStart(); | ||
| } | ||
| //#endregion | ||
| //#region src/rolldown/nft.ts | ||
@@ -1480,6 +1641,19 @@ const nft = async (args) => { | ||
| }); | ||
| const serviceRoutePrefix = normalizeServiceRoutePrefix(args.config?.routePrefix ?? args.service?.routePrefix); | ||
| const shouldStripServiceRoutePrefix = !!serviceRoutePrefix && (typeof args.config?.serviceName === "string" || !!args.service); | ||
| let lambdaFiles = files; | ||
| let lambdaHandler = handler; | ||
| if (shouldStripServiceRoutePrefix) { | ||
| const shimmedLambda = await applyServiceVcInit({ | ||
| files, | ||
| handler, | ||
| workPath: nftWorkPath | ||
| }); | ||
| lambdaFiles = shimmedLambda.files; | ||
| lambdaHandler = shimmedLambda.handler; | ||
| } | ||
| const lambda = new NodejsLambda({ | ||
| runtime: nodeVersion.runtime, | ||
| handler, | ||
| files, | ||
| handler: lambdaHandler, | ||
| files: lambdaFiles, | ||
| framework: rolldownResult.framework, | ||
@@ -1492,14 +1666,31 @@ shouldAddHelpers: false, | ||
| }); | ||
| if (shouldStripServiceRoutePrefix && serviceRoutePrefix) lambda.environment = { | ||
| ...lambda.environment, | ||
| VERCEL_SERVICE_ROUTE_PREFIX: serviceRoutePrefix, | ||
| VERCEL_SERVICE_ROUTE_PREFIX_STRIP: "1" | ||
| }; | ||
| const serviceName = typeof args.config?.serviceName === "string" && args.config.serviceName !== "" ? args.config.serviceName : void 0; | ||
| const internalServiceFunctionPath = typeof serviceName === "string" && serviceName !== "" ? `/_svc/${serviceName}/index` : void 0; | ||
| const internalServiceOutputPath = internalServiceFunctionPath?.slice(1); | ||
| const remapRouteDestination = (route) => { | ||
| const prefixedRoute = maybePrefixServiceRouteSource(route, serviceRoutePrefix); | ||
| if (!internalServiceFunctionPath || !route.dest) return prefixedRoute; | ||
| return { | ||
| ...prefixedRoute, | ||
| dest: internalServiceFunctionPath | ||
| }; | ||
| }; | ||
| const routes = [ | ||
| { handle: "filesystem" }, | ||
| ...introspectionResult.routes, | ||
| ...introspectionResult.routes.map(remapRouteDestination), | ||
| { | ||
| src: "/(.*)", | ||
| dest: "/" | ||
| src: getServiceCatchallSource(serviceRoutePrefix), | ||
| dest: internalServiceFunctionPath ?? "/" | ||
| } | ||
| ]; | ||
| const output = { index: lambda }; | ||
| const output = internalServiceOutputPath ? { [internalServiceOutputPath]: lambda } : { index: lambda }; | ||
| for (const route of routes) if (route.dest) { | ||
| if (route.dest === "/") continue; | ||
| output[route.dest] = lambda; | ||
| const outputPath = route.dest === internalServiceFunctionPath && internalServiceOutputPath ? internalServiceOutputPath : route.dest; | ||
| output[outputPath] = lambda; | ||
| } | ||
@@ -1516,4 +1707,31 @@ return { | ||
| const normalizeArray = (value) => Array.isArray(value) ? value : value ? [value] : []; | ||
| const normalizeServiceRoutePrefix = (routePrefix) => { | ||
| if (typeof routePrefix !== "string" || routePrefix === "" || routePrefix === ".") return; | ||
| let normalized = routePrefix.startsWith("/") ? routePrefix : `/${routePrefix}`; | ||
| if (normalized !== "/" && normalized.endsWith("/")) normalized = normalized.slice(0, -1); | ||
| return normalized === "/" ? void 0 : normalized; | ||
| }; | ||
| const maybePrefixServiceRouteSource = (route, routePrefix) => { | ||
| if (!routePrefix || typeof route.dest !== "string" || !route.dest.startsWith("/")) return route; | ||
| return { | ||
| ...route, | ||
| src: getPrefixedRouteSource(route.src, route.dest, routePrefix) | ||
| }; | ||
| }; | ||
| const getPrefixedRouteSource = (routeSource, routePath, routePrefix) => { | ||
| if (!routeSource) return routeSource; | ||
| if (routePath === routePrefix || routePath.startsWith(`${routePrefix}/`)) return routeSource; | ||
| const escapedRoutePrefix = toRegexSource(routePrefix); | ||
| if (routeSource.startsWith("^(?:")) return `^(?:${escapedRoutePrefix}${routeSource.slice(4)}`; | ||
| if (routeSource.startsWith("^")) return `^${escapedRoutePrefix}${routeSource.slice(1)}`; | ||
| return `${escapedRoutePrefix}${routeSource}`; | ||
| }; | ||
| const getServiceCatchallSource = (routePrefix) => { | ||
| if (!routePrefix) return "/(.*)"; | ||
| return `^${escapeForRegex(routePrefix)}(?:/(.*))?$`; | ||
| }; | ||
| const escapeForRegex = (value) => value.replace(/[|\\{}()[\]^$+*?.]/g, "\\$&"); | ||
| const toRegexSource = (value) => escapeForRegex(value).replaceAll("/", "\\/"); | ||
| //#endregion | ||
| export { build, build$1 as cervelBuild, serve as cervelServe, findEntrypoint, findEntrypointOrThrow, getBuildSummary, introspectApp, nodeFileTrace, prepareCache, srvxOptions, version }; |
+1
-1
| { | ||
| "name": "@vercel/backends", | ||
| "version": "0.0.46", | ||
| "version": "0.0.47", | ||
| "license": "Apache-2.0", | ||
@@ -5,0 +5,0 @@ "main": "./dist/index.mjs", |
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
Debug access
Supply chain riskUses debug, reflection and dynamic code execution features.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
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 7 instances in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 2 instances 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
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
Debug access
Supply chain riskUses debug, reflection and dynamic code execution features.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
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 5 instances in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 2 instances 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
169850
9.57%4597
9.01%42
40%