Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ Downloads SBOMs from GitHub, Mend, and Wiz. Uploads to S3 and ClickHouse.
| merge | Merge SBOMs stored in S3 | false | false | false |
| include | Comma-separated list of filenames or patterns to include when merging | (empty) | false | false |
| exclude | Comma-separated list of filenames or patterns to exclude when merging | (empty) | false | false |
| debug | Enable debug logging | false | false | false |

- `sbom-format` specifies the format you want the final SBOM to be in. For example, GitHub only supports SPDX, settings this input to `cyclonedx` will convert the SBOM to CycloneDX format.
- `include` and `exclude` are only used when `merge` is set to `true`. They allow you to filter which files from the S3 bucket should be included in the merge operation.
Expand Down Expand Up @@ -219,7 +220,7 @@ jobs:

- name: Generate Token
id: generate-token
uses: actions/create-github-app-token@v1
uses: actions/create-github-app-token@v2
with:
app-id: ${{ secrets.CLICKBOM_AUTH_APP_ID }}
private-key: ${{ secrets.CLICKBOM_AUTH_PRIVATE_KEY }}
Expand Down Expand Up @@ -282,7 +283,7 @@ jobs:

- name: Generate Token
id: generate-token
uses: actions/create-github-app-token@v1
uses: actions/create-github-app-token@v2
with:
app-id: ${{ secrets.CLICKBOM_AUTH_APP_ID }}
private-key: ${{ secrets.CLICKBOM_AUTH_PRIVATE_KEY }}
Expand Down Expand Up @@ -346,7 +347,7 @@ jobs:

- name: Generate Token
id: generate-token
uses: actions/create-github-app-token@v1
uses: actions/create-github-app-token@v2
with:
app-id: ${{ secrets.CLICKBOM_AUTH_APP_ID }}
private-key: ${{ secrets.CLICKBOM_AUTH_PRIVATE_KEY }}
Expand Down Expand Up @@ -390,7 +391,7 @@ jobs:

- name: Generate Token
id: generate-token
uses: actions/create-github-app-token@v1
uses: actions/create-github-app-token@v2
with:
app-id: ${{ secrets.CLICKBOM_AUTH_APP_ID }}
private-key: ${{ secrets.CLICKBOM_AUTH_PRIVATE_KEY }}
Expand Down Expand Up @@ -444,7 +445,7 @@ jobs:

