mirror of
https://github.com/AikidoSec/safe-chain.git
synced 2026-05-26 12:10:49 +00:00
Cleanup
This commit is contained in:
parent
1cf8fd1241
commit
d064d46668
32 changed files with 429 additions and 400 deletions
|
|
@ -4,25 +4,49 @@
|
|||
|
||||
param(
|
||||
[switch]$ci,
|
||||
[switch]$includepython
|
||||
[switch]$includepython,
|
||||
[string]$InstallDir
|
||||
)
|
||||
|
||||
$Version = $env:SAFE_CHAIN_VERSION # Will be fetched from latest release if not set
|
||||
function Test-InstallDir {
|
||||
param([string]$Dir)
|
||||
|
||||
# Validate SAFE_CHAIN_DIR before use
|
||||
if ($env:SAFE_CHAIN_DIR) {
|
||||
if (-not [System.IO.Path]::IsPathRooted($env:SAFE_CHAIN_DIR)) {
|
||||
Write-Host "[ERROR] SAFE_CHAIN_DIR must be an absolute path, got: $($env:SAFE_CHAIN_DIR)" -ForegroundColor Red; exit 1
|
||||
if ([string]::IsNullOrWhiteSpace($Dir)) {
|
||||
return @{ Ok = $true; Normalized = $null }
|
||||
}
|
||||
if ($env:SAFE_CHAIN_DIR -match '\.\.') {
|
||||
Write-Host "[ERROR] SAFE_CHAIN_DIR must not contain path traversal (..)" -ForegroundColor Red; exit 1
|
||||
|
||||
if (-not [System.IO.Path]::IsPathRooted($Dir)) {
|
||||
return @{ Ok = $false; Reason = "-InstallDir must be an absolute path, got: $Dir" }
|
||||
}
|
||||
if ($env:SAFE_CHAIN_DIR -match '^[A-Za-z]:[/\\]?$' -or $env:SAFE_CHAIN_DIR -eq '/') {
|
||||
Write-Host "[ERROR] SAFE_CHAIN_DIR cannot be a root or drive-root directory" -ForegroundColor Red; exit 1
|
||||
|
||||
if ($Dir.Contains([System.IO.Path]::PathSeparator)) {
|
||||
return @{ Ok = $false; Reason = "-InstallDir must not contain the PATH separator ($([System.IO.Path]::PathSeparator))" }
|
||||
}
|
||||
|
||||
$normalized = [System.IO.Path]::GetFullPath($Dir)
|
||||
$root = [System.IO.Path]::GetPathRoot($normalized)
|
||||
if ($normalized.TrimEnd('\', '/') -eq $root.TrimEnd('\', '/')) {
|
||||
return @{ Ok = $false; Reason = "-InstallDir cannot be a root or drive-root directory" }
|
||||
}
|
||||
|
||||
$segments = $normalized.Substring($root.Length).Split([char[]]@('\', '/'), [System.StringSplitOptions]::RemoveEmptyEntries)
|
||||
if ($segments -contains "..") {
|
||||
return @{ Ok = $false; Reason = "-InstallDir must not contain path traversal segments" }
|
||||
}
|
||||
|
||||
return @{ Ok = $true; Normalized = $normalized }
|
||||
}
|
||||
|
||||
$SafeChainBase = if ($env:SAFE_CHAIN_DIR) { $env:SAFE_CHAIN_DIR } else { Join-Path $env:USERPROFILE ".safe-chain" }
|
||||
$Version = $env:SAFE_CHAIN_VERSION # Will be fetched from latest release if not set
|
||||
$SafeChainBase = if ($InstallDir) { $InstallDir } else { Join-Path $env:USERPROFILE ".safe-chain" }
|
||||
|
||||
$installDirValidation = Test-InstallDir -Dir $SafeChainBase
|
||||
if (-not $installDirValidation.Ok) {
|
||||
Write-Host "[ERROR] $($installDirValidation.Reason)" -ForegroundColor Red
|
||||
exit 1
|
||||
}
|
||||
|
||||
$SafeChainBase = $installDirValidation.Normalized
|
||||
$InstallDir = Join-Path $SafeChainBase "bin"
|
||||
$RepoUrl = "https://github.com/AikidoSec/safe-chain"
|
||||
|
||||
|
|
|
|||
|
|
@ -6,24 +6,50 @@
|
|||
|
||||
set -e # Exit on error
|
||||
|
||||
validate_install_dir() {
|
||||
dir="$1"
|
||||
|
||||
if [ -z "$dir" ]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
case "$dir" in
|
||||
/*) ;;
|
||||
*)
|
||||
printf '[ERROR] --install-dir must be an absolute path, got: %s\n' "$dir" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
case "$dir" in
|
||||
*:*)
|
||||
printf '[ERROR] --install-dir must not contain the PATH separator (:)\n' >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ "$dir" = "/" ]; then
|
||||
printf '[ERROR] --install-dir cannot be a root or drive-root directory\n' >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
old_ifs=$IFS
|
||||
IFS='/'
|
||||
set -- $dir
|
||||
IFS=$old_ifs
|
||||
|
||||
for segment in "$@"; do
|
||||
if [ "$segment" = ".." ]; then
|
||||
printf '[ERROR] --install-dir must not contain path traversal segments\n' >&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
# Configuration
|
||||
VERSION="${SAFE_CHAIN_VERSION:-}" # Will be fetched from latest release if not set
|
||||
SAFE_CHAIN_BASE="${HOME}/.safe-chain"
|
||||
|
||||
# Validate SAFE_CHAIN_DIR before use
|
||||
if [ -n "${SAFE_CHAIN_DIR}" ]; then
|
||||
case "${SAFE_CHAIN_DIR}" in
|
||||
/*) ;;
|
||||
*) printf '[ERROR] SAFE_CHAIN_DIR must be an absolute path, got: %s\n' "${SAFE_CHAIN_DIR}" >&2; exit 1 ;;
|
||||
esac
|
||||
case "${SAFE_CHAIN_DIR}" in
|
||||
*../*|*/..*|..) printf '[ERROR] SAFE_CHAIN_DIR must not contain path traversal (..)\n' >&2; exit 1 ;;
|
||||
esac
|
||||
if [ "${SAFE_CHAIN_DIR}" = "/" ]; then
|
||||
printf '[ERROR] SAFE_CHAIN_DIR cannot be the root directory\n' >&2; exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
SAFE_CHAIN_BASE="${SAFE_CHAIN_DIR:-${HOME}/.safe-chain}"
|
||||
INSTALL_DIR="${SAFE_CHAIN_BASE}/bin"
|
||||
REPO_URL="https://github.com/AikidoSec/safe-chain"
|
||||
|
||||
|
|
@ -245,19 +271,33 @@ remove_nvm_installation() {
|
|||
|
||||
# Parse command-line arguments
|
||||
parse_arguments() {
|
||||
for arg in "$@"; do
|
||||
case "$arg" in
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
--ci)
|
||||
USE_CI_SETUP=true
|
||||
;;
|
||||
--install-dir)
|
||||
shift
|
||||
if [ $# -eq 0 ]; then
|
||||
error "Missing value for --install-dir"
|
||||
fi
|
||||
SAFE_CHAIN_BASE="$1"
|
||||
;;
|
||||
--install-dir=*)
|
||||
SAFE_CHAIN_BASE="${1#--install-dir=}"
|
||||
;;
|
||||
--include-python)
|
||||
warn "--include-python is deprecated and ignored. Python ecosystem is now included by default."
|
||||
;;
|
||||
*)
|
||||
error "Unknown argument: $arg"
|
||||
error "Unknown argument: $1"
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
validate_install_dir "${SAFE_CHAIN_BASE}"
|
||||
INSTALL_DIR="${SAFE_CHAIN_BASE}/bin"
|
||||
}
|
||||
|
||||
# Main installation
|
||||
|
|
|
|||
|
|
@ -5,22 +5,6 @@
|
|||
# Use HOME on Unix, USERPROFILE on Windows (PowerShell Core is cross-platform)
|
||||
$HomeDir = if ($env:HOME) { $env:HOME } else { $env:USERPROFILE }
|
||||
|
||||
# Validate SAFE_CHAIN_DIR before use
|
||||
if ($env:SAFE_CHAIN_DIR) {
|
||||
if (-not [System.IO.Path]::IsPathRooted($env:SAFE_CHAIN_DIR)) {
|
||||
Write-Host "[ERROR] SAFE_CHAIN_DIR must be an absolute path, got: $($env:SAFE_CHAIN_DIR)" -ForegroundColor Red; exit 1
|
||||
}
|
||||
if ($env:SAFE_CHAIN_DIR -match '\.\.') {
|
||||
Write-Host "[ERROR] SAFE_CHAIN_DIR must not contain path traversal (..)" -ForegroundColor Red; exit 1
|
||||
}
|
||||
if ($env:SAFE_CHAIN_DIR -match '^[A-Za-z]:[/\\]?$' -or $env:SAFE_CHAIN_DIR -eq '/') {
|
||||
Write-Host "[ERROR] SAFE_CHAIN_DIR cannot be a root or drive-root directory" -ForegroundColor Red; exit 1
|
||||
}
|
||||
}
|
||||
|
||||
$DotSafeChain = if ($env:SAFE_CHAIN_DIR) { $env:SAFE_CHAIN_DIR } else { Join-Path $HomeDir ".safe-chain" }
|
||||
$InstallDir = Join-Path $DotSafeChain "bin"
|
||||
|
||||
# Helper functions
|
||||
function Write-Info {
|
||||
param([string]$Message)
|
||||
|
|
@ -38,6 +22,64 @@ function Write-Error-Custom {
|
|||
exit 1
|
||||
}
|
||||
|
||||
function Get-InstallDirFromBinaryPath {
|
||||
param([string]$BinaryPath)
|
||||
|
||||
if ([string]::IsNullOrWhiteSpace($BinaryPath)) {
|
||||
return $null
|
||||
}
|
||||
|
||||
try {
|
||||
$resolvedPath = (Resolve-Path -LiteralPath $BinaryPath -ErrorAction Stop).Path
|
||||
}
|
||||
catch {
|
||||
$resolvedPath = [System.IO.Path]::GetFullPath($BinaryPath)
|
||||
}
|
||||
|
||||
$fileName = [System.IO.Path]::GetFileName($resolvedPath)
|
||||
if (($fileName -ne "safe-chain") -and ($fileName -ne "safe-chain.exe")) {
|
||||
return $null
|
||||
}
|
||||
|
||||
if ($resolvedPath -match '\.(js|cjs|mjs|cmd|ps1)$') {
|
||||
return $null
|
||||
}
|
||||
|
||||
$binDir = Split-Path -Parent $resolvedPath
|
||||
if ((Split-Path -Leaf $binDir) -ne "bin") {
|
||||
return $null
|
||||
}
|
||||
|
||||
return (Split-Path -Parent $binDir)
|
||||
}
|
||||
|
||||
function Get-SafeChainInstallDir {
|
||||
$command = Get-Command safe-chain -ErrorAction SilentlyContinue | Select-Object -First 1
|
||||
if ($command) {
|
||||
try {
|
||||
$reportedInstallDir = & safe-chain get-install-dir 2>$null | Select-Object -First 1
|
||||
if ($reportedInstallDir) {
|
||||
$reportedInstallDir = $reportedInstallDir.Trim()
|
||||
}
|
||||
if ($reportedInstallDir) {
|
||||
return $reportedInstallDir
|
||||
}
|
||||
}
|
||||
catch {
|
||||
# Fall back to deriving the install dir from the discovered command path
|
||||
}
|
||||
}
|
||||
|
||||
if ($command -and $command.Path) {
|
||||
$discoveredInstallDir = Get-InstallDirFromBinaryPath -BinaryPath $command.Path
|
||||
if ($discoveredInstallDir) {
|
||||
return $discoveredInstallDir
|
||||
}
|
||||
}
|
||||
|
||||
return (Join-Path $HomeDir ".safe-chain")
|
||||
}
|
||||
|
||||
# Check and uninstall npm global package if present
|
||||
function Remove-NpmInstallation {
|
||||
# Check if npm is available
|
||||
|
|
@ -90,6 +132,8 @@ function Remove-VoltaInstallation {
|
|||
# Main uninstallation
|
||||
function Uninstall-SafeChain {
|
||||
Write-Info "Uninstalling safe-chain..."
|
||||
$DotSafeChain = Get-SafeChainInstallDir
|
||||
$InstallDir = Join-Path $DotSafeChain "bin"
|
||||
|
||||
# Run teardown if safe-chain is available
|
||||
# Check for both safe-chain.exe (Windows) and safe-chain (Unix) since PowerShell Core runs on all platforms
|
||||
|
|
|
|||
|
|
@ -8,22 +8,6 @@ set -e # Exit on error
|
|||
|
||||
# Configuration
|
||||
|
||||
# Validate SAFE_CHAIN_DIR before use
|
||||
if [ -n "${SAFE_CHAIN_DIR}" ]; then
|
||||
case "${SAFE_CHAIN_DIR}" in
|
||||
/*) ;;
|
||||
*) printf '[ERROR] SAFE_CHAIN_DIR must be an absolute path, got: %s\n' "${SAFE_CHAIN_DIR}" >&2; exit 1 ;;
|
||||
esac
|
||||
case "${SAFE_CHAIN_DIR}" in
|
||||
*../*|*/..*|..) printf '[ERROR] SAFE_CHAIN_DIR must not contain path traversal (..)\n' >&2; exit 1 ;;
|
||||
esac
|
||||
if [ "${SAFE_CHAIN_DIR}" = "/" ]; then
|
||||
printf '[ERROR] SAFE_CHAIN_DIR cannot be the root directory\n' >&2; exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
DOT_SAFE_CHAIN="${SAFE_CHAIN_DIR:-${HOME}/.safe-chain}"
|
||||
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
|
|
@ -49,6 +33,78 @@ command_exists() {
|
|||
command -v "$1" >/dev/null 2>&1
|
||||
}
|
||||
|
||||
resolve_path() {
|
||||
target="$1"
|
||||
|
||||
while [ -L "$target" ]; do
|
||||
link_target=$(readlink "$target" 2>/dev/null || echo "")
|
||||
if [ -z "$link_target" ]; then
|
||||
break
|
||||
fi
|
||||
|
||||
case "$link_target" in
|
||||
/*) target="$link_target" ;;
|
||||
*)
|
||||
target="$(dirname "$target")/$link_target"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
target_dir=$(dirname "$target")
|
||||
target_name=$(basename "$target")
|
||||
|
||||
if cd "$target_dir" 2>/dev/null; then
|
||||
printf '%s/%s\n' "$(pwd -P)" "$target_name"
|
||||
else
|
||||
printf '%s\n' "$target"
|
||||
fi
|
||||
}
|
||||
|
||||
derive_install_dir_from_binary() {
|
||||
binary_path="$1"
|
||||
|
||||
if [ -z "$binary_path" ]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
resolved_path=$(resolve_path "$binary_path")
|
||||
binary_name=$(basename "$resolved_path")
|
||||
case "$binary_name" in
|
||||
safe-chain|safe-chain.exe) ;;
|
||||
*) return 1 ;;
|
||||
esac
|
||||
|
||||
case "$resolved_path" in
|
||||
*.js|*.cjs|*.mjs|*.cmd|*.ps1) return 1 ;;
|
||||
esac
|
||||
|
||||
binary_dir=$(dirname "$resolved_path")
|
||||
if [ "$(basename "$binary_dir")" != "bin" ]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
dirname "$binary_dir"
|
||||
}
|
||||
|
||||
get_install_dir() {
|
||||
if command_exists safe-chain; then
|
||||
install_dir=$(safe-chain get-install-dir 2>/dev/null || true)
|
||||
if [ -n "$install_dir" ]; then
|
||||
printf '%s\n' "$install_dir"
|
||||
return 0
|
||||
fi
|
||||
|
||||
command_path=$(command -v safe-chain)
|
||||
install_dir=$(derive_install_dir_from_binary "$command_path" || true)
|
||||
if [ -n "$install_dir" ]; then
|
||||
printf '%s\n' "$install_dir"
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
|
||||
printf '%s\n' "${HOME}/.safe-chain"
|
||||
}
|
||||
|
||||
# Check and uninstall npm global package if present
|
||||
remove_npm_installation() {
|
||||
if ! command_exists npm; then
|
||||
|
|
@ -154,6 +210,7 @@ remove_nvm_installation() {
|
|||
|
||||
# Main uninstallation
|
||||
main() {
|
||||
DOT_SAFE_CHAIN=$(get_install_dir)
|
||||
SAFE_CHAIN_LOCATION="$DOT_SAFE_CHAIN/bin/safe-chain"
|
||||
|
||||
if [ -x "$SAFE_CHAIN_LOCATION" ]; then
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue