Skip to content

Conversation

@cx-shaked-karta
Copy link
Contributor

Summary

This PR fixes the container-images flag to support Syft-compatible prefix syntax while restricting scanning to single images only.

Changes Made

✅ Added Prefix Syntax Support

  • docker:image:tag - Docker daemon images
  • podman:image:tag - Podman daemon images
  • containerd:image:tag - Containerd daemon images
  • registry:image:tag - Registry images (restricted to single images)
  • docker-archive:file.tar - Docker archive files
  • oci-archive:file.tar - OCI archive files
  • oci-dir:/path/to/dir - OCI directory layout (supports files and directories)
  • file:/path/to/file - Single files

🚫 Added Restrictions

  • Blocked dir: prefix - Prevents scanning entire directories
  • Registry validation - Prevents scanning entire registries without specific images
  • Single image enforcement - Each comma-separated entry must be a single image

🗑️ Removed Features

  • Removed singularity support - No longer supported

🧪 Testing

  • Added 30+ comprehensive test cases covering all scenarios
  • Validates both positive and negative cases
  • Tests comma-separated image lists with mixed valid/invalid entries

Backward Compatibility

  • ✅ Traditional image:tag format still works
  • ✅ Legacy .tar files still supported
  • ✅ Comma-separated lists still work (each entry validated individually)

Example Usage

# ✅ Multiple single images (allowed)
--container-images "docker:nginx:latest,podman:test:latest,registry:ubuntu:20.04"

# 🚫 Bulk scanning (blocked)
--container-images "dir:/path/to/directory"  # Blocked
--container-images "registry:myregistry.com"  # Blocked

Fixes: https://checkmarx.atlassian.net/browse/AST-108903

@github-actions
Copy link

github-actions bot commented Sep 29, 2025

Logo
Checkmarx One – Scan Summary & Detailsb3c00b05-b1d1-46af-b09c-6e2d4d9543f6

Great job! No new security vulnerabilities introduced in this pull request

@cx-shaked-karta cx-shaked-karta changed the title Fix container-images flag to support prefix syntax and restrict to single images (AST-108903) Fix container-images flag to support prefix syntax advanced parsing (AST-108903) Oct 9, 2025
Copy link
Collaborator

@cx-anurag-dalke cx-anurag-dalke left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

@cx-shaked-karta
Copy link
Contributor Author

🔄 Update: Automatic Local Resolution for Tar Files

Added automatic enforcement of --containers-local-resolution when tar files are detected in --container-images flag.

New Behavior

When using --container-images with tar file(s):

  • ✅ If --containers-local-resolution is already set → No action taken
  • ⚠️ If --containers-local-resolution is not set → Automatically enabled with warning message

Implementation Details

New Functions:

  • isTarFileReference() - Detects tar file references with support for:

    • Simple tar files: image.tar
    • Prefixed tar files: docker-archive:alpine.tar, oci-archive:image.tar, file:myimage.tar
    • Quoted paths: 'alpine.tar', "image.tar"
    • Case-insensitive detection: image.TAR
    • ✅ Validates that tar files don't have invalid tag suffixes (e.g., file.tar:latest is rejected)
  • enforceLocalResolutionForTarFiles() - Automatically enables local resolution when tar files are detected

Warning Message:

Warning: Tar file(s) detected in --container-images. Automatically enabling --containers-local-resolution flag.

Examples

# Tar file without --containers-local-resolution
# → Warning printed, flag auto-enabled
cx scan create --container-images "alpine.tar" -s . --project-name test

# Tar file with --containers-local-resolution already set
# → No warning, proceeds normally
cx scan create --container-images "alpine.tar" --containers-local-resolution -s . --project-name test

# Mixed tar + regular images
# → Warning printed, flag auto-enabled for all
cx scan create --container-images "nginx:latest,alpine.tar,ubuntu:20.04" -s . --project-name test

Test Coverage

Added comprehensive test coverage:

  • 17 test cases in TestIsTarFileReference covering all tar file detection scenarios
  • 11 test cases in TestEnforceLocalResolutionForTarFiles validating flag enforcement
  • 4 integration test cases in TestEnforceLocalResolutionForTarFiles_Integration verifying end-to-end behavior

All tests passing ✅

@cx-shaked-karta
Copy link
Contributor Author

cx-shaked-karta commented Oct 12, 2025

🚀 Latest Updates - Complete OCI Directory Support & Advanced Image Processing

✨ Major New Features

1. Full OCI Directory Support (Skopeo Integration)

  • Tag extraction from index.json - Automatically reads org.opencontainers.image.ref.name annotation
  • Nested path support - Handles paths like docker.io/library/alpine
  • No explicit tag required - Tags embedded in OCI metadata, not CLI input
  • Multiple manifest handling - Uses first manifest's tag annotation
  • Comprehensive error handling - Skips images missing tag annotations with clear warnings

