From 4506e05a53470379b6b05d0b475130b3ac537869 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 31 Mar 2026 09:09:44 +0000 Subject: [PATCH 1/3] Initial plan From bf6ddc3e05fdd25648110d077b16d60885bf3219 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 31 Mar 2026 09:50:32 +0000 Subject: [PATCH 2/3] Fix backtick evaluation in add-script and run-script features Agent-Logs-Url: https://github.com/devcontainer-community/devcontainer-features/sessions/d2225e5d-fb26-4975-97f2-47b2a7d49117 Co-authored-by: sebst <592313+sebst@users.noreply.github.com> --- README.md | 4 ++-- src/add-script/devcontainer-feature.json | 2 +- src/add-script/install.sh | 8 ++++++++ src/run-script/devcontainer-feature.json | 2 +- src/run-script/install.sh | 8 ++++++++ test/add-script/scenarios.json | 11 +++++++++++ test/add-script/test-backtick.sh | 11 +++++++++++ test/run-script/scenarios.json | 10 ++++++++++ test/run-script/test-backtick.sh | 11 +++++++++++ 9 files changed, 63 insertions(+), 4 deletions(-) create mode 100644 test/add-script/scenarios.json create mode 100755 test/add-script/test-backtick.sh create mode 100644 test/run-script/scenarios.json create mode 100755 test/run-script/test-backtick.sh diff --git a/README.md b/README.md index e02c0d1..9c99dfe 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ | Feature | Description | Install method | Version | | ------- | ----------- | -------------- | ------- | -| [add-script](https://github.com/devcontainer-community/devcontainer-features/tree/main/src/add-script) | Add a script from a URL or inline text to /usr/local/bin during devcontainer build | custom | 1.0.0 | +| [add-script](https://github.com/devcontainer-community/devcontainer-features/tree/main/src/add-script) | Add a script from a URL or inline text to /usr/local/bin during devcontainer build | custom | 1.1.0 | | [alexpasmantier/television](https://github.com/devcontainer-community/devcontainer-features/tree/main/src/alexpasmantier-television) | `tv` — fuzzy finder for files, text, and more | gh release | 1.0.1 | | [ankitpokhrel/jira-cli](https://github.com/devcontainer-community/devcontainer-features/tree/main/src/ankitpokhrel-jira-cli) | `jira` — feature-rich interactive Jira command line client | gh release | 1.0.0 | | [apt-build-essential](https://github.com/devcontainer-community/devcontainer-features/tree/main/src/apt-build-essential) | `gcc`/`g++`/`make` — C/C++ compiler toolchain via the build-essential package | apt | 1.0.0 | @@ -78,7 +78,7 @@ | [rclone](https://github.com/devcontainer-community/devcontainer-features/tree/main/src/rclone.org) | `rclone` — sync files to/from cloud storage | gh release | 1.0.1 | | [restic.net](https://github.com/devcontainer-community/devcontainer-features/tree/main/src/restic.net) | `restic` — fast, encrypted, deduplicated backups | gh release | 1.0.1 | | [ripgrep](https://github.com/devcontainer-community/devcontainer-features/tree/main/src/ripgrep) | `rg` — fast grep alternative (ripgrep) | gh release | 1.0.1 | -| [run-script](https://github.com/devcontainer-community/devcontainer-features/tree/main/src/run-script) | Run a script from a URL or inline text during devcontainer build | custom | 1.0.0 | +| [run-script](https://github.com/devcontainer-community/devcontainer-features/tree/main/src/run-script) | Run a script from a URL or inline text during devcontainer build | custom | 1.1.0 | | [schpet/linear-cli](https://github.com/devcontainer-community/devcontainer-features/tree/main/src/schpet-linear-cli) | `linear` — CLI to access linear.com issue tracker | gh release | 1.0.2 | | [smallstep.com](https://github.com/devcontainer-community/devcontainer-features/tree/main/src/smallstep.com) | `step` — zero-trust security toolkit and CA | gh release | 1.0.2 | | [socket.dev/sfw-free](https://github.com/devcontainer-community/devcontainer-features/tree/main/src/socket.dev-sfw-free) | `sfw` — network security proxy that blocks malicious dependencies | gh release | 1.0.0 | diff --git a/src/add-script/devcontainer-feature.json b/src/add-script/devcontainer-feature.json index e9d330f..70a11c8 100644 --- a/src/add-script/devcontainer-feature.json +++ b/src/add-script/devcontainer-feature.json @@ -1,7 +1,7 @@ { "name": "add-script", "id": "add-script", - "version": "1.0.0", + "version": "1.1.0", "description": "Add a script from a URL or inline text to /usr/local/bin during devcontainer build", "documentationURL": "https://github.com/devcontainer-community/devcontainer-features/tree/main/src/add-script", "options": { diff --git a/src/add-script/install.sh b/src/add-script/install.sh index b01f1d9..18b7b07 100755 --- a/src/add-script/install.sh +++ b/src/add-script/install.sh @@ -31,6 +31,14 @@ echo_banner() { } install() { + # Re-read SCRIPT from the env file verbatim to prevent shell evaluation of + # backticks: the devcontainer CLI wraps option values in double quotes in the + # env file and then sources it, which causes bash to evaluate backticks. + # Reading the file directly with awk avoids this evaluation. + if [ -f ./devcontainer-features.env ]; then + SCRIPT=$(awk '/^SCRIPT="/{sub(/^SCRIPT="/,"");v=$0;f=1;next}f{v=v"\n"$0}END{if(f){sub(/"$/,"",v);printf"%s",v}}' ./devcontainer-features.env) + fi + if [ -z "${NAME}" ]; then echo "No script name provided. Nothing to do." return 0 diff --git a/src/run-script/devcontainer-feature.json b/src/run-script/devcontainer-feature.json index a832a76..23cc909 100644 --- a/src/run-script/devcontainer-feature.json +++ b/src/run-script/devcontainer-feature.json @@ -1,7 +1,7 @@ { "name": "run-script", "id": "run-script", - "version": "1.0.0", + "version": "1.1.0", "description": "Run a script from a URL or inline text during devcontainer build", "documentationURL": "https://github.com/devcontainer-community/devcontainer-features/tree/main/src/run-script", "options": { diff --git a/src/run-script/install.sh b/src/run-script/install.sh index 2c37d8f..42c2b14 100755 --- a/src/run-script/install.sh +++ b/src/run-script/install.sh @@ -31,6 +31,14 @@ echo_banner() { } install() { + # Re-read SCRIPT from the env file verbatim to prevent shell evaluation of + # backticks: the devcontainer CLI wraps option values in double quotes in the + # env file and then sources it, which causes bash to evaluate backticks. + # Reading the file directly with awk avoids this evaluation. + if [ -f ./devcontainer-features.env ]; then + SCRIPT=$(awk '/^SCRIPT="/{sub(/^SCRIPT="/,"");v=$0;f=1;next}f{v=v"\n"$0}END{if(f){sub(/"$/,"",v);printf"%s",v}}' ./devcontainer-features.env) + fi + if [ -n "${URL}" ] && [ -n "${SCRIPT}" ]; then printf >&2 '=== [ERROR] Both "url" and "script" options are provided. Please provide only one.\n' exit 1 diff --git a/test/add-script/scenarios.json b/test/add-script/scenarios.json new file mode 100644 index 0000000..3260b7f --- /dev/null +++ b/test/add-script/scenarios.json @@ -0,0 +1,11 @@ +{ + "test-backtick": { + "image": "debian:latest", + "features": { + "add-script": { + "name": "test-backtick", + "script": "#!/bin/bash\necho `hostname`" + } + } + } +} diff --git a/test/add-script/test-backtick.sh b/test/add-script/test-backtick.sh new file mode 100755 index 0000000..e1d1267 --- /dev/null +++ b/test/add-script/test-backtick.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +set -e + +source dev-container-features-test-lib + +check "test-backtick script exists" test -f /usr/local/bin/test-backtick +check "test-backtick script is executable" test -x /usr/local/bin/test-backtick +check "test-backtick script contains verbatim backtick" grep -qF '`hostname`' /usr/local/bin/test-backtick + +reportResults diff --git a/test/run-script/scenarios.json b/test/run-script/scenarios.json new file mode 100644 index 0000000..7879d0d --- /dev/null +++ b/test/run-script/scenarios.json @@ -0,0 +1,10 @@ +{ + "test-backtick": { + "image": "debian:latest", + "features": { + "run-script": { + "script": "echo backtick_test=`hostname` > /tmp/devcontainer-run-script-test.txt" + } + } + } +} diff --git a/test/run-script/test-backtick.sh b/test/run-script/test-backtick.sh new file mode 100755 index 0000000..688648d --- /dev/null +++ b/test/run-script/test-backtick.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +set -e + +source dev-container-features-test-lib + +check "run-script created output file" test -f /tmp/devcontainer-run-script-test.txt +check "run-script output contains expected prefix" grep -q 'backtick_test=' /tmp/devcontainer-run-script-test.txt +check "run-script output contains non-empty value" grep -qv 'backtick_test=$' /tmp/devcontainer-run-script-test.txt + +reportResults From c2ea83f720f99bef6ba18af833bcaedb7075c917 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 31 Mar 2026 10:24:48 +0000 Subject: [PATCH 3/3] Fix tmpScript unbound variable in run-script EXIT trap Agent-Logs-Url: https://github.com/devcontainer-community/devcontainer-features/sessions/c2ae8d45-408c-4b82-ad03-40b5db72a1d9 Co-authored-by: sebst <592313+sebst@users.noreply.github.com> --- src/run-script/install.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/src/run-script/install.sh b/src/run-script/install.sh index 42c2b14..ee3aa83 100755 --- a/src/run-script/install.sh +++ b/src/run-script/install.sh @@ -49,7 +49,6 @@ install() { return 0 fi - local tmpScript tmpScript="$(mktemp)" trap 'rm -f "${tmpScript}"' EXIT