Skip to content

Conversation

@matifali
Copy link
Member

  • Replace code-server with official VS Code CLI
  • Download CLI from code.visualstudio.com using cli-alpine-* URLs
  • Add release_channel variable (stable/insiders)
  • Add commit_id variable to pin specific VS Code versions
  • Support offline mode with fallback to code-server or cached vscode-server
  • Add comprehensive bun tests for settings, extensions, and CLI arguments
  • Add Terraform tests for variable validation

- Replace code-server with official VS Code CLI
- Download CLI from code.visualstudio.com using cli-alpine-* URLs
- Add release_channel variable (stable/insiders)
- Add commit_id variable to pin specific VS Code versions
- Support offline mode with fallback to code-server or cached vscode-server
- Add comprehensive bun tests for settings, extensions, and CLI arguments
- Add Terraform tests for variable validation
@matifali matifali requested a review from Copilot December 31, 2025 11:29
@matifali
Copy link
Member Author

@codex review

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +94 to +98
PLATFORM=$(uname -s)
case "$PLATFORM" in
Linux)
PLATFORM="alpine"
;;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Linux CLI download uses alpine build and fails on glibc hosts

The platform detection forces PLATFORM="alpine" for any Linux host, so the download URL later resolves to cli-alpine-* instead of the normal cli-linux-*. On standard Debian/Ubuntu (glibc) images the alpine binary requires the musl loader (/lib/ld-musl-*.so.1) and will not execute, so the script exits before VS Code starts. This makes the module unusable on the default glibc-based images; the detection should only pick the alpine build on Alpine and use the linux build elsewhere.

Useful? React with 👍 / 👎.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refactors the vscode-web module to use the official VS Code CLI instead of code-server, enabling better version control and alignment with official VS Code tooling.

  • Migrates from code-server to official VS Code CLI with code serve-web command
  • Adds release_channel variable to support stable/insiders releases
  • Implements comprehensive offline mode with fallback to code-server or cached vscode-server
  • Adds extensive test coverage with 21 new integration tests

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
main.tf Removes platform variable, adds release_channel and repositions commit_id variable with updated description
run.sh Complete rewrite to download and use VS Code CLI instead of code-server, with offline fallback mechanisms
main.test.ts Adds comprehensive test suite with 21 tests covering script generation, settings management, extension installation, and container integration
vscode-web.tftest.hcl New Terraform validation tests for variable constraints and URL generation
README.md Updates documentation to reflect VS Code CLI usage and new configuration options

Comment on lines +115 to +122
if command -v curl > /dev/null 2>&1; then
curl -fsSL "$CLI_URL" -o "/tmp/vscode-cli.tar.gz"
elif command -v wget > /dev/null 2>&1; then
wget -q "$CLI_URL" -O "/tmp/vscode-cli.tar.gz"
else
echo "Neither curl nor wget is available. Please install one of them."
exit 1
;;
esac

# Detect the platform
if [ -n "${PLATFORM}" ]; then
DETECTED_PLATFORM="${PLATFORM}"
elif [ -f /etc/alpine-release ] || grep -qi 'ID=alpine' /etc/os-release 2> /dev/null || command -v apk > /dev/null 2>&1; then
DETECTED_PLATFORM="alpine"
elif [ "$(uname -s)" = "Darwin" ]; then
DETECTED_PLATFORM="darwin"
else
DETECTED_PLATFORM="linux"
fi
fi
Copy link

Copilot AI Dec 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The curl and wget commands don't check for download failures. If the download fails (e.g., network issue, 404 error), the script continues to the tar extraction which will fail with a confusing error message. Add error checking after the download commands to provide a clear error message.

Copilot uses AI. Check for mistakes.
fi
printf "$${BOLD}VS Code Web commit id version $HASH.\n"
# Extract CLI
tar -xzf /tmp/vscode-cli.tar.gz -C "${INSTALL_PREFIX}/bin"
Copy link

