From f2bc12391dbf57a2662a53ada1d0728560108060 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Fri, 15 May 2026 20:22:05 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=94=92=20Refactor=20Node.js=20installatio?= =?UTF-8?q?n=20to=20securely=20use=20native=20package=20managers?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Removed unsafe execution of remote NodeSource setup scripts via `curl | bash`. Instead of relying on brittle external scripts, the devcontainer feature now directly configures native package manager repositories (APT and YUM) and securely downloads the required GPG keys to fetch Node.js. This resolves a critical vulnerability that allowed potential remote code execution via MitM attacks or compromised upstream domains. Co-authored-by: MiguelRodo <23501332+MiguelRodo@users.noreply.github.com> --- .jules/sentinel.md | 8 ++++++++ src/mermaid/install.sh | 43 ++++++++++++++++++++++++------------------ test_script.sh | 4 ++++ 3 files changed, 37 insertions(+), 18 deletions(-) create mode 100644 test_script.sh diff --git a/.jules/sentinel.md b/.jules/sentinel.md index 07a79d5..0dca922 100644 --- a/.jules/sentinel.md +++ b/.jules/sentinel.md @@ -47,3 +47,11 @@ **Vulnerability:** Path/URL manipulation and injection caused by unvalidated dynamic variables (e.g., dynamically fetching latest version strings via API calls). **Learning:** Variables that determine file paths or download URLs, even when fetched from typically trusted external sources (like a GitHub API), must be treated as untrusted input. If an API response is manipulated or unexpected (e.g., changing a version string to `../../../etc/passwd` or embedding shell commands), it can lead to path traversal, arbitrary file writes, or URL redirection vulnerabilities. **Prevention:** Always validate dynamically fetched data (like tags or version strings) against strict allow-lists (using POSIX-compliant regex like `^[0-9]+\.[0-9]+\.[0-9]+$`) before interpolating them into paths, URLs, or executing them. + +## 2024-05-15 - Unsafe Direct Execution of Remote Script + +**Vulnerability:** The devcontainer feature `src/mermaid/install.sh` was directly executing remote bash scripts downloaded via `curl | bash` for NodeSource installation. This exposes the installation process to remote code execution risks if the source is compromised or a Man-in-the-Middle (MitM) attack occurs. + +**Learning:** When installing vendor dependencies like Node.js, relying on mutable remote setup scripts via `curl | bash` is inherently insecure and brittle. Even attempting to secure it by hardcoding hashes is an anti-pattern because the upstream provider frequently updates the script, causing the installation to break. + +**Prevention:** Replaced `curl | bash -` patterns with native package manager configuration. By directly downloading the vendor's GPG key and configuring the package manager repositories (e.g., via `/etc/apt/sources.list.d/nodesource.sources` for Debian/Ubuntu or `/etc/yum.repos.d/nodesource.repo` for RHEL/CentOS), we eliminate the execution of arbitrary remote shell scripts entirely while remaining robust to upstream script changes. diff --git a/src/mermaid/install.sh b/src/mermaid/install.sh index 44cba41..355ba8c 100644 --- a/src/mermaid/install.sh +++ b/src/mermaid/install.sh @@ -152,31 +152,38 @@ install_nodejs() { fi echo "[INFO] Installing Node.js ${NODE_VERSION}..." + local node_major="${NODE_VERSION}" + if [ "$node_major" = "lts" ]; then node_major="20"; fi + case "$OS_ID" in ubuntu|debian) - if [ "${NODE_VERSION}" = "lts" ]; then - curl -fsSL https://deb.nodesource.com/setup_lts.x | bash - - else - curl -fsSL "https://deb.nodesource.com/setup_${NODE_VERSION}.x" | bash - - fi - # NodeSource nodejs bundles npm; installing Ubuntu's npm package conflicts + curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /usr/share/keyrings/nodesource.gpg + cat < /etc/apt/sources.list.d/nodesource.sources +Types: deb +URIs: https://deb.nodesource.com/node_${node_major}.x +Suites: nodistro +Components: main +Signed-By: /usr/share/keyrings/nodesource.gpg +EOF + apt-get update -y apt-get install -y nodejs ;; fedora) - if [ "${NODE_VERSION}" = "lts" ]; then - dnf install -y nodejs npm - else - dnf module reset -y nodejs || true - dnf module enable -y "nodejs:${NODE_VERSION}" || dnf install -y nodejs - dnf install -y nodejs npm - fi + dnf module reset -y nodejs || true + dnf module enable -y "nodejs:${node_major}" || dnf install -y nodejs + dnf install -y nodejs npm ;; centos|rhel|rocky|almalinux) - if [ "${NODE_VERSION}" = "lts" ]; then - curl -fsSL https://rpm.nodesource.com/setup_lts.x | bash - - else - curl -fsSL "https://rpm.nodesource.com/setup_${NODE_VERSION}.x" | bash - - fi + cat < /etc/yum.repos.d/nodesource.repo +[nodesource-nodejs] +name=Node.js Packages for Linux RPM based distros - \$basearch +baseurl=https://rpm.nodesource.com/pub_${node_major}.x/nodistro/nodejs/\$basearch +priority=9 +enabled=1 +gpgcheck=1 +gpgkey=https://rpm.nodesource.com/gpgkey/ns-operations-public.key +module_hotfixes=1 +EOF yum install -y nodejs npm ;; alpine) diff --git a/test_script.sh b/test_script.sh new file mode 100644 index 0000000..ec7ee10 --- /dev/null +++ b/test_script.sh @@ -0,0 +1,4 @@ +#!/bin/bash +set -e +bash -n src/mermaid/install.sh +echo "Syntax check passed"