Example Usage:

# Create OCI directory with Skopeo
skopeo copy --override-arch amd64 docker://alpine:latest oci:docker.io/library/alpine:latest

# Scan with CxOne CLI (no tag in CLI command)
cx scan create --container-images "oci-dir:docker.io/library/alpine" --containers-local-resolution

2. Zero-Package Image Filtering

  • Automatic exclusion - Images with 0 packages automatically skipped
  • Clear warnings - Logs: "Image X has 0 packages, skipping from containers-resolution.json"
  • Corruption detection - Failed tar extractions excluded from results
  • 🎯 Benefit: Only images with analyzable content included in scan results

3. Enhanced Tar File Handling

  • Prefix stripping - Correctly strips file:, docker-archive:, oci-archive: before file operations
  • Metadata extraction - Reads manifest.json from tar files for accurate image name/tag
  • Improved logging - Better visibility into tar file processing
  • Error resilience - Graceful handling of corrupted or invalid tar files

4. Automatic Local Resolution for Tar Files

  • Smart detection - Automatically identifies tar files in --container-images
  • Auto-enable flag - Sets --containers-local-resolution when tar files detected
  • User warning - Clear message: "Warning: Tar file(s) detected in --container-images. Automatically enabling --containers-local-resolution flag."
  • No duplicate warnings - Silent if flag already set

🏗️ Architecture Improvements

Cross-Project Changes

ast-cli (internal/commands/scan.go):

  • Prefix validation with consistent constants
  • OCI directory path validation
  • Tar file auto-detection
  • Passes prefixed images directly to Syft (no stripping)

containers-resolver (pkg/containerResolver/containerScanner.go):

  • Orchestrates image analysis across projects
  • Platform-specific analysis (linux/amd64)
  • Result aggregation and filtering

containers-syft-packages-extractor (pkg/syftPackagesExtractor/utils.go):

  • Scheme source extraction for stereoscope compatibility
  • OCI directory metadata extraction
  • Tar file metadata extraction
  • Zero-package filtering
  • Conditional platform logging

🧪 Comprehensive Test Coverage

New Tests Added

containers-syft-packages-extractor:

  • TestExtractImageNameAndTagFromOCIDir (6 test cases)

    • Valid OCI dir with tag annotation
    • Multiple manifests handling
    • Nested path extraction
    • Missing annotation error handling
    • Empty manifests error handling
    • Invalid JSON error handling
  • TestIsTaggedImageFormat (11 test cases)

    • Standard images with tags
    • Daemon prefixes (docker, podman, containerd, registry)
    • Archive prefixes (oci-dir, oci-archive, docker-archive, file)
    • Tar files and images without tags

ast-cli:

  • ✅ 5 OCI-dir validation test cases in TestValidateContainerImageFormat_Comprehensive
  • ✅ 17 test cases in TestIsTarFileReference
  • ✅ 11 test cases in TestEnforceLocalResolutionForTarFiles
  • ✅ 4 integration test cases in TestEnforceLocalResolutionForTarFiles_Integration

All tests passing: ✅ 100% pass rate


📊 Processing Flow

User Input → CLI Validation → Normalization → Resolver → Syft Analysis → SBOM → Transform → Filter (0-pkg) → Save
   (CLI)      (scan.go)        (scan.go)      (resolver)  (syft-extractor)  (SBOM)  (utils.go)    (skip)      (JSON)

📝 Documentation Updates

  • Confluence page updated - Complete technical documentation with flow diagrams
  • Docker Save vs Skopeo OCI comparison table - Feature-by-feature comparison
  • Skopeo best practices - Step-by-step guides for all scenarios
  • Troubleshooting section - Common issues and solutions

📖 Documentation: Container Images Flag Validation Logic


🔧 Bug Fixes

  1. Fixed magic number linting - Replaced hardcoded 2 with minPartsForTaggedImage constant
  2. Fixed OCI-dir validation - Now allows directories without explicit tags
  3. Fixed prefix stripping - Correct handling across all image formats
  4. Fixed tar file paths - Proper prefix removal for file operations
  5. Fixed zero-package handling - Empty images no longer included in results

✅ Validation Examples

Valid Inputs:

# Standard images
--container-images "nginx:latest,alpine:3.18"

# OCI directories (tag from index.json)
--container-images "oci-dir:docker.io/library/alpine"
--container-images "oci-dir:./my-alpine-image"

# Tar files (with auto local-resolution)
--container-images "alpine.tar"
--container-images "file:./images/nginx.tar"
--container-images "docker-archive:saved-image.tar"

