#!/usr/bin/env bash # StackPatch quickscan — anonymous CVE check for your Linux server. # Source: https://mindsparkstack.com/scan.sh — read it before piping to bash. # # What this does: # - Reads /etc/os-release, uname -r, and dpkg-query output # - POSTs to https://mindsparkstack.com/api/stackpatch/quickscan (anonymous, no signup) # - Pretty-prints findings + recommended actions inline # # What it does NOT do: # - Modify your system # - Send identifying info (no hostname, IP, public key, env vars) # - Persist anything server-side beyond a 5-min cache set -eu if ! command -v python3 >/dev/null 2>&1; then echo "stackpatch-scan: python3 required (used to format JSON)" >&2 exit 1 fi if ! command -v curl >/dev/null 2>&1; then echo "stackpatch-scan: curl required" >&2 exit 1 fi API_URL="https://mindsparkstack.com/api/stackpatch/quickscan" python3 - <<'PY' import json import os import subprocess import sys import urllib.error import urllib.request API_URL = "https://mindsparkstack.com/api/stackpatch/quickscan" def run(cmd): try: return subprocess.check_output(cmd, stderr=subprocess.DEVNULL, text=True).strip() except Exception: return "" # 1. Distro + codename distro = "" codename = "" if os.path.exists("/etc/os-release"): with open("/etc/os-release") as f: for line in f: line = line.strip() if line.startswith("ID="): distro = line[3:].strip().strip('"') elif line.startswith("VERSION_CODENAME="): codename = line[17:].strip().strip('"') kernel = run(["uname", "-r"]) # 2. Packages (top 200) packages = {} if any(os.access(os.path.join(p, "dpkg-query"), os.X_OK) for p in os.environ.get("PATH", "").split(":")): out = run(["dpkg-query", "-W", "-f=${Package}\t${Version}\n"]) for line in out.splitlines()[:200]: parts = line.split("\t") if len(parts) == 2 and parts[0]: packages[parts[0]] = parts[1] print() print("=== StackPatch quickscan ===") print(f" distro: {distro}") print(f" codename: {codename}") print(f" kernel: {kernel}") print(f" packages: {len(packages)}") print() payload = json.dumps({ "distro": distro, "codename": codename, "kernel": kernel, "packages": packages, }).encode("utf-8") req = urllib.request.Request( API_URL, data=payload, headers={"Content-Type": "application/json"}, method="POST", ) try: with urllib.request.urlopen(req, timeout=15) as resp: data = json.loads(resp.read().decode("utf-8")) except urllib.error.URLError as e: print(f"stackpatch-scan: API call failed: {e}", file=sys.stderr) sys.exit(2) except Exception as e: print(f"stackpatch-scan: unexpected error: {e}", file=sys.stderr) sys.exit(2) findings = data.get("findings", []) if not findings: print("\u2705 No quickscan matches.") print() print(data.get("next_step", "")) else: plural = "es" if len(findings) != 1 else "" print(f"\u26a0\ufe0f {len(findings)} match{plural} on your stack:") print() for f in findings: sev = f.get("severity", "?").upper() print(f" [{sev}] {f.get('id')} {f.get('title', '')}") print(f" why: {f.get('why', '')}") print(f" match: {f.get('affected_match', '')}") print(f" recommend: {f.get('recommended_action', '')}") cmd = f.get("command") if cmd: print(f" command:") for line in cmd.splitlines(): print(f" $ {line}") print() cta = data.get("cta", {}) outcome = data.get("outcome", "clean") headline = data.get("headline", "") next_step = data.get("next_step", "") print() print("--") if headline: if outcome == "vulnerable": print(f"\u26a0\ufe0f {headline}") elif outcome == "unsupported": print(f"\u2139\ufe0f {headline}") else: print(f"\u2705 {headline}") if next_step: print(f" {next_step}") print() cta_focus = data.get("cta_focus", "monitor") if cta_focus == "buy": print(f" Buy founder seat ($99 lifetime, 50 only): {cta.get('lifetime', '')}") print(f" Live audit URL of our own VPS: {cta.get('free_audit_demo', '')}") print(f" Honest comparison vs vuls.io: https://mindsparkstack.com{cta.get('vs_vuls', '/patch/vs-vuls')}") elif cta_focus == "waitlist": print(f" Join the waitlist (your distro): https://mindsparkstack.com{cta.get('waitlist', '/patch#waitlist')}") print(f" Roadmap / V2: {cta.get('see_full_product', '')}") else: print(f" Buy founder seat ($99 lifetime, 50 only): {cta.get('lifetime', '')}") print(f" Live audit URL of our own VPS: {cta.get('free_audit_demo', '')}") print(f" Full product page: {cta.get('see_full_product', '')}") PY