From 12fd751baa48e48ae3bc153e605da1f075b8e8b8 Mon Sep 17 00:00:00 2001 From: Hans Ott Date: Mon, 13 Oct 2025 16:56:01 +0200 Subject: [PATCH] Don't continue if safe-chain wasn't found Unless --safe-chain-malware-action=prompt is used --- README.md | 12 +++-- .../startup-scripts/init-posix.sh | 45 +++++++++++++++++-- 2 files changed, 50 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 1083c0e..ed5b58e 100644 --- a/README.md +++ b/README.md @@ -77,10 +77,10 @@ To uninstall the Aikido Safe Chain, you can run the following command: ## Malware Action -You can control how Aikido Safe Chain responds when malware is detected using the `--safe-chain-malware-action` flag: +You can control how Aikido Safe Chain responds when malware is detected or when safe-chain is not available using the `--safe-chain-malware-action` flag: -- `--safe-chain-malware-action=block` (**default**) - Automatically blocks installation and exits with an error when malware is detected -- `--safe-chain-malware-action=prompt` - Prompts the user to decide whether to continue despite the malware detection +- `--safe-chain-malware-action=block` (**default**) - Automatically blocks installation and exits with an error when malware is detected or when safe-chain is unavailable +- `--safe-chain-malware-action=prompt` - Prompts the user to decide whether to continue despite the malware detection or missing safe-chain Example usage: @@ -88,6 +88,12 @@ Example usage: npm install suspicious-package --safe-chain-malware-action=prompt ``` +### When Safe Chain is Not Available + +By default, if the safe-chain commands (aikido-npm, aikido-yarn, etc.) are not found in your PATH, the command will be **blocked** to protect you from installing packages without malware scanning. This can happen when using version managers like [asdf](https://github.com/asdf-vm/asdf) where each Node version has its own global packages. + +To continue in this situation, use the `prompt` mode: `npm install package --safe-chain-malware-action=prompt` + # Usage in CI/CD You can protect your CI/CD pipelines from malicious packages by integrating Aikido Safe Chain into your build process. This ensures that any packages installed during your automated builds are checked for malware before installation. diff --git a/packages/safe-chain/src/shell-integration/startup-scripts/init-posix.sh b/packages/safe-chain/src/shell-integration/startup-scripts/init-posix.sh index 353c6c0..6d9f3d3 100644 --- a/packages/safe-chain/src/shell-integration/startup-scripts/init-posix.sh +++ b/packages/safe-chain/src/shell-integration/startup-scripts/init-posix.sh @@ -2,9 +2,26 @@ function printSafeChainWarning() { # \033[43;30m is used to set the background color to yellow and text color to black # \033[0m is used to reset the text formatting - printf "\033[43;30mWarning:\033[0m safe-chain is not available to protect you from installing malware. %s will run without it.\n" "$1" + printf "\033[43;30mWarning:\033[0m safe-chain is not available to protect you from installing malware. %s will run without it.\n" "$1" >&2 # \033[36m is used to set the text color to cyan - printf "Install safe-chain by using \033[36mnpm install -g @aikidosec/safe-chain\033[0m.\n" + printf "Install safe-chain by using \033[36mnpm install -g @aikidosec/safe-chain\033[0m.\n" >&2 +} + +function getMalwareAction() { + # Parse --safe-chain-malware-action flag from arguments + local action="" + for arg in "$@"; do + if [[ "$arg" =~ ^--safe-chain-malware-action=(.+)$ ]]; then + action="${BASH_REMATCH[1]}" + fi + done + + # Default to block if not specified + if [[ -z "$action" ]]; then + echo "block" + else + echo "$action" + fi } function wrapSafeChainCommand() { @@ -19,10 +36,30 @@ function wrapSafeChainCommand() { # If the aikido command is available, just run it with the provided arguments "$aikido_cmd" "$@" else - # If the aikido command is not available, print a warning and run the original command + # If the aikido command is not available, handle based on --safe-chain-malware-action flag printSafeChainWarning "$original_cmd" - command "$original_cmd" "$@" + local action=$(getMalwareAction "$@") + + case "$action" in + prompt) + # Ask user if they want to continue + printf "Do you want to continue without safe-chain protection? [y/N] " >&2 + read -r response + if [[ "$response" =~ ^[Yy]$ ]]; then + command "$original_cmd" "$@" + else + printf "Aborted.\n" >&2 + return 1 + fi + ;; + block|*) + # Block by default (safest option) + printf "Refusing to execute %s without safe-chain protection.\n" "$original_cmd" >&2 + printf "To continue anyway, add: \033[36m--safe-chain-malware-action=prompt\033[0m\n" >&2 + return 1 + ;; + esac fi }