qa
Systematically QA test a web application and fix bugs found. Runs QA testing, then iteratively fixes bugs in source code, committing each fix atomically and re-
Security score
The qa skill was audited on Mar 16, 2026 and we found 24 security issues across 4 threat categories, including 2 critical. Review the findings below before installing.
Categories Tested
Security Issues
Piping content to bash shell
| 129 | 1. Tell the user: "gstack browse needs a one-time build (~10 seconds). OK to proceed?" Then STOP and wait. |
| 130 | 2. Run: `cd <SKILL_DIR> && ./setup` |
| 131 | 3. If `bun` is not installed: `curl -fsSL https://bun.sh/install | bash` |
| 132 | |
| 133 | **Create output directories:** |
Command substitution pattern
| 24 | |
| 25 | ```bash |
| 26 | _UPD=$(~/.claude/skills/gstack/bin/gstack-update-check 2>/dev/null || .claude/skills/gstack/bin/gstack-update-check 2>/dev/null || true) |
| 27 | [ -n "$_UPD" ] && echo "$_UPD" || true |
| 28 | mkdir -p ~/.gstack/sessions |
Command substitution pattern
| 28 | mkdir -p ~/.gstack/sessions |
| 29 | touch ~/.gstack/sessions/"$PPID" |
| 30 | _SESSIONS=$(find ~/.gstack/sessions -mmin -120 -type f 2>/dev/null | wc -l | tr -d ' ') |
| 31 | find ~/.gstack/sessions -mmin +120 -type f -delete 2>/dev/null || true |
| 32 | _CONTRIB=$(~/.claude/skills/gstack/bin/gstack-config get gstack_contributor 2>/dev/null || true) |
Command substitution pattern
| 30 | _SESSIONS=$(find ~/.gstack/sessions -mmin -120 -type f 2>/dev/null | wc -l | tr -d ' ') |
| 31 | find ~/.gstack/sessions -mmin +120 -type f -delete 2>/dev/null || true |
| 32 | _CONTRIB=$(~/.claude/skills/gstack/bin/gstack-config get gstack_contributor 2>/dev/null || true) |
| 33 | ``` |
| 34 |
Command substitution pattern
| 104 | **Require clean working tree before starting:** |
| 105 | ```bash |
| 106 | if [ -n "$(git status --porcelain)" ]; then |
| 107 | echo "ERROR: Working tree is dirty. Commit or stash changes before running /qa." |
| 108 | exit 1 |
Command substitution pattern
| 115 | |
| 116 | ```bash |
| 117 | _ROOT=$(git rev-parse --show-toplevel 2>/dev/null) |
| 118 | B="" |
| 119 | [ -n "$_ROOT" ] && [ -x "$_ROOT/.claude/skills/gstack/browse/dist/browse" ] && B="$_ROOT/.claude/skills/gstack/browse/dist/browse" |
Command substitution pattern
| 146 | 1. **Project-scoped test plans:** Check `~/.gstack/projects/` for recent `*-test-plan-*.md` files for this repo |
| 147 | ```bash |
| 148 | SLUG=$(git remote get-url origin 2>/dev/null | sed 's|.*[:/]\([^/]*/[^/]*\)\.git$|\1|;s|.*[:/]\([^/]*/[^/]*\)$|\1|' | tr '/' '-') |
| 149 | ls -t ~/.gstack/projects/$SLUG/*-test-plan-*.md 2>/dev/null | head -1 |
| 150 | ``` |
Command substitution pattern
| 553 | **Project-scoped:** Write test outcome artifact for cross-session context: |
| 554 | ```bash |
| 555 | SLUG=$(git remote get-url origin 2>/dev/null | sed 's|.*[:/]\([^/]*/[^/]*\)\.git$|\1|;s|.*[:/]\([^/]*/[^/]*\)$|\1|' | tr '/' '-') |
| 556 | mkdir -p ~/.gstack/projects/$SLUG |
| 557 | ``` |
Curl to non-GitHub URL
| 129 | 1. Tell the user: "gstack browse needs a one-time build (~10 seconds). OK to proceed?" Then STOP and wait. |
| 130 | 2. Run: `cd <SKILL_DIR> && ./setup` |
| 131 | 3. If `bun` is not installed: `curl -fsSL https://bun.sh/install | bash` |
| 132 | |
| 133 | **Create output directories:** |
Access to home directory dotfiles
| 24 | |
| 25 | ```bash |
| 26 | _UPD=$(~/.claude/skills/gstack/bin/gstack-update-check 2>/dev/null || .claude/skills/gstack/bin/gstack-update-check 2>/dev/null || true) |
| 27 | [ -n "$_UPD" ] && echo "$_UPD" || true |
| 28 | mkdir -p ~/.gstack/sessions |
Access to home directory dotfiles
| 26 | _UPD=$(~/.claude/skills/gstack/bin/gstack-update-check 2>/dev/null || .claude/skills/gstack/bin/gstack-update-check 2>/dev/null || true) |
| 27 | [ -n "$_UPD" ] && echo "$_UPD" || true |
| 28 | mkdir -p ~/.gstack/sessions |
| 29 | touch ~/.gstack/sessions/"$PPID" |
| 30 | _SESSIONS=$(find ~/.gstack/sessions -mmin -120 -type f 2>/dev/null | wc -l | tr -d ' ') |
Access to home directory dotfiles
| 27 | [ -n "$_UPD" ] && echo "$_UPD" || true |
| 28 | mkdir -p ~/.gstack/sessions |
| 29 | touch ~/.gstack/sessions/"$PPID" |
| 30 | _SESSIONS=$(find ~/.gstack/sessions -mmin -120 -type f 2>/dev/null | wc -l | tr -d ' ') |
| 31 | find ~/.gstack/sessions -mmin +120 -type f -delete 2>/dev/null || true |
Access to home directory dotfiles
| 28 | mkdir -p ~/.gstack/sessions |
| 29 | touch ~/.gstack/sessions/"$PPID" |
| 30 | _SESSIONS=$(find ~/.gstack/sessions -mmin -120 -type f 2>/dev/null | wc -l | tr -d ' ') |
| 31 | find ~/.gstack/sessions -mmin +120 -type f -delete 2>/dev/null || true |
| 32 | _CONTRIB=$(~/.claude/skills/gstack/bin/gstack-config get gstack_contributor 2>/dev/null || true) |
Access to home directory dotfiles
| 29 | touch ~/.gstack/sessions/"$PPID" |
| 30 | _SESSIONS=$(find ~/.gstack/sessions -mmin -120 -type f 2>/dev/null | wc -l | tr -d ' ') |
| 31 | find ~/.gstack/sessions -mmin +120 -type f -delete 2>/dev/null || true |
| 32 | _CONTRIB=$(~/.claude/skills/gstack/bin/gstack-config get gstack_contributor 2>/dev/null || true) |
| 33 | ``` |
Access to home directory dotfiles
| 30 | _SESSIONS=$(find ~/.gstack/sessions -mmin -120 -type f 2>/dev/null | wc -l | tr -d ' ') |
| 31 | find ~/.gstack/sessions -mmin +120 -type f -delete 2>/dev/null || true |
| 32 | _CONTRIB=$(~/.claude/skills/gstack/bin/gstack-config get gstack_contributor 2>/dev/null || true) |
| 33 | ``` |
| 34 |
Access to home directory dotfiles
| 33 | ``` |
| 34 | |
| 35 | If output shows `UPGRADE_AVAILABLE <old> <new>`: read `~/.claude/skills/gstack/gstack-upgrade/SKILL.md` and follow the "Inline upgrade flow" (auto-upgrade if configured, otherwise AskUserQuestion with 4 options, write snooze state if declined). If `JUST_UPGRADED <from> <to>`: tell user "Running gstack v{to} (just updated!)" and continue. |
| 36 | |
| 37 | ## AskUserQuestion Format |
Access to home directory dotfiles
| 54 | **NOT gstack issues:** user's app bugs, network errors to user's URL, auth failures on user's site. |
| 55 | |
| 56 | **To file:** write `~/.gstack/contributor-logs/{slug}.md` with this structure: |
| 57 | |
| 58 | ``` |
Access to home directory dotfiles
| 74 | ``` |
| 75 | |
| 76 | Then run: `mkdir -p ~/.gstack/contributor-logs && open ~/.gstack/contributor-logs/{slug}.md` |
| 77 | |
| 78 | Slug: lowercase, hyphens, max 60 chars (e.g. `browse-snapshot-ref-gap`). Skip if file already exists. Max 3 reports per session. File inline and continue — don't stop the workflow. Tell user: "Filed gstack field report: {title}" |
Access to home directory dotfiles
| 118 | B="" |
| 119 | [ -n "$_ROOT" ] && [ -x "$_ROOT/.claude/skills/gstack/browse/dist/browse" ] && B="$_ROOT/.claude/skills/gstack/browse/dist/browse" |
| 120 | [ -z "$B" ] && B=~/.claude/skills/gstack/browse/dist/browse |
| 121 | if [ -x "$B" ]; then |
| 122 | echo "READY: $B" |
Access to home directory dotfiles
| 144 | Before falling back to git diff heuristics, check for richer test plan sources: |
| 145 | |
| 146 | 1. **Project-scoped test plans:** Check `~/.gstack/projects/` for recent `*-test-plan-*.md` files for this repo |
| 147 | ```bash |
| 148 | SLUG=$(git remote get-url origin 2>/dev/null | sed 's|.*[:/]\([^/]*/[^/]*\)\.git$|\1|;s|.*[:/]\([^/]*/[^/]*\)$|\1|' | tr '/' '-') |
Access to home directory dotfiles
| 147 | ```bash |
| 148 | SLUG=$(git remote get-url origin 2>/dev/null | sed 's|.*[:/]\([^/]*/[^/]*\)\.git$|\1|;s|.*[:/]\([^/]*/[^/]*\)$|\1|' | tr '/' '-') |
| 149 | ls -t ~/.gstack/projects/$SLUG/*-test-plan-*.md 2>/dev/null | head -1 |
| 150 | ``` |
| 151 | 2. **Conversation context:** Check if a prior `/plan-eng-review` or `/plan-ceo-review` produced test plan output in this conversation |
Access to home directory dotfiles
| 554 | ```bash |
| 555 | SLUG=$(git remote get-url origin 2>/dev/null | sed 's|.*[:/]\([^/]*/[^/]*\)\.git$|\1|;s|.*[:/]\([^/]*/[^/]*\)$|\1|' | tr '/' '-') |
| 556 | mkdir -p ~/.gstack/projects/$SLUG |
| 557 | ``` |
| 558 | Write to `~/.gstack/projects/{slug}/{user}-{branch}-test-outcome-{datetime}.md` |
Access to home directory dotfiles
| 556 | mkdir -p ~/.gstack/projects/$SLUG |
| 557 | ``` |
| 558 | Write to `~/.gstack/projects/{slug}/{user}-{branch}-test-outcome-{datetime}.md` |
| 559 | |
| 560 | **Per-issue additions** (beyond standard report template): |
Curl pipe to interpreter
| 129 | 1. Tell the user: "gstack browse needs a one-time build (~10 seconds). OK to proceed?" Then STOP and wait. |
| 130 | 2. Run: `cd <SKILL_DIR> && ./setup` |
| 131 | 3. If `bun` is not installed: `curl -fsSL https://bun.sh/install | bash` |
| 132 | |
| 133 | **Create output directories:** |