Summary
task validate / scripts/validate-plugins.sh cannot run to completion on a stock macOS machine. CONTRIBUTING asks contributors to run it before opening a PR, and .pre-commit-config.yaml invokes it via the plugin-ci hook on every commit, so a macOS contributor hits this on their first commit in a file they did not touch.
There are two independent causes. The second only becomes visible once the first is fixed.
Steps to reproduce
- On macOS with the system bash (
/bin/bash, 3.2.57 — what #!/usr/bin/env bash resolves to by default)
git clone https://github.com/Keeper-Security/keeper-agent-kit && cd keeper-agent-kit
bash scripts/validate-plugins.sh
Actual behavior
Cause 1 — mapfile is a bash 4+ builtin (6 call sites: lines 165, 166, 188, 344, 363, 495).
$ bash scripts/validate-plugins.sh
== Plugin manifests (Claude + Cursor) ==
✓ Claude plugin.json (1.2.0) [x6 ok]
== Root marketplaces ==
--- Claude ---
scripts/validate-plugins.sh: line 165: mapfile: command not found
EXIT CODE: 127
$ /bin/bash --version
GNU bash, version 3.2.57(1)-release (arm64-apple-darwin25)
Cause 2 — quadratic pattern substitution. With mapfile replaced, validation then runs indefinitely. ${var//[$' \t\r\n']/} (lines 105 and 296) applied to a multi-kilobyte string hits bash 3.2's quadratic substitution path:
body length: 11,353 chars (plugins/keeper-admin/skills/keeper-admin/SKILL.md)
bash 3.2 ${body//[$' \t\r\n']/} -> still running after 25s
bash 3.2 printf | tr -d ' \t\r\n' -> 0s
Expected behavior
The script completes and reports pass/fail on the platform CONTRIBUTING targets.
Suggested fix
Three changes, no behavioural difference on bash 4+:
- the 6
mapfile -t X < <(cmd) sites -> X=(); while IFS= read -r _line; do X+=("$_line"); done < <(cmd)
- the 2
${var//[$' \t\r\n']/} uses -> $(printf '%s' "$var" | tr -d ' \t\r\n')
Verified locally on bash 3.2.57: the script then prints ✓ All validations passed and exits 0.
Why this has not surfaced
The workflows that validated plugins and skills (validate-plugin.yml, test-skills.yml) were removed in efccb1a when the tree moved from skills/** to plugins/*/skills/* and the path filters stopped matching. Validation now runs only in the local pre-commit hook, so a contributor on macOS gets no CI signal that their change was fine. Restoring a CI job that runs this script would also catch regressions of this kind. Happy to open that as a separate issue if it is useful.
Environment
- OS: macOS 26 (Darwin 25.2.0, arm64), system bash 3.2.57
- Agent / tool: n/a — repo tooling
- Repo area:
scripts/validate-plugins.sh, .pre-commit-config.yaml, Taskfile.yaml
Additional context
Happy to open a PR with the fix above if that is welcome.
Summary
task validate/scripts/validate-plugins.shcannot run to completion on a stock macOS machine. CONTRIBUTING asks contributors to run it before opening a PR, and.pre-commit-config.yamlinvokes it via theplugin-cihook on every commit, so a macOS contributor hits this on their first commit in a file they did not touch.There are two independent causes. The second only becomes visible once the first is fixed.
Steps to reproduce
/bin/bash, 3.2.57 — what#!/usr/bin/env bashresolves to by default)git clone https://github.com/Keeper-Security/keeper-agent-kit && cd keeper-agent-kitbash scripts/validate-plugins.shActual behavior
Cause 1 —
mapfileis a bash 4+ builtin (6 call sites: lines 165, 166, 188, 344, 363, 495).Cause 2 — quadratic pattern substitution. With
mapfilereplaced, validation then runs indefinitely.${var//[$' \t\r\n']/}(lines 105 and 296) applied to a multi-kilobyte string hits bash 3.2's quadratic substitution path:Expected behavior
The script completes and reports pass/fail on the platform CONTRIBUTING targets.
Suggested fix
Three changes, no behavioural difference on bash 4+:
mapfile -t X < <(cmd)sites ->X=(); while IFS= read -r _line; do X+=("$_line"); done < <(cmd)${var//[$' \t\r\n']/}uses ->$(printf '%s' "$var" | tr -d ' \t\r\n')Verified locally on bash 3.2.57: the script then prints
✓ All validations passedand exits 0.Why this has not surfaced
The workflows that validated plugins and skills (
validate-plugin.yml,test-skills.yml) were removed inefccb1awhen the tree moved fromskills/**toplugins/*/skills/*and the path filters stopped matching. Validation now runs only in the local pre-commit hook, so a contributor on macOS gets no CI signal that their change was fine. Restoring a CI job that runs this script would also catch regressions of this kind. Happy to open that as a separate issue if it is useful.Environment
scripts/validate-plugins.sh,.pre-commit-config.yaml,Taskfile.yamlAdditional context
Happy to open a PR with the fix above if that is welcome.