diff --git a/library/agent/Agent.ts b/library/agent/Agent.ts index 067387857..712d14b10 100644 --- a/library/agent/Agent.ts +++ b/library/agent/Agent.ts @@ -36,6 +36,7 @@ export class Agent { private preventedPrototypePollution = false; private incompatiblePackages: Record = {}; private wrappedPackages: Record = {}; + private requiredPackages: Record = {}; private timeoutInMS = 10000; private hostnames = new Hostnames(200); private users = new Users(1000); @@ -268,6 +269,7 @@ export class Agent { this.routes.clear(); this.hostnames.clear(); this.users.clear(); + this.requiredPackages = {}; const response = await this.api.report( this.token, { @@ -365,6 +367,7 @@ export class Agent { }, {} ), + requiredPackages: this.requiredPackages, incompatiblePackages: { prototypePollution: this.incompatiblePackages, }, @@ -433,11 +436,24 @@ export class Agent { this.logger.log(`Failed to wrap module ${module}: ${error.message}`); } + onPackageRequired(name: string, version: string) { + if (!this.requiredPackages[name]) { + this.requiredPackages[name] = []; + } + + if (this.requiredPackages[name].includes(version)) { + return; + } + + this.requiredPackages[name].push(version); + } + onPackageWrapped(name: string, details: WrappedPackage) { if (this.wrappedPackages[name]) { // Already reported as wrapped return; } + this.wrappedPackages[name] = details; if (details.version) { diff --git a/library/agent/api/Event.ts b/library/agent/api/Event.ts index b2afd469f..193a66d9d 100644 --- a/library/agent/api/Event.ts +++ b/library/agent/api/Event.ts @@ -1,12 +1,16 @@ import { Kind } from "../Attack"; import { Source } from "../Source"; +type Version = string; +type PackageName = string; + export type AgentInfo = { dryMode: boolean; hostname: string; version: string; library: string; - packages: Record; + packages: Record; + requiredPackages: Record; ipAddress: string; preventedPrototypePollution: boolean; incompatiblePackages: { diff --git a/library/agent/hooks/wrapRequire.ts b/library/agent/hooks/wrapRequire.ts index d8b90c402..774377f1f 100644 --- a/library/agent/hooks/wrapRequire.ts +++ b/library/agent/hooks/wrapRequire.ts @@ -189,11 +189,6 @@ function patchPackage(this: mod, id: string, originalExports: unknown) { .map((pkg) => pkg.getVersions()) .flat(); - // We don't want to patch this package because we do not have any hooks for it - if (!versionedPackages.length) { - return originalExports; - } - // Read the package.json of the required package const packageJson = originalRequire( `${pathInfo.base}/package.json` @@ -207,19 +202,24 @@ function patchPackage(this: mod, id: string, originalExports: unknown) { ); } + const agent = getInstance(); + agent?.onPackageRequired(moduleName, installedPkgVersion); + + // We don't want to patch this package because we do not have any hooks for it + if (!versionedPackages.length) { + return originalExports; + } + // Check if the installed package version is supported (get all matching versioned packages) const matchingVersionedPackages = versionedPackages.filter((pkg) => satisfiesVersion(pkg.getRange(), installedPkgVersion) ); - const agent = getInstance(); - if (agent) { - // Report to the agent that the package was wrapped or not if it's version is not supported - agent.onPackageWrapped(moduleName, { - version: installedPkgVersion, - supported: !!matchingVersionedPackages.length, - }); - } + // Report to the agent that the package was wrapped or not if it's version is not supported + agent?.onPackageWrapped(moduleName, { + version: installedPkgVersion, + supported: !!matchingVersionedPackages.length, + }); if (!matchingVersionedPackages.length) { // We don't want to patch this package version