Session log: cPanel CVE-2026-41940 IOC scan + remediation on IX/WebSvr
Both servers were already patched (11.110.0.97 and 11.134.0.20) via daily auto-update. IOC scan found 16 flagged sessions across both plus 4 uncommented SSH keys on IX. Critical remediation: - Forensic evidence preserved before any deletion - 4 uncommented SSH keys removed from IX (server-side backup retained) - 16 flagged sessions purged across both servers - Root passwords rotated via chpasswd - New WHM API tokens created; 3 stale transfer-* tokens revoked - Vault entries + 1Password Infrastructure items updated Forensic deep-dive verdict: patch held. All 7 actual CVE exploit attempts (botnet IPs hitting /json-api/version) returned HTTP 403. The "multi-line pass" IOC hits on user sessions were false positives. Unidentified 76.18.103.222 root session traced to routine SSL maintenance (zero sensitive endpoints touched). Skill hardening: - Added MANDATORY service-token directive to .claude/commands/1password.md enforcing OP_SERVICE_ACCOUNT_TOKEN from SOPS for all op CLI calls - Per Mike: memory files alone don't reliably bind agent behavior; baking governance into skill content loaded at moment of use. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -34,16 +34,61 @@ Never ask users to paste API keys, passwords, or tokens into:
|
||||
|
||||
---
|
||||
|
||||
## Setup Check
|
||||
## ⚠️ MANDATORY: Use the SOPS-vaulted service account token, never the desktop session
|
||||
|
||||
Always verify the CLI is ready before any operation:
|
||||
**Every `op` invocation in agent flows must run with `OP_SERVICE_ACCOUNT_TOKEN` set.** The desktop-app integration prompts to unlock the app, which interrupts the agent flow and is unacceptable. The service token is in the SOPS vault at `infrastructure/1password-service-account.sops.yaml` (vault entry kind=`api-key`, name=`1Password Service Account (Agentic-RW)`).
|
||||
|
||||
### Load the token at the start of any 1Password work
|
||||
|
||||
```bash
|
||||
# Decrypt the service token from SOPS (uses the machine's age key)
|
||||
export OP_SERVICE_ACCOUNT_TOKEN=$(sops -d /c/Users/guru/vault/infrastructure/1password-service-account.sops.yaml 2>/dev/null \
|
||||
| grep -E '^\s*credential:' | sed -E 's/^\s*credential:\s*//' | head -1)
|
||||
|
||||
# Verify
|
||||
op whoami # expect "User Type: SERVICE_ACCOUNT"
|
||||
```
|
||||
|
||||
After `export`, every subsequent `op` call in the same bash invocation inherits the token. For one-off calls without exporting:
|
||||
|
||||
```bash
|
||||
SVC=$(sops -d /c/Users/guru/vault/infrastructure/1password-service-account.sops.yaml 2>/dev/null | grep -E '^\s*credential:' | sed -E 's/^\s*credential:\s*//' | head -1)
|
||||
OP_SERVICE_ACCOUNT_TOKEN="$SVC" op item get "Item Name" --vault Infrastructure
|
||||
```
|
||||
|
||||
### Vault path resolution
|
||||
|
||||
The vault lives wherever `.claude/identity.json` says (`vault_path`). On the current Windows workstation it's `C:/Users/guru/vault`, but other machines (Howard's, future workstations) may differ. Resolve dynamically when needed:
|
||||
|
||||
```bash
|
||||
VAULT_DIR=$(python -c "import json; print(json.load(open('/c/Users/guru/ClaudeTools/.claude/identity.json'))['vault_path'])")
|
||||
SVC=$(sops -d "$VAULT_DIR/infrastructure/1password-service-account.sops.yaml" 2>/dev/null | grep -E '^\s*credential:' | sed -E 's/^\s*credential:\s*//' | head -1)
|
||||
export OP_SERVICE_ACCOUNT_TOKEN="$SVC"
|
||||
```
|
||||
|
||||
### Service account scope (verified 2026-04-30)
|
||||
|
||||
The Agentic-RW service account has access to: **Clients, Infrastructure, Internal Sites, Managed Websites, MSP Tools, Projects, Sorting**. The Private vault is intentionally NOT shared with the service account — if you need to read from Private, that's a different conversation, not a fallback to desktop session.
|
||||
|
||||
### When the token fails
|
||||
|
||||
- `op vault list` returns "account is not signed in" with the token set → token is malformed or revoked. Decrypt directly via `sops -d` and inspect.
|
||||
- `vault.sh get-field` may fail with "PyYAML not installed" — use direct `sops -d` + grep instead until that wrapper bug is fixed.
|
||||
- Never fall back to the desktop-app session in agent flows. If the service token is unrecoverable, stop and tell Mike.
|
||||
|
||||
---
|
||||
|
||||
## Setup Check (only for net-new machine onboarding)
|
||||
|
||||
For a fresh workstation that doesn't have the service token wired up yet:
|
||||
|
||||
```bash
|
||||
bash scripts/check_setup.sh
|
||||
```
|
||||
|
||||
If not installed: https://developer.1password.com/docs/cli/get-started/
|
||||
If not signed in: unlock the **1Password desktop app** (after Mac restart, the app must be unlocked before the CLI works)
|
||||
|
||||
The desktop-app sign-in flow is for **interactive human use**, not agent flows — those go through the service account above.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
- [Ollama Tier-0 Routing](feedback_ollama_tier0_routing.md) - Route drafts/summaries/classifications through Ollama (qwen3:14b). Mike designed ClaudeTools this way — not optional.
|
||||
- [Syncro Emergency Billing](feedback_syncro_emergency_billing.md) — Emergency = 1.5× multiplier, not additive. Branch by `customer.prepay_hours`: no-prepaid → `26184` at actual hrs; prepaid → `26118` at hrs×1.5. Never stack. Always set `price_retail`.
|
||||
- [Identity precedence](feedback_identity_precedence.md) — Trust `.claude/identity.json` over the system-reminder `userEmail` hint when they disagree (shared-login machines).
|
||||
- [1Password — always use service token](feedback_1password_service_token.md) — Source OP_SERVICE_ACCOUNT_TOKEN from SOPS for every `op` call. Desktop-app integration prompts are unacceptable in agent flows.
|
||||
|
||||
## Machine
|
||||
- [ACG-5070 Workstation Setup](reference_workstation_setup.md) - Windows 11 Pro clean install 2026-03-30, replaced CachyOS. All tools installed.
|
||||
|
||||
26
.claude/memory/feedback_1password_service_token.md
Normal file
26
.claude/memory/feedback_1password_service_token.md
Normal file
@@ -0,0 +1,26 @@
|
||||
---
|
||||
name: 1Password — always use service account token
|
||||
description: Use the SOPS-vaulted OP_SERVICE_ACCOUNT_TOKEN for all op CLI calls; the desktop-app integration prompts are unacceptable in agent flows
|
||||
type: feedback
|
||||
---
|
||||
|
||||
For every `op` CLI invocation, source `OP_SERVICE_ACCOUNT_TOKEN` from `infrastructure/1password-service-account.sops.yaml` first. Without it, `op` falls back to the desktop-app integration which interrupts the workflow with "unlock the app" prompts.
|
||||
|
||||
**Why:** Mike confirmed 2026-04-30 — "the prompts are infuriating." Service account auth is the standard CI/agent pattern documented in the 1password skill but I had been defaulting to the desktop session.
|
||||
|
||||
**How to apply:**
|
||||
```bash
|
||||
SVC_TOKEN=$(sops -d /c/Users/guru/vault/infrastructure/1password-service-account.sops.yaml 2>/dev/null \
|
||||
| grep -E '^\s*credential:' | sed -E 's/^\s*credential:\s*//' | head -1)
|
||||
|
||||
# Pass through env var to every op call
|
||||
OP_SERVICE_ACCOUNT_TOKEN="$SVC_TOKEN" op item get ...
|
||||
# Or export once at the top of a script
|
||||
export OP_SERVICE_ACCOUNT_TOKEN="$SVC_TOKEN"
|
||||
```
|
||||
|
||||
The `vault.sh get-field` wrapper currently fails on this entry due to a missing PyYAML dependency in the wrapper's fallback parser — use direct `sops -d` + grep until that's fixed.
|
||||
|
||||
**Vaults the service account can see** (per 2026-04-30 test): Clients, Infrastructure, Internal Sites, Managed Websites, MSP Tools, Projects, Sorting. (The Private vault is intentionally not shared with the service account.)
|
||||
|
||||
**When to skip:** Never. If the desktop session also happens to be authed, that's fine, but the service token path must be the one the agent reaches for.
|
||||
Reference in New Issue
Block a user