# Daemon sources
--container-images "docker:nginx:latest,podman:alpine:3.18"

# Mixed formats
--container-images "nginx:latest,oci-dir:./alpine,file:ubuntu.tar"

Invalid Inputs (with helpful errors):

# Missing tag
--container-images "nginx"
# ❌ Error: image does not have a tag

# OCI dir without tag annotation
--container-images "oci-dir:path/to/oci-dir"
# ⚠️ Warning: no image tag found in OCI index.json annotations (image skipped)

# Compressed tar
--container-images "image.tar.gz"
# ❌ Error: file is compressed, use non-compressed format (tar)

# OCI dir with explicit tag (NOT SUPPORTED)
--container-images "oci-dir:./my-image:latest"
# ❌ Will fail - tags must be in index.json, not CLI command

📈 Stats

  • +1,007 lines added
  • -51 lines removed
  • 5 files changed
  • 22 commits (latest: 0419c02)
  • 40+ test cases covering all scenarios
  • 0 linting errors

🔗 Related Links


Ready for review! ✅ All tests passing, documentation complete, zero linting issues.

Copy link
Collaborator

@cx-anurag-dalke cx-anurag-dalke left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

Checkmarx Automation added 16 commits October 13, 2025 17:07
…ngle images

- Add support for Syft-compatible prefix syntax (docker:, podman:, containerd:, registry:, docker-archive:, oci-archive:, oci-dir:, file:)
- Restrict scanning to single images only (prevent bulk directory/registry scanning)
- Remove singularity support
- Add comprehensive validation for all supported formats
- Maintain backward compatibility with traditional image:tag format

Fixes AST-108903
- Add helpful error message for .tar files with paths suggesting file: prefix
- Add specific filenames to file existence error messages
- Detect when users input file paths without proper prefix format
- Prevent customer confusion about format requirements

Examples:
- 'empty/alpine.tar' → suggests 'file:empty/alpine.tar'
- 'file:missing.tar' → shows 'file missing.tar does not exist' (not just 'file does not exist')

This addresses customer usability issues and makes error messages more actionable.
- Add transformContainerImagesForSyft function to strip file: prefix before passing to syft extractor
- Syft expects just the file path, not the file: prefix for local file sources
- Other prefixes (docker:, podman:, etc.) are passed through unchanged
- Fixes customer issue where file:empty/alpine.tar caused syft provider errors

This resolves the original panic and syft parsing issues reported in AST-108903.
- Replace simple prefix stripping with proper scheme extraction logic
- Mimic stereoscope.ExtractSchemeSource behavior exactly like syft CLI does
- Extract valid schemes (file:, docker:, registry:, etc.) and pass stripped input to syft
- Leave invalid or missing schemes unchanged (e.g., nginx:latest stays as-is)
- Supports all syft source provider schemes: file, dir, docker, podman, containerd, registry, docker-archive, oci-archive, oci-dir, singularity

This matches syft's exact behavior where both 'file:path' and 'path' work identically.
Resolves AST-108903 syft compatibility issues.
- Add isFilePath() function to detect file paths vs image references
- Automatically append ':latest' tag to file paths without tags
- Prevents 'index out of range' panic in containers-syft-packages-extractor
- Handles file extensions: .tar, .tar.gz, .tgz and paths with / or - Preserves existing tags when present (e.g., 'file.tar:v1.0' unchanged)

WORKAROUND for vendor library bug where it expects image:tag format
but file paths don't naturally have tags. Resolves AST-108903 panic issue.
The approach of adding ':latest' tags to file paths causes syft to look for
files with colons in the filename (e.g., 'empty/alpine.tar:latest' instead
of 'empty/alpine.tar').

Current status:
- ✅ Scheme extraction works correctly (file: prefix handling)
- ✅ Validation accepts file paths with and without schemes
- ❌ Vendor library panic still occurs for untagged file paths

WORKAROUND: Customers should add explicit tags to file paths:
  --container-images 'file:empty/alpine.tar:latest,file:empty/alpine.tar.gz:latest'

TODO: Fix vendor library panic at the appropriate layer (not in CLI processing)
… (AST-112118)

- Implement unified validation logic for all container image formats
  * Support for image:tag format with proper tag validation
  * Support for .tar files with existence checks
  * Detection and rejection of compressed tar files (.tar.gz, .tar.bz2, .tar.xz, .tgz)
  * Support for all syft/stereoscope prefixes (docker:, podman:, containerd:, registry:,
    docker-archive:, oci-archive:, oci-dir:, file:)
  * Explicit rejection of 'dir:' prefix to prevent directory scanning

