sync: auto-sync from HOWARD-HOME at 2026-07-07 11:45:40

Author: Howard Enos
Machine: HOWARD-HOME
Timestamp: 2026-07-07 11:45:40
This commit is contained in:
2026-07-07 11:46:10 -07:00
parent 1e1bae772d
commit a507678254
6 changed files with 76 additions and 2 deletions

View File

@@ -11,6 +11,10 @@ Incident 2026-07-07: **vwp-qbs** (Valley Wide Plastering QuickBooks server) was
**This is SYSTEMIC, not a one-off.** The same rule fired + attempted auto-isolate on **tps-tina** (The Prairie Schooner) the same day — different GuruRMM script, different client. Per-command-line suppression is whack-a-mole. Note: the isolate-host response only actually cuts a host off where its endpoint policy has isolation enabled (vwp-qbs got isolated; tps-tina fired the same alert but `extensionSuccess=None`, stayed online).
**FLEET-WIDE FIX LIVE (2026-07-07):** Datto EDR suppression rule **`3365e79a`** "GuruRMM origin - Exfil-over-HTTP (fleet-wide FP)" — matches Rule Name = Exfiltration Over HTTP Protocol + Grand Parent = `gururmm-agent.exe`, org/loc empty = ALL clients. Suppresses this one rule for any GuruRMM-launched process fleet-wide (present + future scripts); every other rule still fires on RMM-origin. Created in the CONSOLE (by Howard) after the API create path proved unsafe. The two earlier narrow per-command-line rules (`e4dd55bf`, `7ea2a577`) are now redundant subsets — harmless, left in place.
**API FOOTGUN (do NOT create suppressions via `raw POST` on this tenant):** `POST /SuppressionRules` forces `active:true` and auto-creates an EMPTY match-everything version → a live "suppress all" window (I hit this with `7c36b89f`, deleted within ~2 min). `GET`/`PATCH /SuppressionRules/{id}` 400 ("undefined is not valid JSON"); `DELETE /{id}` works. Create suppressions in the CONSOLE until an atomic API create is verified. Details in `.claude/skills/datto-edr/references/api-reference.md`.
**What's deployed (done):**
- Narrow suppression rule (Datto EDR, id `e4dd55bf`) for VWP's exact script: matches Process Command Line + Grand Parent = `gururmm-agent.exe`. Does NOT blind other PowerShell. API schema for suppression is now in `.claude/skills/datto-edr/references/api-reference.md`.
- **EDR isolation watcher**: `.claude/scripts/edr-isolation-watch.sh` + `register-edr-watcher.ps1`, registered as Windows Scheduled Task **"ClaudeTools - EDR Isolation Watcher"** on Howard-Home (runs every 10 min, posts new auto-isolations to #dev-alerts — see [[feedback_fire_dev_alerts_for_client_work]]). Plain script, zero tokens. State file `.edr-watch-state.json` (gitignored) dedupes; seeded with the vwp-qbs + tps-tina event ids so it stays silent for the already-triaged ones. Retire when GuruRMM EDR webhook (Feature 6) lands.

View File

@@ -0,0 +1,5 @@
' gps-rmm-progress-hidden.vbs — launch the GPS->RMM progress check with no visible window.
' Run via the GPS-RMM-Progress scheduled task through wscript.exe (GUI host, no console),
' which starts bash with window style 0 (hidden) so the daily check no longer flashes a
' console window on the desktop. Runtime env is identical to a direct bash launch.
CreateObject("WScript.Shell").Run """C:\Program Files\Git\bin\bash.exe"" -lc ""cd /c/claudetools && bash .claude/scripts/gps-rmm-progress-check.sh""", 0, False

View File

@@ -138,6 +138,17 @@ rule = fleet-wide, gated by the metadata match). **Do NOT blanket-whitelist an R
grandparent by itself** — the RMM is a SYSTEM-level RCE channel and the top MSP attack path;
whitelisting all of it blinds EDR exactly where it matters.
**[DANGER] API create footgun (verified live 2026-07-07).** `POST /SuppressionRules` on this
tenant (a) **ignores `active:false` and forces the rule LIVE immediately**, and (b) auto-creates
an **EMPTY-metadata version that matches EVERYTHING**. So the two-step "create rule → then add
version" path leaves a live match-all suppression window (observed ~2 min → deleted). Also note
`GET`/`PATCH /SuppressionRules/{id}` (single-resource route) **HTTP 400** "undefined is not valid
JSON" on this tenant — read via `GET /SuppressionRules?filter={"where":{"id":"..."}}` instead;
**`DELETE /SuppressionRules/{id}` DOES work** (returns null, sets `deleted:true`). Until an
**atomic** create (metadata embedded in the POST body) is verified, **create suppressions in the
CONSOLE**, not via `raw POST`. If you must POST, verify the version's active fields IMMEDIATELY
and `DELETE` on any doubt.
**Create — CONSOLE-observed, API create RUN-unverified.** Console flow: open the alert →
**Create Suppression Rule** → check the desired Match fields → Save. This POSTs a
`SuppressionRule` (carrying `alertId`, `name`, `description`, `organizationId`, `locationId`,

View File

@@ -267,7 +267,7 @@ def build_parser() -> argparse.ArgumentParser:
sp.add_argument("method", help="GET/POST/PUT/DELETE")
sp.add_argument("path", help="e.g. Agents or Agents/scan")
sp.add_argument("--filter", help="LoopBack filter JSON (GET)")
sp.add_argument("--data", help="request body JSON")
sp.add_argument("--data", help="request body JSON, or @path to read JSON from a file")
sp.add_argument("--confirm", action="store_true",
help="required for non-GET methods")
return p
@@ -408,7 +408,13 @@ def main(argv=None) -> int:
print(f"[BLOCKED] {method} requires --confirm.", file=sys.stderr)
return 2
filt = json.loads(args.filter) if args.filter else None
body = json.loads(args.data) if args.data else None
if args.data and args.data.startswith("@"):
with open(args.data[1:], "r", encoding="utf-8") as _f:
body = json.load(_f)
elif args.data:
body = json.loads(args.data)
else:
body = None
# Same tenant-wide footgun guard the scan command has: a POST to any
# */scan endpoint with no non-empty `where` scans the ENTIRE tenant.
if method == "POST" and args.path.rstrip("/").lower().endswith("scan"):

View File

@@ -21,6 +21,10 @@ Categories (the `[type]` tag): _(none)_ = skill/command execution failure ·
2026-07-07 | GURU-BEAST-ROG | syncro | add_line_item and update_line_item both ignored user_id override - line item attributed to API key owner (1735) despite user_id 1750 in payload; needed GUI fix [ctx: ticket=32509 line=43169157]
2026-07-07 | Howard-Home | datto-edr | [friction] SuppressionRules POST forces active=true and auto-creates an EMPTY match-everything version; two-step create (rule then version) briefly went live matching all. Neutralized via DELETE. FIX: create atomically with metadata embedded, or use console. [ctx: tenant=azcomp4587 rule=7c36b89f impact=~2min-possible-oversuppression]
2026-07-07 | Howard-Home | datto-edr | Datto EDR HTTP 400: {"error":{"statusCode":400,"name":"SyntaxError","message":""undefined" is not valid JSON"}} [ctx: cmd=raw] (x2)
2026-07-07 | GURU-5070 | bash/env | [friction] appended a scratch write to /tmp/_vwpinv inside the syncro invoice block; PreToolUse block-tmp-path hook blocked the ENTIRE Bash call so no invoice ran - had to re-run. Never write scratch to /tmp on Windows; use a repo-relative path or skip it [ctx: ref=feedback_tmp_path_windows]
2026-07-07 | GURU-5070 | troubleshooting/assumption | [correction] repeatedly asserted Datto EDR was not cleanly uninstalled and pushed reinstall-to-uninstall; user had already removed it via its own uninstaller. A persistent WFP block filter can survive a clean uninstall (vendor bug) - frame it that way, don't blame the operator's removal

View File

@@ -0,0 +1,44 @@
# Session — GPS-RMM-Progress console popup made silent
## User
- **User:** Howard Enos (howard)
- **Machine:** Howard-Home
- **Role:** tech
## Summary
Howard reported a command window flashing on the desktop then disappearing. Traced it to
the `GPS-RMM-Progress` Windows scheduled task and made it run windowless.
## Diagnosis
- **Task:** `GPS-RMM-Progress` (root `\` folder, author `Howard`)
- **Old action:** `C:\Program Files\Git\bin\bash.exe -lc "cd /c/claudetools && bash .claude/scripts/gps-rmm-progress-check.sh"`
- **Trigger:** daily at 08:07 (single fire; no repetition interval)
- **Root cause of flash:** action launched `bash.exe` (console subsystem) with
`LogonType = Interactive` + `Hidden = False`, so a console window drew on the desktop each run.
- Script is our GPS->GuruRMM enrollment progress check: read-only against RMM `/api/agents`,
DMs Howard a daily summary via `discord-dm.sh`. No interactive desktop needed -> safe to hide.
## Fix
- Added `.claude/scripts/gps-rmm-progress-hidden.vbs` — a wscript wrapper that runs bash with
window style `0` (hidden), `False` (no wait). `wscript.exe` is a GUI-subsystem host, so no
console is ever allocated.
- Repointed the task action to:
- Execute: `C:\Windows\System32\wscript.exe`
- Arguments: `"C:\claudetools\.claude\scripts\gps-rmm-progress-hidden.vbs"`
- Runtime environment unchanged (same interactive session, vault/SSH/env intact); only the
window is suppressed.
## Verification
- `Start-ScheduledTask GPS-RMM-Progress` -> `LastResult 0x0`, no visible wscript/bash/conhost
windows. Flash eliminated.
- The verification run was a real (non-dry) execution, so it sent Howard the normal daily
Discord summary (expected).
## Files changed
- `.claude/scripts/gps-rmm-progress-hidden.vbs` (new)
## Notes / pending
- The scheduled task itself is per-machine (not stored in repo) — this fix applies to
Howard-Home only. Same change would be needed on any other machine running this task.
- Script self-reports `COMPLETE` once every tracked GPS client hits its RMM target; at that
point the task can be retired: `schtasks /Delete /TN GPS-RMM-Progress /F`.