NOTE: When using Trivy, it will download a Vulnerability DB, Java Index DB, and Checks Bundle during every run. This quickly triggers rate-limiting errors. The script below will pre-cache the DB's every 24 hours, to ensure that excessive MegaLinter scans do not trigger rate-limiting.
#!/usr/bin/env bash
#
# MegaLinter via Docker CLI
# https://megalinter.io/latest/install-docker/
#
# Run in directory with mega-linter.yml: megalinter
# Run a specific version of MegaLinter: megalinter v8
#
# shellcheck disable=SC2034
export MEGALINTER_IMAGE="${MEGALINTER_IMAGE:-"oxsecurity/megalinter"}"
export MEGALINTER_VERSION="${MEGALINTER_VERSION:-"v8"}"
trivy_cache_primer() {
TRIVY_CACHE_DIR="${HOME:-/tmp/lint}/.cache/trivy"
_CACHE_TIMER="_cache-timer"
_TRIVY_DB_REPO="public.ecr.aws/aquasecurity/trivy-db:2"
_TRIVY_JAVA_DB_REPO="public.ecr.aws/aquasecurity/trivy-java-db:1"
_TRIVY_CHECKS_REPO="ghcr.io/aquasecurity/trivy-checks:1"
_TRIVY_DB_CACHE_PATH="${TRIVY_CACHE_DIR}/db"
_TRIVY_JAVA_DB_CACHE_PATH="${TRIVY_CACHE_DIR}/java-db"
_TRIVY_CHECKS_CACHE_PATH="${TRIVY_CACHE_DIR}/checks"
# Create cache directory, if it doesn't exist.
[[ ! -d "$TRIVY_CACHE_DIR" ]] && mkdir -p "$TRIVY_CACHE_DIR"
# Delete outdated cache-timers.
find "$TRIVY_CACHE_DIR" -name "*$_CACHE_TIMER" -type f -mmin +1440 -delete
# Trivy Vulnerability DB
# If cache-timer doesn't exist, or cache is empty, prime the cache.
if [[ ! -e "${_TRIVY_DB_CACHE_PATH}${_CACHE_TIMER}" ]] || [[ -z "$(ls -A "$_TRIVY_DB_CACHE_PATH")" ]]; then
rm -rf "$_TRIVY_DB_CACHE_PATH" "${_TRIVY_DB_CACHE_PATH}${_CACHE_TIMER}"
mkdir -p "$_TRIVY_DB_CACHE_PATH"
(
cd "$TRIVY_CACHE_DIR" || echo ""
echo "Pulling Trivy Vulnerability DB and storing in cache."
oras pull "$_TRIVY_DB_REPO" &&
tar -xzf db.tar.gz -C "$_TRIVY_DB_CACHE_PATH" &&
rm -f db.tar.gz
)
# Reset the cache-timer, if cache is not empty.
[[ -n "$(ls -A "$_TRIVY_DB_CACHE_PATH")" ]] && touch "${_TRIVY_DB_CACHE_PATH}${_CACHE_TIMER}"
fi
# Trivy Java Index DB
# If cache-timer doesn't exist, or cache is empty, prime the cache.
if [[ ! -e "${_TRIVY_JAVA_DB_CACHE_PATH}${_CACHE_TIMER}" ]] || [[ -z "$(ls -A "$_TRIVY_JAVA_DB_CACHE_PATH")" ]]; then
rm -rf "$_TRIVY_JAVA_DB_CACHE_PATH" "${_TRIVY_JAVA_DB_CACHE_PATH}${_CACHE_TIMER}"
mkdir -p "$_TRIVY_JAVA_DB_CACHE_PATH"
(
cd "$TRIVY_CACHE_DIR" || echo ""
echo "Pulling Trivy Java Index DB and storing in cache."
oras pull "$_TRIVY_JAVA_DB_REPO" &&
tar -xzf javadb.tar.gz -C "$_TRIVY_JAVA_DB_CACHE_PATH" &&
rm -f javadb.tar.gz
)
# Reset the cache-timer, if cache is not empty.
[[ -n "$(ls -A "$_TRIVY_JAVA_DB_CACHE_PATH")" ]] && touch "${_TRIVY_JAVA_DB_CACHE_PATH}${_CACHE_TIMER}"
fi
# Trivy Checks Bundle
# If cache-timer doesn't exist, or cache is empty, prime the cache.
if [[ ! -e "${_TRIVY_CHECKS_CACHE_PATH}${_CACHE_TIMER}" ]] || [[ -z "$(ls -A "$_TRIVY_CHECKS_CACHE_PATH")" ]]; then
rm -rf "$_TRIVY_CHECKS_CACHE_PATH" "${_TRIVY_CHECKS_CACHE_PATH}${_CACHE_TIMER}"
mkdir -p "$_TRIVY_CHECKS_CACHE_PATH"
(
cd "$TRIVY_CACHE_DIR" || echo ""
echo "Pulling Trivy Checks Bundle and storing in cache."
oras pull "$_TRIVY_CHECKS_REPO" &&
tar -xzf bundle.tar.gz -C "$_TRIVY_CHECKS_CACHE_PATH" &&
rm -f bundle.tar.gz
)
# Reset the cache-timer, if cache is not empty.
[[ -n "$(ls -A "$_TRIVY_CHECKS_CACHE_PATH")" ]] && touch "${_TRIVY_CHECKS_CACHE_PATH}${_CACHE_TIMER}"
fi
# output cache file list for debugging.
echo "Contents of Trivy cache directory: $TRIVY_CACHE_DIR"
ls -lahF "$TRIVY_CACHE_DIR"
}
main() {
if [ "$(whoami)" == "runner" ]; then
: # echo "Don't execute in GitHub Actions workflow runs."
else
trivy_cache_primer
# Clean up previous reports directory.
[[ -d "$(pwd)/megalinter-reports" ]] && rm -rf "$(pwd)/megalinter-reports"
# Run MegaLinter with cache enabled.
local OPTS=()
OPTS+=(--rm)
# OPTS+=(-q)
[[ -t 0 ]] && OPTS+=(-it) # terminal
[[ -e ~/.ssh/config_shared ]] && OPTS+=(-v ~/.ssh/config_shared:/root/.ssh/config)
[[ -e ~/.ssh/id_rsa_shared ]] && OPTS+=(-v ~/.ssh/id_rsa_shared:/root/.ssh/id_rsa_shared)
OPTS+=(-v /var/run/docker.sock:/var/run/docker.sock:rw)
OPTS+=(-v "$(pwd):/tmp/lint:rw")
OPTS+=(-v "$HOME/.cache/trivy:/tmp/megalinter/.cache/trivy:rw")
OPTS+=(-e "TRIVY_CACHE_DIR=/tmp/megalinter/.cache/trivy")
OPTS+=(-e "TRIVY_SKIP_DB_UPDATE=true")
OPTS+=(-e "TRIVY_SKIP_JAVA_DB_UPDATE=true")
OPTS+=(-e "TRIVY_SKIP_CHECK_UPDATE=true")
OPTS+=(--name "${PWD##*/}-megalinter-${MEGALINTER_VERSION}")
docker run "${OPTS[@]}" "${MEGALINTER_IMAGE}:${MEGALINTER_VERSION}" "$@"
fi
}
main "$@"
---
# Configuration file for MegaLinter
# See all available variables at https://megalinter.io/configuration/ and in linters documentation
# Activates formatting and auto-fixing
APPLY_FIXES: none
# https://megalinter.io/latest/supported-linters/
# If you use ENABLE variable, all other languages/formats/tooling formats will be disabled by default
ENABLE:
- BASH
# - CLOUDFORMATION
# - CSS
- DOCKERFILE
- ENV
# - GHERKIN
# - HTML
- JAVASCRIPT
- JSON
# - KUBERNETES
- MARKDOWN
# - OPENAPI
- PYTHON
- REPOSITORY
- TERRAFORM
# - XML
- YAML
DISABLE_LINTERS:
- JAVASCRIPT_STANDARD
- JSON_PRETTIER
- KUBERNETES_KUBEVAL
- MARKDOWN_MARKDOWN_LINK_CHECK
- MARKDOWN_REMARK_LINT
# - PYTHON_BLACK
- PYTHON_FLAKE8
- PYTHON_ISORT
- PYTHON_MYPY
- PYTHON_PYRIGHT
- PYTHON_RUFF
# - REPOSITORY_CHECKOV
- REPOSITORY_DEVSKIM
- REPOSITORY_DUSTILOCK
- REPOSITORY_GOODCHECK
- REPOSITORY_GRYPE
# - REPOSITORY_KICS
- REPOSITORY_SEMGREP
- REPOSITORY_SYFT
- REPOSITORY_TRUFFLEHOG
- TERRAFORM_TERRASCAN
BASH_EXEC_FILE_EXTENSIONS: ['']
BASH_EXEC_FILTER_REGEX_INCLUDE: '(bin/*|scripts/*)'
BASH_SHELLCHECK_FILE_EXTENSIONS: ['', '.sh', '.bash', '.dash', '.ksh']
BASH_SHELLCHECK_FILTER_REGEX_EXCLUDE: '.gitkeep'
BASH_SHELLCHECK_FILTER_REGEX_INCLUDE: '(bin/*|scripts/*)'
BASH_SHFMT_FILE_EXTENSIONS: ['', '.sh', '.bash', '.dash', '.ksh']
BASH_SHFMT_FILTER_REGEX_EXCLUDE: '.gitkeep'
BASH_SHFMT_FILTER_REGEX_INCLUDE: '(bin/*|scripts/*)'
EXCLUDED_DIRECTORIES: ['.git', '.terraform', 'megalinter-reports', 'node_modules']
FLAVOR_SUGGESTIONS: false
FORMATTERS_DISABLE_ERRORS: false
JSON_JSONLINT_FILTER_REGEX_EXCLUDE: '(\.devcontainer/|\.vscode/)'
MARKDOWN_MARKDOWN_LINK_CHECK_DISABLE_ERRORS: true
MARKDOWN_MARKDOWNLINT_FILTER_REGEX_EXCLUDE: '(CHANGELOG.md)'
PRINT_ALL_FILES: false
PRINT_ALPACA: false
PYTHON_PYLINT_CONFIG_FILE: pyproject.toml
PYTHON_PYLINT_ARGUMENTS: '--fail-under=0 --fail-on=E'
PYTHON_BANDIT_CONFIG_FILE: pyproject.toml
PYTHON_BANDIT_PRE_COMMANDS:
- command: 'pip install bandit[toml]'
cwd: 'workspace'
REPORTERS_MARKDOWN_TYPE: simple
REPOSITORY_CHECKOV_ARGUMENTS: ['--check', 'HIGH', '--skip-check', 'MEDIUM']
REPOSITORY_KICS_ARGUMENTS: '--exclude-severities info,low'
REPOSITORY_TRIVY_ARGUMENTS:
- '--db-repository'
- 'public.ecr.aws/aquasecurity/trivy-db:2'
- '--java-db-repository'
- 'public.ecr.aws/aquasecurity/trivy-java-db:1'
- '--skip-dirs'
- '.devcontainer'
- '--skip-dirs'
- '.terraform'
- '--skip-dirs'
- 'megalinter-reports'
- '--skip-dirs'
- 'node_modules'
SHOW_ELAPSED_TIME: true
SHOW_SKIPPED_LINTERS: false
YAML_PRETTIER_FILTER_REGEX_EXCLUDE: '(\.github/workflows)'
YAML_YAMLLINT_FILTER_REGEX_EXCLUDE: '(\.github/workflows)'