From 9de74886b6d839c492de43e85c1f5c29e558b229 Mon Sep 17 00:00:00 2001 From: Sander Declerck Date: Fri, 13 Mar 2026 11:53:31 +0100 Subject: [PATCH 1/8] Implement Aikido Endpoint installation script --- install-scripts/install-endpoint-mac.sh | 130 ++++++++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 install-scripts/install-endpoint-mac.sh diff --git a/install-scripts/install-endpoint-mac.sh b/install-scripts/install-endpoint-mac.sh new file mode 100644 index 0000000..e44d854 --- /dev/null +++ b/install-scripts/install-endpoint-mac.sh @@ -0,0 +1,130 @@ +#!/bin/sh + +# Downloads and installs SafeChain Ultimate endpoint on macOS +# +# Usage: curl -fsSL | sudo sh -s -- --token + +set -e # Exit on error + +# Configuration +INSTALL_URL="https://github.com/AikidoSec/safechain-internals/releases/download/v1.2.4/SafeChainUltimate.pkg" +DOWNLOAD_SHA256="9c341c479e022cc98ddaeb704681a08c8eaacdcaa59e4256ecf90362af6a5514" +TOKEN_FILE="/tmp/aikido_endpoint_token.txt" + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +NC='\033[0m' # No Color + +# Helper functions +info() { + printf "${GREEN}[INFO]${NC} %s\n" "$1" +} + +error() { + printf "${RED}[ERROR]${NC} %s\n" "$1" >&2 + exit 1 +} + +# Download file +download() { + url="$1" + dest="$2" + + if command -v curl >/dev/null 2>&1; then + curl -fsSL "$url" -o "$dest" || error "Failed to download from $url" + elif command -v wget >/dev/null 2>&1; then + wget -q "$url" -O "$dest" || error "Failed to download from $url" + else + error "Neither curl nor wget found. Please install one of them." + fi +} + +# Verify SHA256 checksum +verify_checksum() { + file="$1" + expected="$2" + + actual=$(shasum -a 256 "$file" | awk '{ print $1 }') + + if [ "$actual" != "$expected" ]; then + error "Checksum verification failed. Expected: $expected, Got: $actual" + fi + + info "Checksum verified successfully." +} + +# Cleanup temporary files +cleanup() { + if [ -f "$PKG_FILE" ]; then + rm -f "$PKG_FILE" + fi + if [ -f "$TOKEN_FILE" ]; then + rm -f "$TOKEN_FILE" + fi +} + +# Parse command-line arguments +parse_arguments() { + TOKEN="" + + while [ $# -gt 0 ]; do + case "$1" in + --token) + if [ -z "${2:-}" ]; then + error "--token requires a value" + fi + TOKEN="$2" + shift 2 + ;; + *) + error "Unknown argument: $1" + ;; + esac + done +} + +# Main installation +main() { + parse_arguments "$@" + + # 1. Check if we're running on macOS + if [ "$(uname -s)" != "Darwin" ]; then + error "This script is only supported on macOS." + fi + + # Check if we're running as root + if [ "$(id -u)" -ne 0 ]; then + error "Root privileges required. Please run with sudo: sudo sh $0 --token " + fi + + # Prompt for token if not provided via CLI + if [ -z "$TOKEN" ]; then + printf "Enter your Aikido endpoint token: " + read -r TOKEN + if [ -z "$TOKEN" ]; then + error "Token is required. Pass it with --token or enter it when prompted." + fi + fi + + # 2. Download and verify checksum + PKG_FILE=$(mktemp /tmp/SafeChainUltimate.XXXXXX.pkg) + trap cleanup EXIT + + info "Downloading SafeChain Ultimate..." + download "$INSTALL_URL" "$PKG_FILE" + + info "Verifying checksum..." + verify_checksum "$PKG_FILE" "$DOWNLOAD_SHA256" + + # 3. Write token to file for the installer + printf "%s" "$TOKEN" > "$TOKEN_FILE" + + # 4. Install the package + info "Installing SafeChain Ultimate..." + installer -pkg "$PKG_FILE" -target / + + info "SafeChain Ultimate installed successfully!" +} + +main "$@" From b3d81d2f43a56dccc47626e88d180d8af5dfade7 Mon Sep 17 00:00:00 2001 From: Sander Declerck Date: Fri, 13 Mar 2026 11:58:44 +0100 Subject: [PATCH 2/8] Don't prompt for token --- install-scripts/install-endpoint-mac.sh | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/install-scripts/install-endpoint-mac.sh b/install-scripts/install-endpoint-mac.sh index e44d854..f13474d 100644 --- a/install-scripts/install-endpoint-mac.sh +++ b/install-scripts/install-endpoint-mac.sh @@ -95,16 +95,12 @@ main() { # Check if we're running as root if [ "$(id -u)" -ne 0 ]; then - error "Root privileges required. Please run with sudo: sudo sh $0 --token " + error "Root privileges required. Please re-run with sudo, e.g.: curl -fsSL | sudo sh -s -- --token " fi - # Prompt for token if not provided via CLI + # Check if token is provided via command argument if [ -z "$TOKEN" ]; then - printf "Enter your Aikido endpoint token: " - read -r TOKEN - if [ -z "$TOKEN" ]; then - error "Token is required. Pass it with --token or enter it when prompted." - fi + error "Token is required. Pass it with --token or enter it when prompted." fi # 2. Download and verify checksum From 5dfccaac9d0cbc249b039cdd62a5b48ad533f5b5 Mon Sep 17 00:00:00 2001 From: Sander Declerck Date: Fri, 13 Mar 2026 12:27:21 +0100 Subject: [PATCH 3/8] Update install url to arm64 pkg --- install-scripts/install-endpoint-mac.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/install-scripts/install-endpoint-mac.sh b/install-scripts/install-endpoint-mac.sh index f13474d..ebcf4aa 100644 --- a/install-scripts/install-endpoint-mac.sh +++ b/install-scripts/install-endpoint-mac.sh @@ -7,8 +7,8 @@ set -e # Exit on error # Configuration -INSTALL_URL="https://github.com/AikidoSec/safechain-internals/releases/download/v1.2.4/SafeChainUltimate.pkg" -DOWNLOAD_SHA256="9c341c479e022cc98ddaeb704681a08c8eaacdcaa59e4256ecf90362af6a5514" +INSTALL_URL="https://github.com/AikidoSec/safechain-internals/releases/download/v1.2.2/SafeChainUltimate-darwin-arm64.pkg" +DOWNLOAD_SHA256="779edc4d2fa367582bf9af6be30a0533fcd2a3490d921f834129719eb4f02f42" TOKEN_FILE="/tmp/aikido_endpoint_token.txt" # Colors for output From 7c5692f700c4c0cc18514859b43c62a0d64a9ef1 Mon Sep 17 00:00:00 2001 From: Sander Declerck Date: Fri, 13 Mar 2026 13:30:13 +0100 Subject: [PATCH 4/8] Update endpoint to 1.2.5 --- install-scripts/install-endpoint-mac.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/install-scripts/install-endpoint-mac.sh b/install-scripts/install-endpoint-mac.sh index ebcf4aa..8a0424d 100644 --- a/install-scripts/install-endpoint-mac.sh +++ b/install-scripts/install-endpoint-mac.sh @@ -7,8 +7,8 @@ set -e # Exit on error # Configuration -INSTALL_URL="https://github.com/AikidoSec/safechain-internals/releases/download/v1.2.2/SafeChainUltimate-darwin-arm64.pkg" -DOWNLOAD_SHA256="779edc4d2fa367582bf9af6be30a0533fcd2a3490d921f834129719eb4f02f42" +INSTALL_URL="https://github.com/AikidoSec/safechain-internals/releases/download/v1.2.5/SafeChainUltimate.pkg" +DOWNLOAD_SHA256="abc2b0e6c6a4ca33cd893eeb16744f9f2da90013fb1abac301f5c00c2ad8bc30" TOKEN_FILE="/tmp/aikido_endpoint_token.txt" # Colors for output From 4bf27ac2db6d8203e7e115061b7bd8494c338291 Mon Sep 17 00:00:00 2001 From: Sander Declerck Date: Fri, 13 Mar 2026 13:36:56 +0100 Subject: [PATCH 5/8] Add windows install script --- install-scripts/install-endpoint-windows.ps1 | 95 ++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 install-scripts/install-endpoint-windows.ps1 diff --git a/install-scripts/install-endpoint-windows.ps1 b/install-scripts/install-endpoint-windows.ps1 new file mode 100644 index 0000000..5c6eb3e --- /dev/null +++ b/install-scripts/install-endpoint-windows.ps1 @@ -0,0 +1,95 @@ +# Downloads and installs SafeChain Ultimate endpoint on Windows +# +# Usage: iex "& { $(iwr '' -UseBasicParsing) } -token " + +param( + [string]$token +) + +# Configuration +$InstallUrl = "https://github.com/AikidoSec/safechain-internals/releases/download/v1.2.5/SafeChainUltimate.msi" +$DownloadSha256 = "c4d1be7bb2128473b8e955244dc186b5d3f091f668b43cdd3d810cff9d38193c" + +# Ensure TLS 1.2 is enabled for downloads +[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 + +# Helper functions +function Write-Info { + param([string]$Message) + Write-Host "[INFO] $Message" -ForegroundColor Green +} + +function Write-Error-Custom { + param([string]$Message) + Write-Host "[ERROR] $Message" -ForegroundColor Red + exit 1 +} + +# Check if running as Administrator +function Test-Administrator { + $identity = [Security.Principal.WindowsIdentity]::GetCurrent() + $principal = New-Object Security.Principal.WindowsPrincipal($identity) + return $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) +} + +# Main installation +function Install-Endpoint { + # 1. Check if we're running as Administrator + if (-not (Test-Administrator)) { + Write-Error-Custom "Administrator privileges required. Please run this script in an elevated terminal (Run as Administrator)." + } + + # Check if token is provided, prompt if not + if ([string]::IsNullOrWhiteSpace($token)) { + $token = Read-Host "Enter your Aikido endpoint token" + if ([string]::IsNullOrWhiteSpace($token)) { + Write-Error-Custom "Token is required. Pass it with -token or enter it when prompted." + } + } + + # 2. Download the .msi + $msiFile = Join-Path $env:TEMP "SafeChainUltimate-$([System.Guid]::NewGuid().ToString('N')).msi" + + Write-Info "Downloading SafeChain Ultimate..." + try { + $ProgressPreference = 'SilentlyContinue' + Invoke-WebRequest -Uri $InstallUrl -OutFile $msiFile -UseBasicParsing + $ProgressPreference = 'Continue' + } + catch { + Write-Error-Custom "Failed to download from $InstallUrl : $_" + } + + try { + # Verify SHA256 checksum + Write-Info "Verifying checksum..." + $actualHash = (Get-FileHash -Path $msiFile -Algorithm SHA256).Hash.ToLower() + if ($actualHash -ne $DownloadSha256) { + Write-Error-Custom "Checksum verification failed. Expected: $DownloadSha256, Got: $actualHash" + } + Write-Info "Checksum verified successfully." + + # 3. Install the package with token passed as MSI property + Write-Info "Installing SafeChain Ultimate..." + $process = Start-Process -FilePath "msiexec" -ArgumentList "/i", "`"$msiFile`"", "/qn", "/norestart", "AIKIDO_TOKEN=$token" -Wait -PassThru + if ($process.ExitCode -ne 0) { + Write-Error-Custom "MSI installer failed (exit code: $($process.ExitCode))." + } + + Write-Info "SafeChain Ultimate installed successfully!" + } + finally { + # Cleanup + if (Test-Path $msiFile) { + Remove-Item -Path $msiFile -Force -ErrorAction SilentlyContinue + } + } +} + +# Run installation +try { + Install-Endpoint +} +catch { + Write-Error-Custom "Installation failed: $_" +} From af90b20f1271a3e73ed31458c25fc40fd5e6b66a Mon Sep 17 00:00:00 2001 From: Sander Declerck Date: Fri, 13 Mar 2026 14:09:50 +0100 Subject: [PATCH 6/8] Add uninstall scripts --- install-scripts/uninstall-endpoint-mac.sh | 50 ++++++++++++++++ .../uninstall-endpoint-windows.ps1 | 59 +++++++++++++++++++ 2 files changed, 109 insertions(+) create mode 100644 install-scripts/uninstall-endpoint-mac.sh create mode 100644 install-scripts/uninstall-endpoint-windows.ps1 diff --git a/install-scripts/uninstall-endpoint-mac.sh b/install-scripts/uninstall-endpoint-mac.sh new file mode 100644 index 0000000..b1ba6e4 --- /dev/null +++ b/install-scripts/uninstall-endpoint-mac.sh @@ -0,0 +1,50 @@ +#!/bin/sh + +# Uninstalls SafeChain Ultimate endpoint on macOS +# +# Usage: curl -fsSL | sudo sh + +set -e # Exit on error + +# Configuration +UNINSTALL_SCRIPT="/Library/Application Support/AikidoSecurity/SafeChainUltimate/scripts/uninstall" + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +NC='\033[0m' # No Color + +# Helper functions +info() { + printf "${GREEN}[INFO]${NC} %s\n" "$1" +} + +error() { + printf "${RED}[ERROR]${NC} %s\n" "$1" >&2 + exit 1 +} + +# Main uninstallation +main() { + # Check if we're running on macOS + if [ "$(uname -s)" != "Darwin" ]; then + error "This script is only supported on macOS." + fi + + # Check if we're running as root + if [ "$(id -u)" -ne 0 ]; then + error "Root privileges required. Please re-run with sudo, e.g.: curl -fsSL | sudo sh" + fi + + # Check if the uninstall script exists + if [ ! -f "$UNINSTALL_SCRIPT" ]; then + error "SafeChain Ultimate does not appear to be installed (uninstall script not found)." + fi + + info "Uninstalling SafeChain Ultimate..." + "$UNINSTALL_SCRIPT" + + info "SafeChain Ultimate uninstalled successfully!" +} + +main "$@" diff --git a/install-scripts/uninstall-endpoint-windows.ps1 b/install-scripts/uninstall-endpoint-windows.ps1 new file mode 100644 index 0000000..5de5bfe --- /dev/null +++ b/install-scripts/uninstall-endpoint-windows.ps1 @@ -0,0 +1,59 @@ +# Uninstalls SafeChain Ultimate endpoint on Windows +# +# Usage: iex (iwr '' -UseBasicParsing) + +# Configuration +$AppName = "SafeChain Ultimate" + +# Helper functions +function Write-Info { + param([string]$Message) + Write-Host "[INFO] $Message" -ForegroundColor Green +} + +function Write-Error-Custom { + param([string]$Message) + Write-Host "[ERROR] $Message" -ForegroundColor Red + exit 1 +} + +# Check if running as Administrator +function Test-Administrator { + $identity = [Security.Principal.WindowsIdentity]::GetCurrent() + $principal = New-Object Security.Principal.WindowsPrincipal($identity) + return $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) +} + +# Main uninstallation +function Uninstall-Endpoint { + # Check if we're running as Administrator + if (-not (Test-Administrator)) { + Write-Error-Custom "Administrator privileges required. Please run this script in an elevated terminal (Run as Administrator)." + } + + # Find the installed product + Write-Info "Looking for SafeChain Ultimate installation..." + $app = Get-WmiObject -Class Win32_Product -Filter "Name='$AppName'" + + if (-not $app) { + Write-Error-Custom "SafeChain Ultimate does not appear to be installed." + } + + $productCode = $app.IdentifyingNumber + + Write-Info "Uninstalling SafeChain Ultimate..." + $process = Start-Process -FilePath "msiexec" -ArgumentList "/x", $productCode, "/qn", "/norestart" -Wait -PassThru + if ($process.ExitCode -ne 0) { + Write-Error-Custom "Uninstall failed (exit code: $($process.ExitCode))." + } + + Write-Info "SafeChain Ultimate uninstalled successfully!" +} + +# Run uninstallation +try { + Uninstall-Endpoint +} +catch { + Write-Error-Custom "Uninstallation failed: $_" +} From 8eabdd17ba9bb6890190971b1f91a9a90a9b9fdb Mon Sep 17 00:00:00 2001 From: Sander Declerck Date: Fri, 13 Mar 2026 14:19:25 +0100 Subject: [PATCH 7/8] Verify token format --- install-scripts/install-endpoint-mac.sh | 7 +++++++ install-scripts/install-endpoint-windows.ps1 | 5 +++++ 2 files changed, 12 insertions(+) diff --git a/install-scripts/install-endpoint-mac.sh b/install-scripts/install-endpoint-mac.sh index 8a0424d..684a8a8 100644 --- a/install-scripts/install-endpoint-mac.sh +++ b/install-scripts/install-endpoint-mac.sh @@ -103,6 +103,13 @@ main() { error "Token is required. Pass it with --token or enter it when prompted." fi + # Validate token to prevent injection + case "$TOKEN" in + *[\"\'\;\`\$\ ]*) + error "Invalid token format. Token must not contain quotes, semicolons, backticks, dollar signs, or whitespace." + ;; + esac + # 2. Download and verify checksum PKG_FILE=$(mktemp /tmp/SafeChainUltimate.XXXXXX.pkg) trap cleanup EXIT diff --git a/install-scripts/install-endpoint-windows.ps1 b/install-scripts/install-endpoint-windows.ps1 index 5c6eb3e..f99d1ff 100644 --- a/install-scripts/install-endpoint-windows.ps1 +++ b/install-scripts/install-endpoint-windows.ps1 @@ -47,6 +47,11 @@ function Install-Endpoint { } } + # Validate token to prevent command/property injection via msiexec + if ($token -match '[";`$\s]') { + Write-Error-Custom "Invalid token format. Token must not contain quotes, semicolons, backticks, dollar signs, or whitespace." + } + # 2. Download the .msi $msiFile = Join-Path $env:TEMP "SafeChainUltimate-$([System.Guid]::NewGuid().ToString('N')).msi" From b3e5726a836a12044ed96e0724e4ad845a9d5f8b Mon Sep 17 00:00:00 2001 From: Sander Declerck Date: Fri, 13 Mar 2026 14:30:29 +0100 Subject: [PATCH 8/8] Add new scripts to release --- .github/workflows/build-and-release.yml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-and-release.yml b/.github/workflows/build-and-release.yml index a752eb8..bab932c 100644 --- a/.github/workflows/build-and-release.yml +++ b/.github/workflows/build-and-release.yml @@ -77,6 +77,10 @@ jobs: sed "s/\$Version = Get-LatestVersion/\$Version = \"${VERSION}\"/" install-scripts/install-safe-chain.ps1 > release-artifacts/install-safe-chain.ps1 cp install-scripts/uninstall-safe-chain.sh release-artifacts/uninstall-safe-chain.sh cp install-scripts/uninstall-safe-chain.ps1 release-artifacts/uninstall-safe-chain.ps1 + cp install-scripts/install-endpoint-mac.sh release-artifacts/install-endpoint-mac.sh + cp install-scripts/install-endpoint-windows.ps1 release-artifacts/install-endpoint-windows.ps1 + cp install-scripts/uninstall-endpoint-mac.sh release-artifacts/uninstall-endpoint-mac.sh + cp install-scripts/uninstall-endpoint-windows.ps1 release-artifacts/uninstall-endpoint-windows.ps1 - name: Upload binaries to existing GitHub Release env: @@ -94,7 +98,11 @@ jobs: release-artifacts/install-safe-chain.sh \ release-artifacts/install-safe-chain.ps1 \ release-artifacts/uninstall-safe-chain.sh \ - release-artifacts/uninstall-safe-chain.ps1 + release-artifacts/uninstall-safe-chain.ps1 \ + release-artifacts/install-endpoint-mac.sh \ + release-artifacts/install-endpoint-windows.ps1 \ + release-artifacts/uninstall-endpoint-mac.sh \ + release-artifacts/uninstall-endpoint-windows.ps1 publish-npm: name: Publish to npm