Skip to content

fix(init): stop plugin-sourced shell opts leaking into the caller's shell - #44

Open
alfred-agent-broker[bot] wants to merge 3 commits into
nextfrom
fix/plugin-source-opts-leak
Open

alfred-agent-broker[bot] wants to merge 3 commits into
nextfrom
fix/plugin-source-opts-leak

Conversation

@alfred-agent-broker

Copy link
Copy Markdown

Summary

  • Board 20a1e3d2: a %dante/run-recorder plugin's file-scope set -u leaked
    nounset into the operator's interactive shell on every fresh shell (shy's
    init.bash sources every installed script's entry.sh directly into the
    current shell, not a subprocess). Symptom: zypper's bash completion errored
    ZYPPER_CMDLIST: unbound variable, and every shy completion was affected.
  • _shy_safe_source (new helper in init/init.bash / internal/cmd/init.bash)
    saves $- before each source call and restores u/e/pipefail afterward if
    the sourced file changed them. Used in _shy_source_flat and
    _shy_source_installed_scripts in place of bare source — this protects
    against every current AND future plugin, not just the one that triggered
    this bug.
  • The %dante/run-recorder plugin itself is fixed at its own source in a
    companion dante (Forgejo) repo PR, scoping set -u per-function via
    local - instead of file scope.

Test plan

  • bash -c 'set +u; source init/init.bash >/dev/null 2>&1; [[ $- == *u* ]] && echo LEAK || echo CLEAN' → CLEAN
  • Fresh source init.bash still succeeds; shy --help still works
  • Spot-checked a run-recorder function (rr-session-init / rr-status)
    still runs correctly with strict mode active inside the function

Co-Authored-By: Claude Opus 4.8 noreply@anthropic.com

Any sourced plugin script that changes u/e/pipefail (e.g. a file-scope
`set -u`) leaked those options into whatever shell sourced init.bash --
confirmed via %dante/run-recorder's session-recorder.sh, which broke
bash completions in the operator's interactive shell ("ZYPPER_CMDLIST:
unbound variable" from zypper's completion, and every shy completion
affected the same way) once nounset leaked out of a sourced entry.sh.

Add _shy_safe_source: sources a file, then restores u/e/pipefail to
whatever they were immediately before the source if the sourced file
changed them. Used in place of bare `source` in both
_shy_source_flat and _shy_source_installed_scripts, so this protects
against every current AND future plugin, not just the one that
triggered this fix (which is fixed at its own source in a companion
%dante/run-recorder change).

Board: 20a1e3d2.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@Mr-RedHat-fb
Mr-RedHat-fb self-requested a review July 21, 2026 13:04
Comment thread init/init.bash
# init.bash, breaking unrelated things (e.g. bash completions tripping over
# `set -u` on an unset variable). Belt-and-suspenders: protects against every
# current AND future plugin, on top of any per-plugin fix.
_shy_safe_source() {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Comment thread internal/cmd/init.bash
# init.bash, breaking unrelated things (e.g. bash completions tripping over
# `set -u` on an unset variable). Belt-and-suspenders: protects against every
# current AND future plugin, on top of any per-plugin fix.
_shy_safe_source() {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@sonarqubecloud

Copy link
Copy Markdown

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