ios-qa
“Live-device iOS QA for SwiftUI apps. (gstack)”
daemon
src
test
docs
scripts
gen-accessors-tool
Sources
GenAccessors
templates
aipkg.jsondaemon/src/allowlist.tsdaemon/src/audit.tsdaemon/src/auth-mint.tsdaemon/src/cli-mint.tsdaemon/src/devicectl.tsdaemon/src/index.tsdaemon/src/proxy.tsdaemon/src/session-tokens.tsdaemon/src/single-instance.tsdaemon/src/tailscale-localapi.tsdaemon/src/tunnel-bootstrap.tsdaemon/src/types.tsdaemon/test/allowlist.test.tsdaemon/test/audit.test.tsdaemon/test/auth-mint.test.tsdaemon/test/cli-mint.test.tsdaemon/test/daemon-integration.test.tsdaemon/test/proxy-classify.test.tsdaemon/test/session-tokens.test.tsdaemon/test/single-instance.test.tsdaemon/test/tailscale-localapi.test.tsdaemon/test/tunnel-bootstrap.test.tsdocs/tailscale-acl-example.mdLICENSE.txtREADME.mdscripts/gen-accessors-tool/Package.swiftscripts/gen-accessors-tool/Sources/GenAccessors/main.swiftscripts/gen-accessors.test.tsscripts/gen-accessors.tsSKILL.mdSKILL.md.tmpltemplates/Bridges.swift.templatetemplates/DebugBridgeManager.swift.templatetemplates/DebugBridgeTouch.h.templatetemplates/DebugBridgeTouch.h.template is a binary file (1.3 kB). Install the package to read it locally.
templates/DebugBridgeTouch.m.templatetemplates/DebugBridgeTouch.m.template is a binary file (11 kB). Install the package to read it locally.
templates/DebugBridgeWiring.swift.templatetemplates/DebugOverlay.swift.templatetemplates/Package.swift.templatetemplates/StateAccessor.swift.templatetemplates/StateServer.swift.template- 01SDI-272%MEDIUM
SKILL.md:61
detailhide
Telemetry collection capability (skill-usage.jsonl, timeline-log, analytics writes) is embedded throughout the preamble without clear user consent or opt-in. The skill description says 'Live-device iOS QA' but collects telemetry including skill name, repo name, duration, and session IDs. Users may not expect this data collection from a QA tool.
59_LAKE_SEEN=$([ -f ~/.gstack/.completeness-intro-seen ] && echo "yes" || echo "no")60echo "LAKE_INTRO: $_LAKE_SEEN"61_TEL=$(~/.claude/skills/gstack/bin/gstack-config get telemetry 2>/dev/null || true)62_TEL_PROMPTED=$([ -f ~/.gstack/.telemetry-prompted ] && echo "yes" || echo "no")63_TEL_START=$(date +%s)fix 1. Move telemetry logic behind an explicit consent gate (AskUserQuestion on first run). 2. Document what data is collected (skill name, duration, repo basename, session ID) and where it's stored. 3. Default to 'off' rather than 'community'. 4. Add a clear banner in the skill description stating telemetry is collected.
- 02SDI-270%MEDIUM
SKILL.md:39
detailhide
The skill persists configuration, learnings, checkpoints, and question preferences to ~/.gstack/ across invocations. This scope expansion beyond iOS QA (config management, learning persistence, checkpoint auto-commit) creates hidden state that users may not expect from a QA tool. Persistence without explicit user control is a form of scope creep that can introduce bugs and security issues.
37Voice triggers (speech-to-text aliases): "iOS quality check", "test the iPhone app", "run iOS QA".3839## Preamble (run first)4041```bashfix 1. Scope the skill strictly to iOS QA; move config/learning/checkpoint logic to a separate '/gstack-init' or '/gstack-config' skill. 2. If persistence is kept, add a preamble warning and AskUserQuestion asking whether to enable it. 3. Document ~/.gstack/ directory contents and retention policies. 4. Provide a cleanup option (/ios-clean or similar) to remove all persistent state.
- 03SDI-365%LOW
SKILL.md:6
detailhide
The manifest lists only high-level tools (Bash, Read, Write, Edit, Grep, Glob, AskUserQuestion) but the preamble and Phase 2 sections extensively use shell constructs (find, wc, grep, sed, jq) and assume a POSIX environment. This creates a mismatch between declared capabilities and actual runtime requirements, making the skill difficult to audit and potentially fragile on non-Unix systems.
4version: 1.0.05description: Live-device iOS QA for SwiftUI apps. (gstack)6allowed-tools:7 - Bash8 - Readfix 1. Update allowed-tools to include explicit Bash permission or rename 'Bash' to 'Shell' if that's the intent. 2. Add platform requirements (macOS only, Xcode required, Tailscale optional) to the manifest or skill description. 3. Replace shell-heavy sections with explicit Bash tool invocations with clear parameter passing.
- 04SDI-175%LOW
SKILL.md:5
detailhide
The skill description ('Live-device iOS QA for SwiftUI apps') does not mention that it: (1) modifies the user's app source code (adds DebugBridge SPM dependency), (2) builds and deploys to a real device, (3) spawns a daemon process, (4) can expose the device over Tailscale, (5) collects telemetry. Users invoking 'ios qa' may be surprised by these infrastructure changes and network exposure.
3preamble-tier: 34version: 1.0.05description: Live-device iOS QA for SwiftUI apps. (gstack)6allowed-tools:7 - Bashfix 1. Expand skill description to include: 'Modifies Package.swift, builds and deploys to device, spawns a daemon, optionally exposes device over Tailscale.' 2. Add a Phase 0 preamble AskUserQuestion that warns the user about these actions before proceeding. 3. List all files that will be modified (Package.swift, app source, ~/.gstack/*, device state).
- 05SDI-370%LOW
daemon/src/index.ts:118
detailhide
The code reads several environment variables (GSTACK_IOS_DAEMON_PORT, GSTACK_IOS_TARGET_UDID, GSTACK_IOS_TARGET_BUNDLE_ID, GSTACK_IOS_TAILNET_BIND) without documented permission requirements. If this skill runs with elevated privileges or in shared environments, attackers could inject malicious values (e.g., GSTACK_IOS_TAILNET_BIND='0.0.0.0' to expose the daemon network-wide) to bypass intended access controls. Environment variable injection is a common attack vector.
116 });117 });118 const tailnetBindAddr = process.env.GSTACK_IOS_TAILNET_BIND ?? '127.0.0.1';119 // For tailnet port: actualPort + 1 if specified, else port 0 (OS-assigned).120 const requestedTailnetPort = requestedPort === 0 ? 0 : actualPort + 1;fix 1) Document all required environment variables and their security implications in the skill manifest. 2) Add explicit validation: reject GSTACK_IOS_TAILNET_BIND if it is not 127.0.0.1, ::1, or explicitly whitelisted. 3) Log all environment variable sources at startup for audit trails. 4) Consider moving sensitive config to a restricted config file instead of environment variables.
- 06SDI-185%MEDIUM
scripts/gen-accessors-tool/Sources/GenAccessors/main.swift:1
detailhide
This skill is advertised as 'Live-device iOS QA for SwiftUI apps' focused on testing, but contains a code generation tool that generates Swift source files and manages a persistent cache in ~/.gstack/cache/. This hidden code generation capability could inject malicious code into the app's build process if the cache is compromised or if the tool is invoked with untrusted input files. Users expecting a QA testing tool are unaware they're running a code generator.
1// gen-accessors entry point. Walks the input dir for *.swift files, parses2// each via SwiftParser, finds @Observable classes with @Snapshotable-marked3// properties, and emits StateAccessor.swift for each.fix Clearly document the code generation capability in the skill manifest and description. Separate the code generation tool into a distinct skill with explicit warnings. Implement validation of input files and cryptographic verification of cached outputs. Require explicit user consent before generating or caching code.
- 07SDI-380%LOW
scripts/gen-accessors-tool/Sources/GenAccessors/main.swift:64
detailhide
The tool reads environment variables like SWIFT_VERSION, GEN_ACCESSORS_REV, and APP_BUILD_ID without validation, and uses them directly in generated Swift code and cache keys. An attacker could set malicious environment variables to poison the build cache or inject code into generated state accessors. These operations are far beyond the scope of a QA testing tool and lack security controls.
6263 // Emit64 let output = render(specs: specs, buildId: getEnv("APP_BUILD_ID") ?? "unknown", accessorHash: cacheKey)65 try? FileManager.default.createDirectory(atPath: outputDir, withIntermediateDirectories: true)66 try? output.write(toFile: "\(outputDir)/StateAccessor.swift", atomically: true, encoding: .utf8)fix Validate all environment variables against a whitelist of acceptable values. Document which environment variables are used and why. Implement integrity checks on cached data using signatures. Consider running the code generation in an isolated environment with restricted environment variable access.
- 08SQP-278%HIGH
SKILL.md:844
detailhide
Phase 2 builds and deploys the app to a real device via xcodebuild and devicectl without any user confirmation or warning. The skill modifies the user's source code (adds DebugBridge dependency), rebuilds the app, and installs it on the device. If the device is a production iPhone or contains sensitive data, this is dangerous. No AskUserQuestion gate protects this action.
842 #endif843 ```8443. Build + deploy to the device with `xcodebuild -scheme <SchemeName>845 -destination 'platform=iOS,id=<UDID>' build install`.8464. Launch via `devicectl device process launch --device <UDID> --console <bundle-id>`.fix 1. Add an explicit AskUserQuestion before Phase 2 deployment, stating: 'This will add DebugBridge to Package.swift, rebuild your app, and install it on the device. Continue?' 2. Require user to confirm the device UDID matches their test device. 3. Provide a dry-run mode (--dry-run) that shows what will be modified without executing. 4. Add an /ios-clean command to remove DebugBridge and restore the original app.
- 09SQP-272%MEDIUM
SKILL.md:868
detailhide
The skill can expose the device over Tailscale (--tailnet flag) without a clear warning to the user. If enabled, the daemon binds the Tailscale interface and allows remote agents to control the device. While the skill includes ACL and capability tier logic, the initial decision to enable Tailnet mode is not protected by an AskUserQuestion, and the implications (remote access, audit logging) are not clearly stated.
8668. `POST /session/release` once the iteration is done.867868Each authenticated mutating request through the tailnet listener (if remote869mode is active) writes an audit row to870`~/.gstack/security/ios-qa-audit.jsonl`.fix 1. Add an AskUserQuestion before enabling --tailnet mode, explaining: 'This will expose your device over Tailscale. Remote agents can see screenshots and interact with the app. Continue?' 2. Show the user the identity of the remote agent (from WhoIs). 3. Default to local-USB mode only; require explicit --tailnet flag. 4. Log all remote interactions to ~/.gstack/security/ios-qa-audit.jsonl and offer to show the user the audit log.
- 10SQP-268%MEDIUM
SKILL.md:41
detailhide
The preamble executes many shell commands without user awareness or consent: config reads/writes, telemetry logs, timeline writes, session directory creation, binary execution (~/.claude/skills/gstack/bin/*), and git operations. This happens immediately on skill invocation, before any AskUserQuestion or user confirmation. A compromised gstack binary could steal credentials, modify the app, or exfiltrate data.
39## Preamble (run first)4041```bash42_UPD=$(~/.claude/skills/gstack/bin/gstack-update-check 2>/dev/null || .claude/skills/gstack/bin/gstack-update-check 2>/dev/null || true)43[ -n "$_UPD" ] && echo "$_UPD" || truefix 1. Separate the preamble into two phases: (a) minimal bootstrap (read config, check device), (b) full setup (only if user confirms via AskUserQuestion). 2. Add a '--skip-preamble' flag for debugging. 3. Log all shell commands executed and their exit codes; offer to show the log at skill end. 4. Pin gstack binary versions and verify checksums before execution.
- 11SQP-285%MEDIUM
SKILL.md.tmpl:5
detailhide
The skill enables remote device control via Tailscale without adequately warning users about the security implications. Remote agents can interact with a live iOS device (tap, swipe, type, modify app state) without explicit understanding that this grants full control over the device and any sensitive data within the app. Users may not realize they're exposing real device functionality to remote parties, potentially including financial apps, messaging apps, or apps with personal data.
3preamble-tier: 34version: 1.0.05description: |6 Live-device iOS QA for SwiftUI apps. Connects to a real iPhone via USB7 CoreDevice IPv6 tunnel, reads Swift source to understand every screen, thenfix Add a prominent security warning section early in the documentation that explicitly states: (1) Remote Tailscale mode grants full device control to remote agents; (2) Only enable Tailnet mode when you trust all users in the allowlist; (3) Audit logs should be monitored regularly; (4) Never run this against production builds with user credentials or live data; (5) Consider network isolation for devices running sensitive apps.
- 12SQP-290%MEDIUM
scripts/gen-accessors-tool/Sources/GenAccessors/main.swift:47
detailhide
The tool silently overwrites StateAccessor.swift files in the output directory without user confirmation or warnings. When combined with the caching mechanism, this can silently inject generated code into a project's source tree. Users running QA tests may have their codebase modified without awareness, creating supply chain risk.
45 if FileManager.default.fileExists(atPath: cachedOutput) {46 // Cache hit. Copy to output dir.47 try? FileManager.default.removeItem(atPath: "\(outputDir)/StateAccessor.swift")48 try? FileManager.default.copyItem(atPath: cachedOutput, toPath: "\(outputDir)/StateAccessor.swift")49 print("gen-accessors: cache hit (\(cacheKey))")fix Implement a confirmation prompt before overwriting any existing files. Log all file modifications with timestamps and previous content hashes. Provide a dry-run mode that shows what would be written without making changes. Document all output files in the skill manifest.
- 13SQP-285%HIGH
templates/Bridges.swift.template:200
detailhide
The code implements undisclosed UI automation capabilities (tap, type, swipe) that can programmatically interact with an iOS app without explicit user consent or warnings. While wrapped in #if DEBUG, this creates a significant attack surface if the debug bridge is inadvertently included in production builds or if an attacker gains access to the consuming app during development. An adversary could silently automate user interactions, exfiltrate data via text input, or manipulate app state without the user's knowledge or ability to audit what actions are being performed.
198// MARK: - MutationBridge implementation199200@MainActor201enum MutationBridgeImpl {202 /// Route a mutation op to the right handler. Returns true on success,fix 1) Ensure the #if DEBUG && canImport(UIKit) conditional is strictly enforced at compile-time and cannot be bypassed at runtime. 2) Add explicit user-facing warnings when the debug bridge is installed, such as a persistent on-screen indicator or launch-time dialog stating 'Debug UI Automation Enabled'. 3) Implement rate-limiting and logging of all automation operations to detect abuse. 4) Require explicit user gesture (e.g., shake to enable) before activating the debug bridge. 5) Add code review gates to prevent accidental inclusion of debug builds in release workflows.