ECS Exec session transcript logging broken on `script` command (util-linux) ≥ 2.39 — script: unexpected number of arguments
- Dominant language
- Go
- Stars
- 1.2k
- Forks
- 357
- PR merge metrics
- No merged PRs in 30d
Description
## Summary
`ssm-session-worker` calls `script(1)` with a legacy positional argument order that was
rejected starting in util-linux v2.39. ECS Exec session logging silently fails on any
container image shipping util-linux ≥ 2.42. This is distinct from #653 (missing binary) —
the binary is present but the invocation is wrong.
## Error
From `/var/log/amazon/ssm/errors.log` inside the container:
```
Failed to generate transcript with the following errors:
exit status 1: script: unexpected number of arguments
exit status 1: script: unexpected number of arguments
```
No log stream is created in CloudWatch and no session log is uploaded anywhere. Sessions
appear to succeed but produce no audit log.
## Root cause
[`generateLogData` in `shell_unix.go` lines 347–356](https://github.com/aws/amazon-ssm-agent/blob/mainline/agent/session/shell/shell_unix.go#L347-L356)
calls `script` in the legacy BSD positional form:
```go
// Form A (line 347): script -c ""
cmdWithFlag := exec.CommandContext(ctx, startRecordSessionCmd, p.logger.logFilePath, scriptFlag, loggerCmd)
// Form B (line 356, fallback): script cat
cmdWithoutFlag := exec.CommandContext(ctx, startRecordSessionCmd, p.logger.logFilePath, catCmd, p.logger.ipcFilePath)
```
util-linux commit [`ec96a89`](https://github.com/util-linux/util-linux/commit/ec96a89ed9551ffacfc58b3056c8070444e3a2f3)
("script: abort if unused arguments are given", **21 Nov 2022**, released in v2.39) tightened
argument parsing. The situation by version:
| Form | util-linux 2.39.x | util-linux 2.42+ |
|------|:-----------------:|:----------------:|
| `script -c "cmd"` (Form A) | ✓ | ✗ |
| `script prog args` (Form B) | ✗ | ✗ |
Both forms fail on 2.42+. Form B fails on all versions ≥ 2.39.
Reproducing the exact SSM agent invocations:
```
$ docker run --rm ubuntu:24.04 bash -c '
apt-get install -y -q util-linux > /dev/null 2>&1
echo "data" > /tmp/ipc
echo "=== Form A (SSM primary): script -c ==="
script /tmp/test.log -c "echo hello" 2>&1 || true
echo "=== Form B (SSM fallback): script cat ==="
script /tmp/test.log cat /tmp/ipc 2>&1 || true
echo "=== Note: -- separator requires 2.41+, also fails here ==="
script -q /tmp/test.log -- cat /tmp/ipc 2>&1 || true
'
=== Form A (SSM primary): script -c ===
Script started, output log file is '/tmp/test.log'.
hello
Script done.
=== Form B (SSM fallback): script cat ===
script: unexpected number of arguments
Try 'script --help' for more information.
=== Note: -- separator requires 2.41+, also fails here ===
script: unexpected number of arguments
Try 'script --help' for more information.
```
Form A happens to still work on 2.39.x because options after the filename are still
accepted, but it fails on 2.42+ (Wolfi/Chainguard). Form B fails on all versions ≥ 2.39.
## Fix
Update [`generateLogData` in `shell_unix.go`](https://github.com/aws/amazon-ssm-agent/blob/mainline/agent/session/shell/shell_unix.go#L347-L356)
to use `-c` with the logfile last. This satisfies util-linux's strict parser (≥ 2.39)
while remaining valid on all older versions, since pre-2.39 accepted options in any order:
```go
// Form A — was: script -c ""
cmdWithFlag := exec.CommandContext(ctx, startRecordSessionCmd, "-q", "-c", loggerCmd, p.logger.logFilePath)
// Form B — was: script cat
cmdWithoutFlag := exec.CommandContext(ctx, startRecordSessionCmd, "-q", "-c",
fmt.Sprintf("%s %s", catCmd, p.logger.ipcFilePath), p.logger.logFilePath)
```
## Workaround
Place the following shim at `/usr/local/bin/script` (ahead of `/usr/bin/script` in `$PATH`):
```sh
#!/bin/sh
# Translates amazon-ssm-agent's legacy script(1) invocation to util-linux >= 2.39 syntax.
# Note: the -- separator requires 2.41+, so we normalise both forms to -c.
file=$1
shift
if [ "$1" = "-c" ]; then
exec /usr/bin/script -q -c "$2" "$file"
fi
exec /usr/bin/script -q -c "$*" "$file"
```
## Environment
- ECS Exec (Session Manager) with CloudWatch Logs transcript logging
- Container: Wolfi/Chainguard (util-linux 2.42); also reproduced on Ubuntu 24.04 (util-linux 2.39.3)
- amazon-ssm-agent: 3.3.0.0
```
/managed-agents/execute-command/amazon-ssm-agent --version
SSM Agent version: 3.3.0.0
```
Contributor guide
Research direction
Read generateLogData in agent/session/shell/shell_unix.go, especially lines 347–356, and reproduce both script invocations with util-linux 2.39 or newer. Verify that transcript logging works on affected images and remains compatible with older util-linux versions, including both the primary and fallback paths.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go, linux
- Domain
- operating-systems
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 76/100