qa-only
Report-only QA testing. Systematically tests a web application and produces a structured report with health score, screenshots, and repro steps — but never fixe
Security score
The qa-only skill was audited on Mar 16, 2026 and we found 23 security issues across 4 threat categories, including 2 critical. Review the findings below before installing.
Categories Tested
Security Issues
Piping content to bash shell
| 110 | 1. Tell the user: "gstack browse needs a one-time build (~10 seconds). OK to proceed?" Then STOP and wait. |
| 111 | 2. Run: `cd <SKILL_DIR> && ./setup` |
| 112 | 3. If `bun` is not installed: `curl -fsSL https://bun.sh/install | bash` |
| 113 | |
| 114 | **Create output directories:** |
Command substitution pattern
| 19 | |
| 20 | ```bash |
| 21 | _UPD=$(~/.claude/skills/gstack/bin/gstack-update-check 2>/dev/null || .claude/skills/gstack/bin/gstack-update-check 2>/dev/null || true) |
| 22 | [ -n "$_UPD" ] && echo "$_UPD" || true |
| 23 | mkdir -p ~/.gstack/sessions |
Command substitution pattern
| 23 | mkdir -p ~/.gstack/sessions |
| 24 | touch ~/.gstack/sessions/"$PPID" |
| 25 | _SESSIONS=$(find ~/.gstack/sessions -mmin -120 -type f 2>/dev/null | wc -l | tr -d ' ') |
| 26 | find ~/.gstack/sessions -mmin +120 -type f -delete 2>/dev/null || true |
| 27 | _CONTRIB=$(~/.claude/skills/gstack/bin/gstack-config get gstack_contributor 2>/dev/null || true) |
Command substitution pattern
| 25 | _SESSIONS=$(find ~/.gstack/sessions -mmin -120 -type f 2>/dev/null | wc -l | tr -d ' ') |
| 26 | find ~/.gstack/sessions -mmin +120 -type f -delete 2>/dev/null || true |
| 27 | _CONTRIB=$(~/.claude/skills/gstack/bin/gstack-config get gstack_contributor 2>/dev/null || true) |
| 28 | ``` |
| 29 |
Command substitution pattern
| 96 | |
| 97 | ```bash |
| 98 | _ROOT=$(git rev-parse --show-toplevel 2>/dev/null) |
| 99 | B="" |
| 100 | [ -n "$_ROOT" ] && [ -x "$_ROOT/.claude/skills/gstack/browse/dist/browse" ] && B="$_ROOT/.claude/skills/gstack/browse/dist/browse" |
Command substitution pattern
| 127 | 1. **Project-scoped test plans:** Check `~/.gstack/projects/` for recent `*-test-plan-*.md` files for this repo |
| 128 | ```bash |
| 129 | SLUG=$(git remote get-url origin 2>/dev/null | sed 's|.*[:/]\([^/]*/[^/]*\)\.git$|\1|;s|.*[:/]\([^/]*/[^/]*\)$|\1|' | tr '/' '-') |
| 130 | ls -t ~/.gstack/projects/$SLUG/*-test-plan-*.md 2>/dev/null | head -1 |
| 131 | ``` |
Command substitution pattern
| 419 | **Project-scoped:** Write test outcome artifact for cross-session context: |
| 420 | ```bash |
| 421 | SLUG=$(git remote get-url origin 2>/dev/null | sed 's|.*[:/]\([^/]*/[^/]*\)\.git$|\1|;s|.*[:/]\([^/]*/[^/]*\)$|\1|' | tr '/' '-') |
| 422 | mkdir -p ~/.gstack/projects/$SLUG |
| 423 | ``` |
Curl to non-GitHub URL
| 110 | 1. Tell the user: "gstack browse needs a one-time build (~10 seconds). OK to proceed?" Then STOP and wait. |
| 111 | 2. Run: `cd <SKILL_DIR> && ./setup` |
| 112 | 3. If `bun` is not installed: `curl -fsSL https://bun.sh/install | bash` |
| 113 | |
| 114 | **Create output directories:** |
Access to home directory dotfiles
| 19 | |
| 20 | ```bash |
| 21 | _UPD=$(~/.claude/skills/gstack/bin/gstack-update-check 2>/dev/null || .claude/skills/gstack/bin/gstack-update-check 2>/dev/null || true) |
| 22 | [ -n "$_UPD" ] && echo "$_UPD" || true |
| 23 | mkdir -p ~/.gstack/sessions |
Access to home directory dotfiles
| 21 | _UPD=$(~/.claude/skills/gstack/bin/gstack-update-check 2>/dev/null || .claude/skills/gstack/bin/gstack-update-check 2>/dev/null || true) |
| 22 | [ -n "$_UPD" ] && echo "$_UPD" || true |
| 23 | mkdir -p ~/.gstack/sessions |
| 24 | touch ~/.gstack/sessions/"$PPID" |
| 25 | _SESSIONS=$(find ~/.gstack/sessions -mmin -120 -type f 2>/dev/null | wc -l | tr -d ' ') |
Access to home directory dotfiles
| 22 | [ -n "$_UPD" ] && echo "$_UPD" || true |
| 23 | mkdir -p ~/.gstack/sessions |
| 24 | touch ~/.gstack/sessions/"$PPID" |
| 25 | _SESSIONS=$(find ~/.gstack/sessions -mmin -120 -type f 2>/dev/null | wc -l | tr -d ' ') |
| 26 | find ~/.gstack/sessions -mmin +120 -type f -delete 2>/dev/null || true |
Access to home directory dotfiles
| 23 | mkdir -p ~/.gstack/sessions |
| 24 | touch ~/.gstack/sessions/"$PPID" |
| 25 | _SESSIONS=$(find ~/.gstack/sessions -mmin -120 -type f 2>/dev/null | wc -l | tr -d ' ') |
| 26 | find ~/.gstack/sessions -mmin +120 -type f -delete 2>/dev/null || true |
| 27 | _CONTRIB=$(~/.claude/skills/gstack/bin/gstack-config get gstack_contributor 2>/dev/null || true) |
Access to home directory dotfiles
| 24 | touch ~/.gstack/sessions/"$PPID" |
| 25 | _SESSIONS=$(find ~/.gstack/sessions -mmin -120 -type f 2>/dev/null | wc -l | tr -d ' ') |
| 26 | find ~/.gstack/sessions -mmin +120 -type f -delete 2>/dev/null || true |
| 27 | _CONTRIB=$(~/.claude/skills/gstack/bin/gstack-config get gstack_contributor 2>/dev/null || true) |
| 28 | ``` |
Access to home directory dotfiles
| 25 | _SESSIONS=$(find ~/.gstack/sessions -mmin -120 -type f 2>/dev/null | wc -l | tr -d ' ') |
| 26 | find ~/.gstack/sessions -mmin +120 -type f -delete 2>/dev/null || true |
| 27 | _CONTRIB=$(~/.claude/skills/gstack/bin/gstack-config get gstack_contributor 2>/dev/null || true) |
| 28 | ``` |
| 29 |
Access to home directory dotfiles
| 28 | ``` |
| 29 | |
| 30 | 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. |
| 31 | |
| 32 | ## AskUserQuestion Format |
Access to home directory dotfiles
| 49 | **NOT gstack issues:** user's app bugs, network errors to user's URL, auth failures on user's site. |
| 50 | |
| 51 | **To file:** write `~/.gstack/contributor-logs/{slug}.md` with this structure: |
| 52 | |
| 53 | ``` |
Access to home directory dotfiles
| 69 | ``` |
| 70 | |
| 71 | Then run: `mkdir -p ~/.gstack/contributor-logs && open ~/.gstack/contributor-logs/{slug}.md` |
| 72 | |
| 73 | 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
| 99 | B="" |
| 100 | [ -n "$_ROOT" ] && [ -x "$_ROOT/.claude/skills/gstack/browse/dist/browse" ] && B="$_ROOT/.claude/skills/gstack/browse/dist/browse" |
| 101 | [ -z "$B" ] && B=~/.claude/skills/gstack/browse/dist/browse |
| 102 | if [ -x "$B" ]; then |
| 103 | echo "READY: $B" |
Access to home directory dotfiles
| 125 | Before falling back to git diff heuristics, check for richer test plan sources: |
| 126 | |
| 127 | 1. **Project-scoped test plans:** Check `~/.gstack/projects/` for recent `*-test-plan-*.md` files for this repo |
| 128 | ```bash |
| 129 | SLUG=$(git remote get-url origin 2>/dev/null | sed 's|.*[:/]\([^/]*/[^/]*\)\.git$|\1|;s|.*[:/]\([^/]*/[^/]*\)$|\1|' | tr '/' '-') |
Access to home directory dotfiles
| 128 | ```bash |
| 129 | SLUG=$(git remote get-url origin 2>/dev/null | sed 's|.*[:/]\([^/]*/[^/]*\)\.git$|\1|;s|.*[:/]\([^/]*/[^/]*\)$|\1|' | tr '/' '-') |
| 130 | ls -t ~/.gstack/projects/$SLUG/*-test-plan-*.md 2>/dev/null | head -1 |
| 131 | ``` |
| 132 | 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
| 420 | ```bash |
| 421 | SLUG=$(git remote get-url origin 2>/dev/null | sed 's|.*[:/]\([^/]*/[^/]*\)\.git$|\1|;s|.*[:/]\([^/]*/[^/]*\)$|\1|' | tr '/' '-') |
| 422 | mkdir -p ~/.gstack/projects/$SLUG |
| 423 | ``` |
| 424 | Write to `~/.gstack/projects/{slug}/{user}-{branch}-test-outcome-{datetime}.md` |
Access to home directory dotfiles
| 422 | mkdir -p ~/.gstack/projects/$SLUG |
| 423 | ``` |
| 424 | Write to `~/.gstack/projects/{slug}/{user}-{branch}-test-outcome-{datetime}.md` |
| 425 | |
| 426 | ### Output Structure |
Curl pipe to interpreter
| 110 | 1. Tell the user: "gstack browse needs a one-time build (~10 seconds). OK to proceed?" Then STOP and wait. |
| 111 | 2. Run: `cd <SKILL_DIR> && ./setup` |
| 112 | 3. If `bun` is not installed: `curl -fsSL https://bun.sh/install | bash` |
| 113 | |
| 114 | **Create output directories:** |