Copilot AI Dec 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The tar extraction command doesn't check for errors. If the extraction fails (e.g., corrupted archive, insufficient disk space), the script will proceed to check for the binary and provide a generic "Failed to install VS Code CLI" error. Consider checking the exit status of tar and providing a more specific error message for extraction failures.

Suggested change
tar -xzf /tmp/vscode-cli.tar.gz -C "${INSTALL_PREFIX}/bin"
if ! tar -xzf /tmp/vscode-cli.tar.gz -C "${INSTALL_PREFIX}/bin"; then
echo "Error extracting VS Code CLI archive. The download may be corrupted or there may be insufficient disk space."
rm -f /tmp/vscode-cli.tar.gz
exit 1
fi

Copilot uses AI. Check for mistakes.
esac

# Detect platform
# Note: VS Code CLI uses 'alpine' for all Linux distributions
Copy link

Copilot AI Dec 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment states "VS Code CLI uses 'alpine' for all Linux distributions," but this is misleading. The URL format "cli-alpine-*" is used for the musl-based CLI download, which works across all Linux distributions (not just Alpine). Consider clarifying the comment to explain that this refers to the download URL format rather than suggesting Alpine-specific functionality.

Suggested change
# Note: VS Code CLI uses 'alpine' for all Linux distributions
# Note: For Linux, the VS Code CLI download URL uses the 'cli-alpine-*' (musl) build,
# which is intended to work across common Linux distributions (not just Alpine).

Copilot uses AI. Check for mistakes.
Comment on lines +144 to +166
ARGS="serve-web --port ${PORT} --host 127.0.0.1 --accept-server-license-terms --without-connection-token --telemetry-level ${TELEMETRY_LEVEL}"

if [ -n "$EXTENSION_ARG" ]; then
ARGS="$ARGS $EXTENSION_ARG"
fi

# Install each extension...
IFS=',' read -r -a EXTENSIONLIST <<< "$${EXTENSIONS}"
# shellcheck disable=SC2066
for extension in "$${EXTENSIONLIST[@]}"; do
if [ -z "$extension" ]; then
continue
if [ -n "$SERVER_BASE_PATH_ARG" ]; then
ARGS="$ARGS $SERVER_BASE_PATH_ARG"
fi
printf "🧩 Installing extension $${CODE}$extension$${RESET}...\n"
output=$($VSCODE_WEB "$EXTENSION_ARG" --install-extension "$extension" --force)
if [ $? -ne 0 ]; then
echo "Failed to install extension: $extension: $output"

if [ -n "$DISABLE_TRUST_ARG" ]; then
ARGS="$ARGS $DISABLE_TRUST_ARG"
fi
done

if [ "${AUTO_INSTALL_EXTENSIONS}" = true ]; then
if ! command -v jq > /dev/null; then
echo "jq is required to install extensions from a workspace file."
else
# Prefer WORKSPACE if set and points to a file
if [ -n "${WORKSPACE}" ] && [ -f "${WORKSPACE}" ]; then
printf "🧩 Installing extensions from %s...\n" "${WORKSPACE}"
# Strip single-line comments then parse .extensions.recommendations[]
extensions=$(sed 's|//.*||g' "${WORKSPACE}" | jq -r '(.extensions.recommendations // [])[]')
for extension in $extensions; do
$VSCODE_WEB "$EXTENSION_ARG" --install-extension "$extension" --force
done
if [ -n "${COMMIT_ID}" ]; then
ARGS="$ARGS --commit-id ${COMMIT_ID}"
fi

printf "Starting VS Code Web on port ${PORT}...\n"
printf "Check logs at ${LOG_PATH}\n"

# shellcheck disable=SC2086
"$CODE_CMD" $ARGS > "${LOG_PATH}" 2>&1 &
Copy link