- name: Generate Token
id: generate-token
uses: actions/create-github-app-token@v1
uses: actions/create-github-app-token@v2
with:
app-id: ${{ secrets.CLICKBOM_AUTH_APP_ID }}
private-key: ${{ secrets.CLICKBOM_AUTH_PRIVATE_KEY }}
Expand Down
50 changes: 31 additions & 19 deletions entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -144,8 +144,10 @@ download_sbom() {

# Debug: Show first few lines of downloaded content
log_debug "First 200 characters of downloaded content:"
head -c 200 "$output_file" | tr '\n' ' ' | sed 's/[[:space:]]\+/ /g'
echo ""
if [[ "${DEBUG:-false}" == "true" ]]; then
head -c 200 "$output_file" | tr '\n' ' ' | sed 's/[[:space:]]\+/ /g'
echo ""
fi

# Quick validation that it's JSON
if ! jq . "$output_file" > /dev/null 2>&1; then
Expand Down Expand Up @@ -748,9 +750,11 @@ download_wiz_report_from_url() {

# Debug: Show what was extracted
log_debug "Extracted files:"
find "$extract_dir" -type f | while read -r file; do
log_debug " - $(basename "$file") ($(file -b "$file" 2>/dev/null || echo "unknown type"))"
done
if [[ "${DEBUG:-false}" == "true" ]]; then
find "$extract_dir" -type f | while read -r file; do
log_debug " - $(basename "$file") ($(file -b "$file" 2>/dev/null || echo "unknown type"))"
done
fi

# Find JSON files in the extracted content
local json_files
Expand Down Expand Up @@ -1159,10 +1163,12 @@ merge_cyclonedx_sboms() {

# Debug: Show raw S3 ls output
log_debug "Raw S3 listing for bucket: $S3_BUCKET"
if ! aws s3 ls "s3://$S3_BUCKET" --recursive; then
log_error "Failed to list files in S3 bucket: $S3_BUCKET"
log_error "Check bucket name and AWS permissions"
exit 1
if [[ "${DEBUG:-false}" == "true" ]]; then
if ! aws s3 ls "s3://$S3_BUCKET" --recursive; then
log_error "Failed to list files in S3 bucket: $S3_BUCKET"
log_error "Check bucket name and AWS permissions"
exit 1
fi
fi

# Extract JSON files (excluding vulns/ directory and target S3_KEY file)
Expand Down Expand Up @@ -1290,10 +1296,12 @@ merge_cyclonedx_sboms() {

# Debug: Show structure of the file to understand why it's not recognized
log_debug "File structure preview for $filename:"
if jq -r 'keys[]' "$local_file" 2>/dev/null | head -5; then
echo "Keys shown above"
else
echo "Unable to read keys from file"
if [[ "${DEBUG:-false}" == "true" ]]; then
if jq -r 'keys[]' "$local_file" 2>/dev/null | head -5; then
echo "Keys shown above"
else
echo "Unable to read keys from file"
fi
fi
fi
else
Expand Down Expand Up @@ -1593,12 +1601,14 @@ setup_clickhouse_table() {

# Test connection first
log_debug "Testing ClickHouse connection..."
if ! curl -s ${auth_params} --data "SELECT 1" "${clickhouse_url}" > /dev/null; then
log_error "ClickHouse connection test failed"
log_error "Please verify your ClickHouse credentials and URL"
return 1
if [[ "${DEBUG:-false}" == "true" ]]; then
if ! curl -s ${auth_params} --data "SELECT 1" "${clickhouse_url}" > /dev/null; then
log_error "ClickHouse connection test failed"
log_error "Please verify your ClickHouse credentials and URL"
return 1
fi
log_success "ClickHouse connection successful"
fi
log_success "ClickHouse connection successful"

# Check if table exists
local table_exists
Expand Down Expand Up @@ -1691,7 +1701,9 @@ insert_sbom_data() {
case "$sbom_format" in
"cyclonedx")
log_debug "Sample CycloneDX component with license:"
jq -r '.components[0] | {name: .name, version: .version, licenses: .licenses}' "$sbom_file" 2>/dev/null || echo "No components found"
if [[ "${DEBUG:-false}" == "true" ]]; then
jq -r '.components[0] | {name: .name, version: .version, licenses: .licenses}' "$sbom_file" 2>/dev/null || echo "No components found"
fi
# Extract from CycloneDX format
jq -r '
.components[]? // empty |
Expand Down
77 changes: 48 additions & 29 deletions lib/sanitize.sh
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,25 @@ sanitize_s3_key() {
echo "$sanitized"
}

# Sanitize UUID format (for Mend/Wiz IDs)
sanitize_uuid() {
local uuid="$1"
local field_name="$2"

# Remove any non-hex characters except hyphens
local sanitized
sanitized=$(echo "$uuid" | sed 's/[^a-fA-F0-9-]//g')

# Validate UUID format (loose validation - some services use non-standard formats)
if [[ ! "$sanitized" =~ ^[0-9a-fA-F]{8}-?([0-9a-fA-F]{4}-?){3}[0-9a-fA-F]{12}$ ]]; then
log_error "Invalid UUID format for $field_name: $uuid"
log_error "UUID must contain only hexadecimal characters and hyphens"
exit 1
fi

echo "$sanitized"
}

# Main sanitization function - sanitizes all environment variables
sanitize_inputs() {
log_debug "Sanitizing input parameters..."
Expand All @@ -149,44 +168,44 @@ sanitize_inputs() {
log_debug "Sanitized MEND_BASE_URL: $MEND_BASE_URL"
fi

# if [[ -n "${MEND_ORG_UUID:-}" ]]; then
# MEND_ORG_UUID=$(sanitize_uuid "$MEND_ORG_UUID" "MEND_ORG_UUID")
# log_debug "Sanitized MEND_ORG_UUID: $MEND_ORG_UUID"
# fi
if [[ -n "${MEND_ORG_UUID:-}" ]]; then
MEND_ORG_UUID=$(sanitize_uuid "$MEND_ORG_UUID" "MEND_ORG_UUID")
log_debug "Sanitized MEND_ORG_UUID: $MEND_ORG_UUID"
fi

if [[ -n "${MEND_USER_KEY:-}" ]]; then
MEND_USER_KEY=$(sanitize_string "$MEND_USER_KEY" 500)
log_debug "Sanitized MEND_USER_KEY: [REDACTED]"
fi

# if [[ -n "${MEND_PROJECT_UUID:-}" ]]; then
# MEND_PROJECT_UUID=$(sanitize_uuid "$MEND_PROJECT_UUID" "MEND_PROJECT_UUID")
# log_debug "Sanitized MEND_PROJECT_UUID: $MEND_PROJECT_UUID"
# fi
if [[ -n "${MEND_PROJECT_UUID:-}" ]]; then
MEND_PROJECT_UUID=$(sanitize_uuid "$MEND_PROJECT_UUID" "MEND_PROJECT_UUID")
log_debug "Sanitized MEND_PROJECT_UUID: $MEND_PROJECT_UUID"
fi

# if [[ -n "${MEND_PRODUCT_UUID:-}" ]]; then
# MEND_PRODUCT_UUID=$(sanitize_uuid "$MEND_PRODUCT_UUID" "MEND_PRODUCT_UUID")
# log_debug "Sanitized MEND_PRODUCT_UUID: $MEND_PRODUCT_UUID"
# fi
if [[ -n "${MEND_PRODUCT_UUID:-}" ]]; then
MEND_PRODUCT_UUID=$(sanitize_uuid "$MEND_PRODUCT_UUID" "MEND_PRODUCT_UUID")
log_debug "Sanitized MEND_PRODUCT_UUID: $MEND_PRODUCT_UUID"
fi

# if [[ -n "${MEND_ORG_SCOPE_UUID:-}" ]]; then
# MEND_ORG_SCOPE_UUID=$(sanitize_uuid "$MEND_ORG_SCOPE_UUID" "MEND_ORG_SCOPE_UUID")
# log_debug "Sanitized MEND_ORG_SCOPE_UUID: $MEND_ORG_SCOPE_UUID"
# fi
if [[ -n "${MEND_ORG_SCOPE_UUID:-}" ]]; then
MEND_ORG_SCOPE_UUID=$(sanitize_uuid "$MEND_ORG_SCOPE_UUID" "MEND_ORG_SCOPE_UUID")
log_debug "Sanitized MEND_ORG_SCOPE_UUID: $MEND_ORG_SCOPE_UUID"
fi

# if [[ -n "${MEND_PROJECT_UUIDS:-}" ]]; then
# # Split by comma and sanitize each UUID
# local sanitized_uuids=()
# IFS=',' read -ra uuid_array <<< "$MEND_PROJECT_UUIDS"
# for uuid in "${uuid_array[@]}"; do
# uuid=$(echo "$uuid" | xargs) # trim whitespace
# if [[ -n "$uuid" ]]; then
# sanitized_uuids+=($(sanitize_uuid "$uuid" "MEND_PROJECT_UUIDS"))
# fi
# done
# MEND_PROJECT_UUIDS=$(IFS=','; echo "${sanitized_uuids[*]}")
# log_debug "Sanitized MEND_PROJECT_UUIDS: $MEND_PROJECT_UUIDS"
# fi
if [[ -n "${MEND_PROJECT_UUIDS:-}" ]]; then
# Split by comma and sanitize each UUID
local sanitized_uuids=()
IFS=',' read -ra uuid_array <<< "$MEND_PROJECT_UUIDS"
for uuid in "${uuid_array[@]}"; do
uuid=$(echo "$uuid" | xargs) # trim whitespace
if [[ -n "$uuid" ]]; then
sanitized_uuids+=($(sanitize_uuid "$uuid" "MEND_PROJECT_UUIDS"))
fi
done
MEND_PROJECT_UUIDS=$(IFS=','; echo "${sanitized_uuids[*]}")
log_debug "Sanitized MEND_PROJECT_UUIDS: $MEND_PROJECT_UUIDS"
fi

# if [[ -n "${MEND_MAX_WAIT_TIME:-}" ]]; then
# MEND_MAX_WAIT_TIME=$(sanitize_numeric "$MEND_MAX_WAIT_TIME" "MEND_MAX_WAIT_TIME" 60 7200)
Expand Down
2 changes: 2 additions & 0 deletions license-mappings.json
Original file line number Diff line number Diff line change
Expand Up @@ -115,11 +115,13 @@
"github.com/BurntSushi/toml": "MIT",
"github.com/cenkalti/backoff/v4": "MIT",
"github.com/ClickHouse/ch-go": "Apache-2.0",
"github.com/ClickHouse/clickhouse-go/v2": "Apache-2.0",
"github.com/containerd/errdefs": "Apache-2.0",
"github.com/containerd/errdefs/pkg": "Apache-2.0",
"github.com/containerd/log": "Apache-2.0",
"github.com/containerd/platforms": "Apache-2.0",
"github.com/cpuguy83/dockercfg": "MIT",
"github.com/Crocmagnon/fatcontext": "MIT",
"github.com/davecgh/go-spew": "ISC",
"github.com/distribution/reference": "Apache-2.0",
"github.com/docker/docker": "Apache-2.0",
Expand Down
43 changes: 43 additions & 0 deletions test/simple.bats
Original file line number Diff line number Diff line change
Expand Up @@ -573,3 +573,46 @@ EOF
[ "$status" -eq 1 ]
[[ "$output" == *"Invalid S3 key"* ]]
}

# Test 60: sanitize_uuid accepts valid UUID
@test "sanitize_uuid accepts valid UUID" {
run sanitize_uuid "123e4567-e89b-12d3-a456-426614174000" "TEST_UUID"
[ "$status" -eq 0 ]
[[ "$output" == "123e4567-e89b-12d3-a456-426614174000" ]]
}

# Test 61: sanitize_uuid accepts UUID without hyphens
@test "sanitize_uuid accepts UUID without hyphens" {
run sanitize_uuid "123e4567e89b12d3a456426614174000" "TEST_UUID"
[ "$status" -eq 0 ]
[[ "$output" == "123e4567e89b12d3a456426614174000" ]]
}

# Test 62: sanitize_uuid accepts UUID with uppercase letters
@test "sanitize_uuid accepts uppercase UUID" {
run sanitize_uuid "123E4567-E89B-12D3-A456-426614174000" "TEST_UUID"
[ "$status" -eq 0 ]
[[ "$output" == "123E4567-E89B-12D3-A456-426614174000" ]]
}

# Test 63: sanitize_uuid removes invalid characters
@test "sanitize_uuid removes invalid characters" {
run sanitize_uuid "123e4567-e89b-12d3-a456-426614174000!@#" "TEST_UUID"
[ "$status" -eq 0 ]
[[ "$output" == "123e4567-e89b-12d3-a456-426614174000" ]]
}

# Test 64: sanitize_uuid rejects too short UUID
@test "sanitize_uuid rejects too short UUID" {
run sanitize_uuid "123" "TEST_UUID"
[ "$status" -eq 1 ]
[[ "$output" == *"Invalid UUID format for TEST_UUID"* ]]
}

# Test 65: sanitize_uuid rejects non-hex characters
@test "sanitize_uuid rejects non-hex characters" {
run sanitize_uuid "123g45678-e89b-12d3-a456-426614174000" "TEST_UUID"
echo "$output"
[ "$status" -eq 0 ]
[[ "$output" == "12345678-e89b-12d3-a456-426614174000" ]]
}