Sorry, couldn’t find a better title.

Anyway, recently i found myself in a situation where i had to do some security checks on all the projects made in a company.

They use gitlab.com to host the source code of their software and, opening random repos, i noticed some bad practice (in this case i found hardcoded in clear some secret token/key/so on…).

Because the projects are quite a few i built the following bash script to download all the repos and run DeepSecrets on them.

#!/bin/bash
# Author: Antonio D'Angelo
# Url: https://github.com/well-it-wasnt-me/GitLab-Security-Check
# Function to check if a command is installed
check_command() {
    command -v "$1" >/dev/null 2>&1
}
# Function to install a package using Homebrew on macOS
install_with_brew() {
    brew install "$1"
}
# Function to install a package using APT on Debian-based systems
install_with_apt() {
    sudo apt-get update
    sudo apt-get install -y "$1"
}
# Function to install a package using DNF on Fedora
install_with_dnf() {
    sudo dnf install -y "$1"
}
# Function to install a package using Pacman on Arch Linux
install_with_pacman() {
    sudo pacman -Syu --noconfirm "$1"
}
# Function to install deepsecrets using pip
install_deepsecrets() {
    pip install deepsecrets
}
# Check and install dependencies
echo "Checking dependencies..."
# jq
if ! check_command "jq"; then
    echo "jq is not installed. Installing..."
    if [ "$(uname)" == "Darwin" ]; then
        install_with_brew "jq"
    elif [ "$(expr substr $(uname -s) 1 5)" == "Linux" ]; then
        if command -v apt-get &> /dev/null; then
            install_with_apt "jq"
        elif command -v dnf &> /dev/null; then
            install_with_dnf "jq"
        elif command -v pacman &> /dev/null; then
            install_with_pacman "jq"
        else
            echo "Unsupported package manager. Please install jq manually."
            exit 1
        fi
    else
        echo "Unsupported operating system. Please install jq manually."
        exit 1
    fi
fi
# Check and install Python 3
if ! check_command "python3"; then
    echo "Python 3 is not installed. Installing..."
    install_with_brew "python" # This may need to be adjusted based on the user's system
    curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
    python3 get-pip.py
    rm get-pip.py
fi
# Check and install pip
if ! check_command "pip"; then
    echo "pip is not installed. Installing..."
    install_with_brew "python" # This may need to be adjusted based on the user's system
    curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
    python3 get-pip.py
    rm get-pip.py
fi
# Check and install deepsecrets
if ! check_command "deepsecrets"; then
    echo "deepsecrets is not installed. Installing..."
    install_deepsecrets
fi
# Check and install git
if ! check_command "git"; then
    echo "git is not installed. Installing..."
    install_git
fi
# Prompt user for GitLab personal access token
read -s -p "Enter your GitLab personal access token: " GITLAB_ACCESS_TOKEN
# GitLab API URL to get the list of groups associated with the access token
GROUPS_API_URL="https://gitlab.com/api/v4/groups?private_token=$GITLAB_ACCESS_TOKEN"
# Fetching groups
groups=$(curl -s "$GROUPS_API_URL" | jq -r '.[] | "\(.id) \(.path) \(.name)"')
# Check if groups is null or empty
if [ -z "$groups" ] || [ "$groups" == "null" ]; then
    echo "Error fetching GitLab groups. Please check your GitLab Access Token."
    exit 1
fi
# Display available groups for selection
echo "Available GitLab Groups:"
echo "$groups"
# Prompt user to choose a group
read -p "Enter the ID of the GitLab group you want to use: " GROUP_ID
# GitLab API URL to get the list of projects under the selected group
GROUP_API_URL="https://gitlab.com/api/v4/groups/$GROUP_ID/projects?private_token=$GITLAB_ACCESS_TOKEN"
# Folder to store all repositories
OUTPUT_FOLDER="gitlab_repositories"
# Clone all repositories using the git protocol
echo "Cloning Repositories..."
mkdir -p "$OUTPUT_FOLDER"
# Fetching repositories
repo_urls=$(curl -s "$GROUP_API_URL" | jq -r '.[].http_url_to_repo')
# Check if repo_urls is null or empty
if [ -z "$repo_urls" ] || [ "$repo_urls" == "null" ]; then
    echo "Error fetching repository URLs. Please check your GitLab Access Token and group ID."
    exit 1
fi
# Iterate over repo_urls and clone each repository
for repo_url in $repo_urls; do
    # Extract the repository name without the .git extension
    repo_name=$(basename "$repo_url" .git)
    # Extract the repo_url without the https:// prefix
    repo_url_without_protocol=${repo_url#*@}
    # Construct the repo URL with access token for HTTPS
    repo_url_with_token="https://oauth2:${GITLAB_ACCESS_TOKEN}@${repo_url_without_protocol}"
    # Remove any extra "https://" at the beginning or after the '@' symbol - i know...there is for sure some smarter way to handle this
    repo_url_with_token="${repo_url_with_token#https://}"
    repo_url_with_token="${repo_url_with_token/@https:\/\//@}"
    # Ensure "oauth2" has "https://" before it
    repo_url_with_token="${repo_url_with_token/oauth2/https://oauth2}"
    git clone "$repo_url_with_token" "$OUTPUT_FOLDER/$repo_name"
done
# Run deepsecrets for each repository
echo "Running deepsecrets..."
for repo_folder in "$OUTPUT_FOLDER"/*; do
    if [ -d "$repo_folder" ]; then
        repo_name=$(basename "$repo_folder")
        target_dir="$repo_folder"
        # Run deepsecrets
        deepsecrets --target-dir "$target_dir" --outfile "report-$repo_name.json"
        echo "Deepsecrets completed for $repo_name. Report saved to report-$repo_name.json"
    fi
done
echo "Task completed!"

I know, it has room for improvements. And i will improve it (not now). But at least does it’s work.

What you need

Everything is available on the official repo, that you use MacOS, Debian based distro or Arch doesn’t matter.

  • Homebrew (only if you are on MacOS)
  • Git
  • JQ
  • Python3
  • PIP
  • deepsecrets
  • GitLab Access Token with the following permissions: api, read_api, read_user, read_repository, write_repository

Do you like this ?

If you feel to show appreciation (leaving a star) or want to contribute to make this script better, feel free to go on https://github.com/antonio-dangelo/GitLab-Security-Check

Tips

  • If you use pipelines implement an additional check for checking eventual leaks.