Skip to content

Commit 389f337

Browse files
Merge pull request #1237 from Checkmarx/adar-cntr-custom-images-dir-fix
Fix cases where directory files are ignored in container scans (AST-106172)
2 parents e69df50 + ab70b2f commit 389f337

File tree

3 files changed

+465
-40
lines changed

3 files changed

+465
-40
lines changed

internal/commands/scan.go

Lines changed: 62 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1473,16 +1473,39 @@ func compressFolder(sourceDir, filter, userIncludeFilter, scaResolver string) (s
14731473
}
14741474
defer outputFile.Close()
14751475
zipWriter := zip.NewWriter(outputFile)
1476-
err = addDirFiles(zipWriter, "", sourceDir, getExcludeFilters(filter), getIncludeFilters(userIncludeFilter))
1476+
1477+
// First check if the directory is empty or all files are filtered out
1478+
isEmpty, err := isDirEmpty(sourceDir, getExcludeFilters(filter), getIncludeFilters(userIncludeFilter))
14771479
if err != nil {
14781480
return "", err
14791481
}
1482+
1483+
// If directory is effectively empty, add a placeholder file
1484+
if isEmpty {
1485+
logger.PrintIfVerbose("Directory is empty or all files are filtered out, adding placeholder file")
1486+
f, err := zipWriter.Create(".container-scan")
1487+
if err != nil {
1488+
return "", errors.Wrapf(err, "Cannot create placeholder file in zip")
1489+
}
1490+
_, err = f.Write([]byte("1"))
1491+
if err != nil {
1492+
return "", errors.Wrapf(err, "Cannot write to placeholder file")
1493+
}
1494+
} else {
1495+
// Add directory files normally
1496+
err = addDirFiles(zipWriter, "", sourceDir, getExcludeFilters(filter), getIncludeFilters(userIncludeFilter))
1497+
if err != nil {
1498+
return "", err
1499+
}
1500+
}
1501+
14801502
if len(scaToolPath) > 0 && len(scaResolverResultsFile) > 0 {
14811503
err = addScaResults(zipWriter)
14821504
if err != nil {
14831505
return "", err
14841506
}
14851507
}
1508+
14861509
// Close the file
14871510
err = zipWriter.Close()
14881511
if err != nil {
@@ -1501,6 +1524,44 @@ func isSingleContainerScanTriggered() bool {
15011524
return len(scanTypeList) == 1 && scanTypeList[0] == commonParams.ContainersType
15021525
}
15031526

1527+
// isDirEmpty checks if a directory is empty or if all files are filtered out
1528+
func isDirEmpty(dir string, excludeFilters, includeFilters []string) (bool, error) {
1529+
empty := true
1530+
1531+
err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
1532+
if err != nil {
1533+
return err
1534+
}
1535+
1536+
// Skip the root directory itself
1537+
if path == dir {
1538+
return nil
1539+
}
1540+
1541+
// Skip directories
1542+
if info.IsDir() {
1543+
return nil
1544+
}
1545+
1546+
// Get relative path
1547+
relPath, err := filepath.Rel(dir, path)
1548+
if err != nil {
1549+
return err
1550+
}
1551+
1552+
// Check if file passes filters
1553+
filename := filepath.Base(relPath)
1554+
if filterMatched(includeFilters, filename) && filterMatched(excludeFilters, filename) {
1555+
empty = false
1556+
return filepath.SkipAll // We found at least one file that will be included
1557+
}
1558+
1559+
return nil
1560+
})
1561+
1562+
return empty, err
1563+
}
1564+
15041565
func getIncludeFilters(userIncludeFilter string) []string {
15051566
return buildFilters(commonParams.BaseIncludeFilters, userIncludeFilter)
15061567
}
@@ -1836,17 +1897,6 @@ func getUploadURLFromSource(cmd *cobra.Command, uploadsWrapper wrappers.UploadsW
18361897
logger.PrintIfVerbose("Single container scan triggered: compressing only the container resolution file")
18371898
containerResolutionFilePath := filepath.Join(directoryPath, ".checkmarx", "containers", containerResolutionFileName)
18381899
zipFilePath, dirPathErr = util.CompressFile(containerResolutionFilePath, containerResolutionFileName, directoryCreationPrefix)
1839-
} else if isSingleContainerScanTriggered() && containerImagesFlag != "" {
1840-
logger.PrintIfVerbose("Single container scan with external images: creating minimal zip file")
1841-
// For container scans with external images, we need to create a minimal zip file
1842-
// since the API requires an upload URL even for container-only scans
1843-
zipFilePath, dirPathErr = createMinimalZipFile()
1844-
if unzip {
1845-
dirRemovalErr := cleanTempUnzipDirectory(directoryPath)
1846-
if dirRemovalErr != nil {
1847-
return "", "", dirRemovalErr
1848-
}
1849-
}
18501900
} else {
18511901
if !isSbom {
18521902
zipFilePath, dirPathErr = compressFolder(directoryPath, sourceDirFilter, userIncludeFilter, scaResolver)
@@ -3239,33 +3289,6 @@ func parseArgs(input string) []string {
32393289
return args
32403290
}
32413291

3242-
// createMinimalZipFile creates a minimal zip file for container scans with external images
3243-
// The API requires an upload URL even for container-only scans, so we create a minimal placeholder
3244-
func createMinimalZipFile() (string, error) {
3245-
outputFile, err := os.CreateTemp(os.TempDir(), "cx-container-*.zip")
3246-
if err != nil {
3247-
return "", errors.Wrapf(err, "Cannot create temp file for container-only scan")
3248-
}
3249-
defer outputFile.Close()
3250-
3251-
zipWriter := zip.NewWriter(outputFile)
3252-
defer zipWriter.Close()
3253-
3254-
// Create a minimal placeholder file
3255-
f, err := zipWriter.Create(".container-scan")
3256-
if err != nil {
3257-
return "", errors.Wrapf(err, "Cannot create placeholder file in zip")
3258-
}
3259-
3260-
// Write minimal content (just a single byte)
3261-
_, err = f.Write([]byte("1"))
3262-
if err != nil {
3263-
return "", errors.Wrapf(err, "Cannot write to placeholder file")
3264-
}
3265-
3266-
return outputFile.Name(), nil
3267-
}
3268-
32693292
func isValidJSONOrXML(path string) (bool, error) {
32703293
ext := strings.ToLower(filepath.Ext(path))
32713294
if ext != jsonExt && ext != xmlExt {

0 commit comments

Comments
 (0)