From 7727d1d08c7343b5a978dfc264132cba56f997d4 Mon Sep 17 00:00:00 2001 From: Joseph Barcia Date: Tue, 21 Apr 2026 13:06:11 +0000 Subject: [PATCH] Fix pmapper-data-basepath ignored in all-checks and race condition in instances module The pmapperCommand in runAllChecksCommand was missing the PmapperDataBasePath parameter, causing --pmapper-data-basepath to be ignored for the pmapper module when running all-checks. (Fixes #105) The instances module had a race condition where role analysis ran before the receiver goroutine finished collecting all MappedInstances. This caused IsAdminRole and CanPrivEscToAdmin columns to appear empty in all-checks despite pmapper data being available. Fixed by signaling the receiver to stop and waiting for it to drain before running role analysis. Version bumped to 2.0.4. --- aws/instances.go | 10 ++++++---- cli/aws.go | 13 +++++++------ globals/utils.go | 2 +- 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/aws/instances.go b/aws/instances.go index 438cd845..2ee0e0d1 100644 --- a/aws/instances.go +++ b/aws/instances.go @@ -128,9 +128,13 @@ func (m *InstancesModule) Instances(filter string, outputDirectory string, verbo } wg.Wait() - //time.Sleep(time.Second * 2) - // Perform role analysis + // Signal the receiver to stop and wait for it to finish draining the channel. + // This must happen BEFORE role analysis to ensure all MappedInstances are collected. + receiverDone <- true + <-receiverDone + + // Perform role analysis (all instances are now in m.MappedInstances) if m.pmapperError == nil { for i := range m.MappedInstances { m.MappedInstances[i].Admin, m.MappedInstances[i].CanPrivEsc = GetPmapperResults(m.SkipAdminCheck, m.pmapperMod, &m.MappedInstances[i].Role) @@ -144,8 +148,6 @@ func (m *InstancesModule) Instances(filter string, outputDirectory string, verbo // Send a message to the spinner goroutine to close the channel and stop spinnerDone <- true <-spinnerDone - receiverDone <- true - <-receiverDone // This conditional block will either dump the userData attribute content or the general instances data, depending on what you select via command line. //fmt.Printf("\n[*] Preparing output...\n\n") diff --git a/cli/aws.go b/cli/aws.go index 386a11fb..d1646708 100644 --- a/cli/aws.go +++ b/cli/aws.go @@ -2435,12 +2435,13 @@ func runAllChecksCommand(cmd *cobra.Command, args []string) { roleTrusts.PrintRoleTrusts(AWSOutputDirectory, Verbosity) pmapperCommand := aws.PmapperModule{ - Caller: *caller, - AWSProfile: profile, - Goroutines: Goroutines, - WrapTable: AWSWrapTable, - AWSOutputType: AWSOutputType, - AWSTableCols: AWSTableCols, + Caller: *caller, + AWSProfile: profile, + Goroutines: Goroutines, + WrapTable: AWSWrapTable, + AWSOutputType: AWSOutputType, + AWSTableCols: AWSTableCols, + PmapperDataBasePath: PmapperDataBasePath, } pmapperCommand.PrintPmapperData(AWSOutputDirectory, Verbosity) diff --git a/globals/utils.go b/globals/utils.go index ae32e1cd..4b512f22 100644 --- a/globals/utils.go +++ b/globals/utils.go @@ -4,4 +4,4 @@ const CLOUDFOX_USER_AGENT = "cloudfox" const CLOUDFOX_LOG_FILE_DIR_NAME = ".cloudfox" const CLOUDFOX_BASE_DIRECTORY = "cloudfox-output" const LOOT_DIRECTORY_NAME = "loot" -const CLOUDFOX_VERSION = "2.0.3" +const CLOUDFOX_VERSION = "2.0.4"