gh-copilot icon indicating copy to clipboard operation
gh-copilot copied to clipboard

[BUG]: `ghcs` accidentally deleted shell history

Open WhoSayIn opened this issue 1 year ago • 9 comments
trafficstars

What happened?

Tried to use the alias ghcs on MacOS Sonoma 14.5 with zsh. After executing a simple command that was suggested, all my command line history got deleted. (suggested code had nothing to do with deleting the history. It was the first time ever I use this.)

Versions

gh v2.57.0, gh-copilot1.0.5 (2024-09-12)

Relevant terminal output

>  ghcs "print current date time"


Welcome to GitHub Copilot in the CLI!
version 1.0.5 (2024-09-12)

I'm powered by AI, so surprises and mistakes are possible. Make sure to verify any generated code or suggestions, and share feedback so that we can learn and improve. For more information, see https://gh.io/gh-copilot-transparency

Suggestion:

  date "+%Y-%m-%d %H:%M:%S"

? Select an option
> Execute command

? Are you sure you want to execute the suggested command?
> Yes
History file deleted.
omz_history:fc:14: event not found: date "+%Y-%m-%d %H:%M:%S"

2024-09-30 16:18:43

WhoSayIn avatar Sep 30 '24 14:09 WhoSayIn

Oof, that's interesting. Sorry about that. Can I check that you've got history aliased to omz_history or something?

➜  ~ type -a history
history is an alias for omz_history
history is a shell builtin

Also, can I check which shell alias you are actually using via:

which ghcs

Please just copy the contents in.

I suspect what's happening here is that you are using the bash aliases and it is conflicting in some way I don't yet understand with the omz_history oh-my-zsh plugin.

williammartin avatar Sep 30 '24 14:09 williammartin

Hi @williammartin

No worries, I had a very recent backup :)

And yes, my history is indeed aliased to omz_history

> type -a history
history is an alias for omz_history
history is a shell builtin

and this the output for the which ghcs;

> which ghcs

