ansible-automation-eng…
Ansible automation: playbooks, roles, collections, Molecule testing, Vault security.
Load when reviewing code that handles URL fetching, file paths, raw SQL, XML parsing, response serialization, debug modes, or error handling that may expose internal data.
$ npx -y skills add notque/vexjoy-agent --agent claude-codeHow it fires
How this agent gets triggered: by you, by Claude, or both.
Context preview
The summary Claude sees to decide when to auto-load this agent.
Load when reviewing code that handles URL fetching, file paths, raw SQL, XML parsing, response serialization, debug modes, or error handling that may expose internal data.
Load when reviewing code that handles URL fetching, file paths, raw SQL, XML parsing, response serialization, debug modes, or error handling that may expose internal data.
Data exfiltration: data crosses a trust boundary it should not. Validate inputs at the boundary, expose only fields the caller needs.
---
When fetching user-provided URLs (webhooks, image proxies, import-from-URL), validate the resolved IP against a blocklist of internal ranges. String-based URL checks fail because DNS rebinding, IP encoding, and redirects bypass hostname validation.
**Python:**
import ipaddress, socket
from urllib.parse import urlparse
BLOCKED_RANGES = [
ipaddress.ip_network('127.0.0.0/8'),
ipaddress.ip_network('10.0.0.0/8'),
ipaddress.ip_network('172.16.0.0/12'),
ipaddress.ip_network('192.168.0.0/16'),
ipaddress.ip_network('169.254.0.0/16'),
]
def safe_fetch(user_url: str) -> bytes:
parsed = urlparse(user_url)
if parsed.scheme not in ('http', 'https'):
raise ValueError('scheme not allowed')
addr = socket.getaddrinfo(parsed.hostname, parsed.port or 443)[0][4][0]
ip = ipaddress.ip_address(addr)
if any(ip in net for net in BLOCKED_RANGES):
raise ValueError('internal IP not allowed')
resp = requests.get(user_url, allow_redirects=False, timeout=10)
return resp.content**TypeScript:**
import { lookup } from 'dns/promises';
import ipaddr from 'ipaddr.js';
const BLOCKED_RANGES = ['private', 'linkLocal', 'loopback', 'uniqueLocal', 'unspecified'];
async function safeFetch(userUrl: string): Promise<Response> {
const parsed = new URL(userUrl);
if (!['http:', 'https:'].includes(parsed.protocol)) throw new Error('scheme not allowed');
const { address } = await lookup(parsed.hostname);
const ip = ipaddr.parse(address);
if (BLOCKED_RANGES.includes(ip.range())) throw new Error('internal IP not allowed');
return fetch(parsed.href, { redirect: 'manual' });
}SSRF reaches internal services, cloud metadata (169.254.169.254 returns IAM credentials).
**CVEs:** Capital One 2019, CVE-2021-26855 (Exchange ProxyLogon), CVE-2024-34351 (Next.js Server Actions SSRF), CVE-2020-28168 (axios redirect bypass), CVE-2024-21893 (Ivanti SAML SSRF).
rg -n 'requests\.(get|post|put)\(|urlopen\(|urllib\.request' --type py
rg -n 'fetch\(|axios\.(get|post)\(|got\(' --type ts --type js
rg -n 'callback_url|webhook_url|target_url|redirect_url' --type py --type ts
rg -n 'allow_redirects=True' --type py---
Resolve the full path and verify it stays within the intended base directory.
**Python:**
from pathlib import Path
from flask import abort, send_file
def serve_export(name: str):
base = Path("/var/app/exports").resolve()
target = (base / name).resolve()
if not target.is_relative_to(base):
abort(403)
return send_file(target)**TypeScript:**
import path from 'path';
function serveFile(name: string, res: Response) {
const base = path.resolve('/var/app/exports');
const target = path.resolve(base, name);
if (!target.startsWith(base + path.sep)) return res.sendStatus(403);
res.sendFile(target);
}**Go:**
func serveExport(w http.ResponseWriter, r *http.Request) {
base := "/var/app/exports"
name := filepath.Base(r.URL.Query().Get("name"))
target := filepath.Join(base, name)
clean, err := filepath.EvalSymlinks(target)
if err != nil || !strings.HasPrefix(clean, base) {
http.Error(w, "forbidden", http.StatusForbidden)
return
}
http.ServeFile(w, r, clean)
}**Archive extraction (Python):**
import tarfile
def safe_extract(archive_path: str, dest: str):
with tarfile.open(archive_path) as tar:
tar.extractall(path=dest, filter="data") # Python 3.12+Path traversal reads arbitrary files. Archive extraction compounds risk (zip-slip).
**CVEs:** CVE-2007-4559 (Python tarfile), CVE-2022-48285 (jszip), CVE-2023-26111 (node-static).
rg -n 'os\.path\.join\(|Path\(' --type py | rg -v 'resolve\(\)|realpath'
rg -n 'extractall\(' --type py | rg -v 'filter='
rg -n 'sendFile\(|readFile\(|readFileSync\(' --type ts
rg -n 'open\(.*request\.|open\(.*user_' --type py---
Pass user values as parameters, never interpolated strings.
**Python (Django):**
invoices = Invoice.objects.filter(customer_id=request.GET["cid"]) # When raw SQL unavoidable: Invoice.objects.extra(where=["customer_id = %s"], params=[request.GET["cid"]])
**TypeScript (Prisma):**
const users = await prisma.$queryRaw`SELECT * FROM users WHERE name = ${name}`;
// NEVER use $queryRawUnsafe with user input**Go:**
row := db.QueryRowContext(ctx,
"SELECT * FROM orders WHERE id = $1 AND user_id = $2",
orderID, userID,
)SQL injection via string interpolation remains one of the most exploited vulnerability classes. ORM escape hatches (`.raw()`, `.extra()`, `$queryRawUnsafe`) bypass parameterization.
**CVEs:** CVE-2023-25813 (Sequelize `literal()`), CVE-2025-23061 (Mongoose `populate({match: userObj})`).
rg -n '\.raw\(f"|\.extra\(where=\[f"|cursor\.execute\(f"|RawSQL\(f"' --type py
rg -n 'text\(f"|session\.execute\(f"' --type py
rg -n '\$queryRawUnsafe|\$executeRawUnsafe' --type ts
rg -n 'literal\(|sequelize\.query\(' --type ts --type js
rg -n 'fmt\.Sprintf.*SELECT|fmt\.Sprintf.*INSERT|fmt\.Sprintf.*UPDATE' --type go---
Configure XML parsers to reject DTDs and external entity references before parsing untrusted XML.
**Python:**
from defusedxml im
Essays and writing behind this toolkit live at vexjoy.com. VexJoy Agent connects plain-English requests to specialist agents, skills, and workflows. /do selects the knowledge and tools needed for your task.
Repo: notque/vexjoy-agent
Ansible automation: playbooks, roles, collections, Molecule testing, Vault security.
**Scope**: Module selection patterns, builtin vs command/shell decisions, collection modules, and version-specific module changes **Version range**:…
**Scope**: Molecule test scenarios, ansible-lint rules, idempotency validation, and check-mode patterns **Version range**: Molecule 6.0+ / ansible-lint 6.0+ /…
Universal rules injected by /do at dispatch. Each agent's .md file supplies domain rules.
**Scope**: Failure modes in agent output style — over-reporting, self-congratulation, verbose narration, and hedging. Covers what to detect and how to fix…
Zero-dependency combat visual upgrades: CSS particle replacement, Framer Motion combat juice, CSS 3D card transforms.