fix: stop staging unused ECS Exec dependencies on runners - #38
Merged
Conversation
Workflow tasks are never launched with enableExecuteCommand, but AWS's ecs-anywhere-install.sh calls exec-setup unconditionally and offers no flag to skip it, staging the SSM session binaries into /var/lib/ecs/deps/execute-command on every registration. Those binaries are never executed and keep surfacing in customer vulnerability scans, currently CVE-2026-71556 in the go-git version vendored by amazon-ssm-agent 3.3.4624.0. Neutralise the installer's exec-setup call before running it, and sweep the directory afterwards in case the call site moves. The ECS agent treats these dependencies as optional: with the directory absent it starts normally and only stops advertising ecs.capability.execute-command, which we never use.
arunim2405
approved these changes
Aug 19, 2026
There was a problem hiding this comment.
Pull request overview
This PR removes AWS ECS Exec “execute-command” dependency staging from runner bootstrap by patching AWS’s ecs-anywhere-install-latest.sh at runtime and sweeping any previously staged binaries from disk, reducing false-positive vulnerability findings and removing an unused capability advertisement.
Changes:
- Add a bootstrap-time rewrite to neutralize the installer’s unconditional
exec-setupcall and prevent ECS Exec SSM binaries from being downloaded. - Add a post-registration cleanup step to remove the ECS Exec dependency directory if it exists.
- Add unit tests + fixtures and document the rationale and the new path override seam.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| main.sh | Adds disable_ecs_exec_setup and remove_ecs_exec_deps, wires them into registration, and introduces ECS_EXEC_DEPS_DIR as an overridable path. |
| test/unit/ecs_exec_deps.bats | Adds unit coverage for installer rewriting, cleanup behavior, idempotency, and wiring in register_instance. |
| test/fixtures/ecs/ecs-anywhere-install.sh.sample | Adds a minimal installer fixture capturing the exec-setup definition and unconditional call. |
| test/helpers/load.bash | Redirects ECS_EXEC_DEPS_DIR into the per-test temp dir for safe rm -rf usage. |
| test/README.md | Documents the new ECS_EXEC_DEPS_DIR override and why it matters for test safety. |
| README.md | Documents why ECS Exec is unused and why the behavior is intentionally not configurable. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
ECS_EXEC_DEPS_DIR is overridable for testing, which made remove_ecs_exec_deps the only place in the script where an env var supplies a whole rm -rf path rather than a fixed literal, and it runs as root. A stray "/" or "/etc" in the environment would have been destructive. Add is_ecs_exec_deps_path, accepting only an absolute path that names a deps directory, and refuse anything else with a logged no-op. Kept as a pure predicate so the catastrophic inputs are unit-testable without any test pointing rm at them; the integration test uses a sentinel inside the test tmpdir so a regression destroys a canary rather than anything real.
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Summary
Stops the runner bootstrap from staging AWS's ECS Exec (
execute-command) SSM binaries on disk, and removes the directory if a previous install left it there. ECS Exec is not used by any StackGuardian workflow, so these binaries were never executed — they only added unused code that customer vulnerability scanners flag.Motivation & Context
A customer's Wiz scan flagged CVE-2026-71556 (
go-gitv5.19.1, High) in/var/lib/ecs/deps/execute-command/bin/3.3.4624.0/ssm-session-workeron their private runners, and asked whether the platform requires ECS Exec.It does not.
enableExecuteCommandis not set on anyRunTaskcall — EXTERNAL, SHARED-EXTERNAL, EC2 or FARGATE — so ECS Exec is off for every workflow task we launch. The binaries arrive anyway:main.shruns AWS's stockecs-anywhere-install.sh, which callsexec-setupunconditionally in its main flow, hardcodingBINARY_VERSION="3.3.4624.0". AWS exposes no flag to skip it, so the only way to stop it is to intervene ourselves.The ECS agent treats these dependencies as optional. With the directory absent,
appendExecCapabilitiesreturns cleanly and the agent simply stops advertisingecs.capability.execute-command— which is a small security gain, since a runner that does not advertise the capability cannot have an exec session opened against it.Changes Made
main.sh: adddisable_ecs_exec_setup, which rewrites the installer's bare top-levelexec-setupcall to a no-op before the script runs. This is the primary mechanism — the binaries are never downloaded, which also removes a large tarball fetch from every bootstrap.main.sh: addremove_ecs_exec_deps, which deletesECS_EXEC_DEPS_DIRafterwards. Backstop for the case where AWS restructures the installer and the rewrite no longer matches.main.sh: wire both intoregister_instanceunconditionally — the rewrite after the existing shebang sanity check, the sweep once registration settles. No flag gates this; there is no supported setup in which a runner needs those binaries.main.sh: addECS_EXEC_DEPS_DIRto the overridable filesystem-locations block, following the existing convention so tests can redirect it.main.sh: addis_ecs_exec_deps_path, a guard on the removal. BecauseECS_EXEC_DEPS_DIRis overridable, this was the only place in the script where an env var supplied a wholerm -rfpath rather than a fixed literal, while running as root — a stray/or/etcin the environment would have been destructive. Only an absolute path naming a deps directory is accepted; anything else is a logged no-op. Raised by Copilot in review.return 0explicitly:debug()isis_debug && printf, so it returns non-zero whenever--debugis off and must not become a function's exit status.test/unit/ecs_exec_deps.bats: 15 tests covering the rewrite, the sweep, idempotency, the no-exec-setupand indented-mention cases, the production default path, and that both calls are present inregister_instance.test/fixtures/ecs/ecs-anywhere-install.sh.sample: trimmed stand-in for AWS's installer preserving theexec-setupdefinition, its helpers, and the unconditional top-level call.test/helpers/load.bash: redirectECS_EXEC_DEPS_DIRinto the per-test tmpdir. This is a safety requirement, not a convenience — without it a test run on a Linux host wouldrm -rfthe real/var/lib/ecs/deps/execute-command.README.md/test/README.md: document why ECS Exec is unused and why this is not configurable; add the new path override to the seam contract.Testing
make lintclean (shellcheck)is_ecs_exec_deps_pathrejects/, bare system directories, relative paths, empty/unset, and near-miss names; verified live thatECS_EXEC_DEPS_DIR=/is refused and returns cleanlyecs-anywhere-install-latest.sh: produces a one-line diff at line 774, leaves theexec-setup()definition intact, result still passesbash -necs.capability.execute-commandabsent, deps directory never created, workflow runs completed normallysystemctl restart ecsas an attribute update (same container instance ARN, no duplicate registration), workflow runs passed on both sidesRisks & Edge Cases
amazon-ssm-agentpackage at/usr/bin/ssm-session-workerand/usr/bin/ssm-agent-worker, carrying the samego-git v5.19.1. That package is required for ECS Anywhere registration and cannot be removed. Worth stating plainly in any customer-facing summary, so this is not read as "fully fixed"./usr/bincopy is installed from thelatestS3 path rather than a pinned version, so it self-heals once AWS ships a build with patchedgo-git. The copy removed here is the one that would not self-heal, since AWS hardcodes its version in the installer.exec-setupcall the rewrite silently no-ops and the sweep handles it; both are logged under--debug.rm -rf /var/lib/ecs/deps/execute-command, which is safe to run against a live agent.Deployment Notes