- Consolidate validation error messages
  * Collect all validation errors before returning
  * Present errors in a single, user-friendly message with header and bullet points
  * Show both input and specific error for each failed validation

- Add helpful hints for common user mistakes
  * Detect compressed tar files and suggest using .tar format
  * Detect incorrect tar file extensions (e.g., .tar.bz) and ask if user meant to scan tar
  * Detect archive prefixes used with image names and suggest correct usage
  * Clear guidance on expected formats in error messages

- Improve input normalization
  * Trim spaces from comma-separated inputs
  * Strip single and double quotes from inputs
  * Handle quotes after prefixes (e.g., file:'/path/to/file')
  * Skip empty entries in comma-separated lists

- Add comprehensive test coverage
  * 40+ test cases covering all validation scenarios
  * Tests for all prefix types (daemon, archive, registry, oci-dir)
  * Tests for error cases with helpful hints
  * Tests for input normalization edge cases
  * Tests for quote handling and special characters

- Code cleanup
  * Remove obsolete validateTraditionalContainerImage function
  * Remove unused isFilePathForVendorLibrary helper
  * Improve code comments for clarity
  * Remove outdated TODO comments

- Update dependencies
  * Remove unused containers-resolver dependency from go.sum
…ata, while retaining build artifacts and manifest directories.
…n and helper functions

- Introduce comprehensive validation for container image formats, including image:tag, tar files, and various prefixes (docker:, podman:, etc.).
- Add detailed comments to clarify the purpose and functionality of key functions related to container image processing.
- Implement helper functions for prefix extraction and validation, improving code readability and maintainability.
- Ensure all new functions are aligned with container-security scan-type requirements.
…d maintainability

- Introduce dedicated validation functions for different container image prefixes: archive, oci-dir, registry, and daemon.
- Consolidate error handling and validation checks into specific functions to streamline the validation process.
- Enhance code clarity with detailed comments explaining the purpose of each validation function.
- Ensure all changes align with container-security scan-type requirements and improve overall code structure.
… validation

- Update error messages for clarity and consistency in the validateCreateScanFlags and validateRegistryPrefix functions.
- Replace hardcoded indices with named constants for better readability in the validateRegistryPrefix and validateDaemonPrefix functions.
- Enhance overall code maintainability by improving variable naming conventions.
- Update test assertions to check for consolidated error messages in the container image validation logic.
- Ensure error messages provide clearer feedback on user input errors, including specific issues with image tags and unsupported prefixes.
- Enhance test coverage for various error scenarios to improve robustness of validation checks.
Checkmarx Automation added 5 commits October 13, 2025 17:07
- Introduce `isTarFileReference` function to identify tar file references in container images.
- Implement `enforceLocalResolutionForTarFiles` function to automatically enable local resolution when tar files are detected in the `--container-images` flag.
- Enhance test coverage with new test cases for tar file detection and local resolution enforcement.
- Ensure integration with the scan create command to validate behavior with tar files.
- Replace magic number 2 with named constant minPartsForTaggedImage
- Fix tar file detection to reject invalid formats (e.g., file.tar:tag)
- Update test cases to reflect correct behavior (tar files cannot have tags)
- Add comprehensive test coverage for tar file detection and local resolution enforcement
- Allow oci-dir: prefix to reference directories without requiring tags
- Allow file:, docker-archive:, oci-archive: prefixes without tags
- Add comprehensive test coverage for oci-dir validation
- Fixes issue where skopeo-generated OCI directories were incorrectly rejected
- Test cases cover: oci-dir without tag, with tag, with tar files, missing directories

The OCI directory layout stores tag information internally, so requiring
a tag in the CLI input is incorrect. This fix allows commands like:
  cx scan create --container-images "oci-dir:my-alpine-image" ...
to work correctly with skopeo-generated OCI directories.
- Upgrade containers-resolver to v1.0.23 and containers-syft-packages-extractor to v1.0.19 in go.mod and go.sum.
- Refactor container image processing logic to pass images as-is to syft, removing the previous prefix-stripping functionality.
- Consolidate container image prefix constants for improved readability and maintainability.
- Enhance validation logic for container image formats by utilizing defined constants instead of hardcoded strings.
- Upgrade containers-resolver to v1.0.24 and containers-syft-packages-extractor to v1.0.20 in go.mod and go.sum for improved functionality and security.
Copy link
Collaborator

@cx-anurag-dalke cx-anurag-dalke left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

Copy link
Collaborator

@cx-anurag-dalke cx-anurag-dalke left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

@cx-anurag-dalke cx-anurag-dalke merged commit 9928345 into main Oct 14, 2025
8 of 9 checks passed
@cx-anurag-dalke cx-anurag-dalke deleted the bug/ast-108903 branch October 14, 2025 07:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants