diff --git a/scripts/gh.sh b/scripts/gh.sh index 6113a75be6..06c15c847b 100755 --- a/scripts/gh.sh +++ b/scripts/gh.sh @@ -11,6 +11,15 @@ set -euo pipefail # ./scripts/gh.sh search issues "search query" --limit 10 # ./scripts/gh.sh label list --limit 100 +export GH_HOST=github.com + +REPO="${GH_REPO:-${GITHUB_REPOSITORY:-}}" +if [[ -z "$REPO" || "$REPO" == */*/* || "$REPO" != */* ]]; then + echo "Error: GH_REPO or GITHUB_REPOSITORY must be set to owner/repo format (e.g., GITHUB_REPOSITORY=anthropics/claude-code)" >&2 + exit 1 +fi +export GH_REPO="$REPO" + ALLOWED_FLAGS=(--comments --state --limit --label) FLAGS_WITH_VALUES=(--state --limit --label) @@ -21,6 +30,7 @@ case "$CMD" in "issue view"|"issue list"|"search issues"|"label list") ;; *) + echo "Error: only 'issue view', 'issue list', 'search issues', 'label list' are allowed (e.g., ./scripts/gh.sh issue view 123)" >&2 exit 1 ;; esac @@ -45,6 +55,7 @@ for arg in "$@"; do fi done if [[ "$matched" == false ]]; then + echo "Error: only --comments, --state, --limit, --label flags are allowed (e.g., ./scripts/gh.sh issue list --state open --limit 20)" >&2 exit 1 fi FLAGS+=("$arg") @@ -62,24 +73,24 @@ for arg in "$@"; do fi done -REPO="${GH_REPO:-${GITHUB_REPOSITORY:-}}" - if [[ "$CMD" == "search issues" ]]; then - if [[ -z "$REPO" ]]; then - exit 1 - fi QUERY="${POSITIONAL[0]:-}" QUERY_LOWER=$(echo "$QUERY" | tr '[:upper:]' '[:lower:]') if [[ "$QUERY_LOWER" == *"repo:"* || "$QUERY_LOWER" == *"org:"* || "$QUERY_LOWER" == *"user:"* ]]; then + echo "Error: search query must not contain repo:, org:, or user: qualifiers (e.g., ./scripts/gh.sh search issues \"bug report\" --limit 10)" >&2 exit 1 fi gh "$SUB1" "$SUB2" "$QUERY" --repo "$REPO" "${FLAGS[@]}" +elif [[ "$CMD" == "issue view" ]]; then + if [[ ${#POSITIONAL[@]} -ne 1 ]] || ! [[ "${POSITIONAL[0]}" =~ ^[0-9]+$ ]]; then + echo "Error: issue view requires exactly one numeric issue number (e.g., ./scripts/gh.sh issue view 123)" >&2 + exit 1 + fi + gh "$SUB1" "$SUB2" "${POSITIONAL[0]}" "${FLAGS[@]}" else - # Reject URLs in positional args to prevent cross-repo access - for pos in "${POSITIONAL[@]}"; do - if [[ "$pos" == http://* || "$pos" == https://* ]]; then - exit 1 - fi - done - gh "$SUB1" "$SUB2" "${POSITIONAL[@]}" "${FLAGS[@]}" + if [[ ${#POSITIONAL[@]} -ne 0 ]]; then + echo "Error: issue list and label list do not accept positional arguments (e.g., ./scripts/gh.sh issue list --state open, ./scripts/gh.sh label list --limit 100)" >&2 + exit 1 + fi + gh "$SUB1" "$SUB2" "${FLAGS[@]}" fi