ghcs () {
        TARGET="shell"
        local GH_DEBUG="$GH_DEBUG"
        local GH_HOST="$GH_HOST"
        read -r -d '' __USAGE <<EOF
Wrapper around \`gh copilot suggest\` to suggest a command based on a natural language description of the desired output effort.
Supports executing suggested commands if applicable.

USAGE
  $FUNCNAME [flags] <prompt>

FLAGS
  -d, --debug              Enable debugging
  -h, --help               Display help usage
      --hostname           The GitHub host to use for authentication
  -t, --target target      Target for suggestion; must be shell, gh, git
                           default: "$TARGET"

EXAMPLES

- Guided experience
  $ $FUNCNAME

- Git use cases
  $ $FUNCNAME -t git "Undo the most recent local commits"
  $ $FUNCNAME -t git "Clean up local branches"
  $ $FUNCNAME -t git "Setup LFS for images"

- Working with the GitHub CLI in the terminal
  $ $FUNCNAME -t gh "Create pull request"
  $ $FUNCNAME -t gh "List pull requests waiting for my review"
  $ $FUNCNAME -t gh "Summarize work I have done in issues and pull requests for promotion"

- General use cases
  $ $FUNCNAME "Kill processes holding onto deleted files"
  $ $FUNCNAME "Test whether there are SSL/TLS issues with github.com"
  $ $FUNCNAME "Convert SVG to PNG and resize"
  $ $FUNCNAME "Convert MOV to animated PNG"
EOF
        local OPT OPTARG OPTIND
        while getopts "dht:-:" OPT
        do
                if [ "$OPT" = "-" ]
                then
                        OPT="${OPTARG%%=*}"
                        OPTARG="${OPTARG#"$OPT"}"
                        OPTARG="${OPTARG#=}"
                fi
                case "$OPT" in
                        (debug | d) GH_DEBUG=api  ;;
                        (help | h) echo "$__USAGE"
                                return 0 ;;
                        (hostname) GH_HOST="$OPTARG"  ;;
                        (target | t) TARGET="$OPTARG"  ;;
                esac
        done
        shift "$((OPTIND-1))"
        TMPFILE="$(mktemp -t gh-copilotXXXXXX)"
        trap 'rm -f "$TMPFILE"' EXIT
        if GH_DEBUG="$GH_DEBUG" GH_HOST="$GH_HOST" gh copilot suggest -t "$TARGET" "$@" --shell-out "$TMPFILE"
        then
                if [ -s "$TMPFILE" ]
                then
                        FIXED_CMD="$(cat $TMPFILE)"
                        history -s $(history 1 | cut -d' ' -f4-)
                        history -s "$FIXED_CMD"
                        echo
                        eval "$FIXED_CMD"
                fi
        else
                return 1
        fi
}

WhoSayIn avatar Oct 02 '24 08:10 WhoSayIn

@WhoSayIn thanks for that.

This looks like the bash alias we ship. Did you copy and paste this from somewhere, or are you perhaps executing gh copilot alias --bash in your zsh startup scripts?

Obviously we shouldn't be deleting your shell history either way, I'm just trying to put the pieces together here. I have a working theory about the omz_history command acting differently and thus history -s $(history 1 | cut -d' ' -f4-) providing strange results.

williammartin avatar Oct 02 '24 09:10 williammartin

Hi @williammartin,

No, I didn't copy paste it from somewhere else :) initially I installed github cli by brew install gh and then I installed the copilot extension by running gh extension install github/gh-copilot

Although while I'm typing this comment, I realized I made a mistake and while I was setting up the aliases, I used the bash section in this readme. But I use zsh as my shell.

So this was in my aliases;

eval "$(gh copilot alias -- bash)"

I suspect this might be the reason.

WhoSayIn avatar Oct 03 '24 08:10 WhoSayIn

I can confirm it was that. I was able to reproduce it.

When using;

eval "$(gh copilot alias -- bash)"

in my zsh, it does delete the history anytime I execute a suggested command.

When using;

eval "$(gh copilot alias -- zsh)"

It works as expected.

So you can decide to close this issue but maybe some safeguard can be implemented for people like me :)

WhoSayIn avatar Oct 03 '24 08:10 WhoSayIn

Thanks!

in my zsh, it does delete the history anytime I execute a suggested command.

Can you check what the output of history 1 | cut -d' ' -f4- is? In particular, I'm interested whether you see -c anywhere, maybe grep for it? My working theory is that because history on zsh is returning all the history commands rather than the last one, somewhere in there it probably has a -c flag which is causing the history to be cleared.

By the way if you updated omz_history, about 3 months ago someone put a prompt in so that you need to confirm history clearing.

So you can decide to close this issue but maybe some safeguard can be implemented for people like me :)

I definitely think we should figure out something here, seems very risky!

williammartin avatar Oct 03 '24 09:10 williammartin

Hi @williammartin ,

history 1 | cut -d' ' -f4- simply returns all my history, maybe that's the issue? history 1 does not return the last history record as intended, I assume it's because I'm using omz_history (a part of oh-my-zshell)

Just updated oh-my-zshell getting help from ghcs :) and it worked as expected, although I got some warnings;

> ghcs "update oh-my-zsh"

Welcome to GitHub Copilot in the CLI!
version 1.0.5 (2024-09-12)

I'm powered by AI, so surprises and mistakes are possible. Make sure to verify any generated code or suggestions, and share feedback so that we can learn and improve. For more information, see https://gh.io/gh-copilot-transparency

Suggestion:

  cd ~/.oh-my-zsh
  git pull origin master

? Select an option
> Execute command

? Are you sure you want to execute the suggested command?
> Yes
ghcs:history:77: bad option: -s  <<<<<<<<<<<<<<<<<<<<
ghcs:history:77: bad option: -s  <<<<<<<<<<<<<<<<<<<<

WhoSayIn avatar Oct 03 '24 09:10 WhoSayIn

history 1 | cut -d' ' -f4- simply returns all my history, maybe that's the issue?

Yeh I'm just wondering if you did history 1 | cut -d' ' -f4- | grep '-c' would you see a -c flag in there somewhere? The -c flag is used to clear the history.

Just updated oh-my-zshell getting help from ghcs :) and it worked as expected, although I got some warnings;

It looks like you are still using the bash alias here?

williammartin avatar Oct 03 '24 11:10 williammartin

Hi @williammartin ,

here's the output I get;

> history 1 | cut -d' ' -f4- | grep '\-c '

kubectl get pod -n cw-app -c OMITTED
kubectl cp -c OMITTED -n OMITTED
tmux new-window -c <~/projects/OMITTED> -n <ab> \; split-window -h \; send-keys 'vim' C-m\n
kubectl cp -c OMITTED -n cw-app --context OMITTED
kubectl cp -c OMITTED -n cw-app --context OMITTED
kubectl cp -c OMITTED -n cw-app --context OMITTED
kubectl cp -c OMITTED -n cw-app --context OMITTED
kubectl cp -c OMITTED -n cw-app --context OMITTED
kubectl cp -c OMITTED -n cw-app --context OMITTED
history 1 | cut -d' ' -f4- | grep '\-c '

So I do have some -cs in my history but they are mostly kubectl parameters :) not sure if it would still clear the history, since history 1 literally returns everything in my system.

WhoSayIn avatar Oct 03 '24 15:10 WhoSayIn

@BagToad was this fixed? I believe this can be closed.

williammartin avatar Nov 06 '24 12:11 williammartin

@williammartin Yes, this is fixed but it hasn't been released yet. I'm happy to close this though - do you agree?

BagToad avatar Nov 10 '24 21:11 BagToad

Released:

  • https://github.com/github/gh-copilot/releases/tag/v1.0.6
    • Fixed command flag injection from execution of gh copilot suggest responses

      • Resolved an issue where command line options from Copilot responses could be injected into some built-in shell commands, causing unexpected behavior.

0xdevalias avatar Jan 17 '25 04:01 0xdevalias

Thanks @0xdevalias! Totally right - this is fixed in the latest 🍻

BagToad avatar Jan 22 '25 22:01 BagToad