Copilot AI Dec 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The run_vscode_web_cli function builds a single ARGS string with values like EXTENSION_ARG, SERVER_BASE_PATH_ARG, and COMMIT_ID and then invokes "$CODE_CMD" $ARGS, which expands ARGS unquoted. If any of these inputs contain shell metacharacters (such as ;, &, backticks, or $()), the shell will interpret them, allowing command injection and arbitrary command execution in the workspace process. To mitigate this, construct the CLI invocation using a properly quoted argument list (arrays) or ensure that all interpolated variables are safely quoted/escaped so that user-controlled data cannot break out of its argument context.

Copilot uses AI. Check for mistakes.
Comment on lines +176 to +184
# Build arguments for code-server
ARGS="--port ${PORT} --host 127.0.0.1 --auth none"

if [ -n "$EXTENSION_ARG" ]; then
ARGS="$ARGS $EXTENSION_ARG"
fi

# shellcheck disable=SC2086
"$SERVER_CMD" $ARGS > "${LOG_PATH}" 2>&1 &
Copy link

Copilot AI Dec 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The run_code_server function constructs an ARGS string incorporating EXTENSION_ARG and then calls "$SERVER_CMD" $ARGS, expanding ARGS without quotes. An attacker who can influence EXTENSIONS_DIR (and therefore EXTENSION_ARG) can inject shell metacharacters to execute additional commands alongside code-server, leading to arbitrary command execution. Use a safely quoted argument list or pass EXTENSION_ARG as a separate, quoted argument so that its contents cannot be parsed as shell syntax.

Suggested change
# Build arguments for code-server
ARGS="--port ${PORT} --host 127.0.0.1 --auth none"
if [ -n "$EXTENSION_ARG" ]; then
ARGS="$ARGS $EXTENSION_ARG"
fi
# shellcheck disable=SC2086
"$SERVER_CMD" $ARGS > "${LOG_PATH}" 2>&1 &
# Build arguments for code-server using an array to avoid word splitting
local args=(--port "${PORT}" --host 127.0.0.1 --auth none)
if [ -n "$EXTENSION_ARG" ]; then
args+=("$EXTENSION_ARG")
fi
"$SERVER_CMD" "${args[@]}" > "${LOG_PATH}" 2>&1 &

Copilot uses AI. Check for mistakes.
Comment on lines +195 to +206
ARGS="--port ${PORT} --host 127.0.0.1 --without-connection-token --accept-server-license-terms --telemetry-level ${TELEMETRY_LEVEL}"

if [ -n "$EXTENSION_ARG" ]; then
ARGS="$ARGS $EXTENSION_ARG"
fi

if [ -n "$SERVER_BASE_PATH_ARG" ]; then
ARGS="$ARGS $SERVER_BASE_PATH_ARG"
fi

# shellcheck disable=SC2086
"$SERVER_CMD" serve-local $ARGS > "${LOG_PATH}" 2>&1 &
Copy link

Copilot AI Dec 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The run_vscode_server function similarly builds an ARGS string with EXTENSION_ARG, SERVER_BASE_PATH_ARG, and telemetry/port values and then invokes "$SERVER_CMD" serve-local $ARGS with ARGS unquoted. If any of these components contain shell metacharacters (for example via a malicious SERVER_BASE_PATH or EXTENSIONS_DIR), the shell will interpret them as control characters, enabling command injection before vscode-server starts. This should be refactored to pass arguments in a quoted list (e.g., using arrays) or otherwise ensure that user-controlled values cannot alter the shell command structure.

Copilot uses AI. Check for mistakes.
Comment on lines +219 to +220
output=$("$CODE_CMD" $EXTENSION_ARG --install-extension "$extension" --force 2>&1)
if [ $? -ne 0 ]; then
Copy link

Copilot AI Dec 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In install_extensions, the call "$CODE_CMD" $EXTENSION_ARG --install-extension "$extension" --force expands EXTENSION_ARG without quotes. A crafted EXTENSIONS_DIR value (propagating into EXTENSION_ARG) containing shell metacharacters could break out of the intended argument and cause arbitrary shell commands to run when installing extensions. Quote EXTENSION_ARG (or build a positional argument list/array) so that its contents are always treated as a single argument to the CLI rather than executable shell syntax.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant