Back to skill

Security audit

Renatus Icm

Security checks for vulnerabilities and agentic risk

Overview

This skill is mostly an event-marketing toolkit, but it handles browser session tokens, lead deletion, mass email, admin exports, and scheduled unsubscribe automation with several unsafe or incomplete controls.

Install only if you are prepared to treat this as a privileged campaign-admin tool. Use a dedicated browser profile for CDP, avoid production service-role keys, review or replace the unsubscribe workflow before sending email, verify consent handling before registration, and do not deploy missing or unaudited Supabase functions.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
Findings (5)

T09 · Insecure Skill Coding Practices

Error
Location
assets/site/unsubscribe.html:102
Finding

Unsubscribe requests are not durably recorded or enforced

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/renatus_register_guest.py:253
Finding

Guest registration grants email and SMS consent without explicit authorization

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/generate_email_template.py:366
Finding

Generated email and calendar HTML permits markup and dangerous-link injection

Content
View full analysis
str: defaults = make_defaults(event_name, event_date, instructors) bullets = [] desc = args.event_description or defaults.get("intro_paragraph1", "") if desc: sentences = [s.strip() for s in desc.replace("\n", ". ").split(".") if len(s.strip()) > 20] for s in sentences[:4]: bullets.append(f"✔ {s.strip()}.") bullet_text = "
".join(bullets) if bullets else defaults.get("bullet_1", "") header_title = args.header_title or event_name or "Renatus Event" subject_lines = args.subject_lines or generate_subject_lines(header_title, event_date) subs = { "event_name": event_name or "Renatus Event", "event_date": event_date, "email_title": f"Free Real Estate Training — {header_title}", "header_title": header_title, "header_subtitle": args.header_subtitle or defaults.get("header_subtitle", ""), "urgency_date": f"📅 {event_date}" if event_date else "📅 Upcoming event", "urgency_location": args.urgency_location if hasattr(args, 'urgency_location') else defaults.get("urgency_location", ""), "intro_paragraph1": args.event_description or defaults.get("intro_paragraph1", ""), "intro_paragraph2": args.intro_paragraph2 if hasattr(args, 'intro_paragraph2') and args.intro_paragraph2 else defaults.get("intro_paragraph2", ""), "instructors": instructors or args.instructors or defaults.get("instructors", ""), "instructor_bio": args.instruc ...[truncated 3098 chars]
Remediation
View remediation
`. 4. Parse all URLs and permit only an explicit scheme and host policy, normally `https`. 5. Reject `javascript:`, `data:`, `file:`, protocol-relative URLs, embedded credentials, and malformed hosts. 6. Keep raw event descriptions out of HTML comments because comment termination can also enable injection. 7. Add Content Security Policy headers to deployed pages as defense in depth. 8. Add tests containing quotes, angle brackets, ``, `javascript:`, and event-handler attributes. 9. Require an operator preview and destination-host confirmation before bulk sending or deployment. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/renatus_leads.py:96
Finding

Lead exports, unsubscribe files, and recipient logs persist sensitive data with default permissions

Content
View full analysis
None: if not rows: print("No rows to write") return fieldnames = ["name", "email", "phone", "company", "notes", "cta_type", "source_page", "created_at"] meta_fields = set() for row in rows: meta = row.get("metadata") or {} meta_fields.update(meta.keys()) all_fields = fieldnames + sorted(meta_fields) with open(path, "w", newline="", encoding="utf-8") as f: writer = csv.DictWriter(f, fieldnames=all_fields, extrasaction="ignore") writer.writeheader() for row in rows: meta = row.get("metadata") or {} flat = {k: v for k, v in row.items() if k != "metadata"} flat["phone"] = meta.get("phone", "") flat["event_id"] = meta.get("event_id", "") flat["registration_id"] = meta.get("registration_id", "") flat["lead_id"] = meta.get("lead_id", "") flat["guest_user_id"] = meta.get("guest_user_id", "") flat["registered_sessions"] = "; ".join(meta.get("registered_sessions", [])) if meta.get("registered_sessions") else "" for k, v in meta.items(): if k not in flat: flat[k] = v writer.writerow(flat) ``` ```python def rows_to_json(rows: list[dict], path: Path) -> None: with open(path, "w", encoding="utf-8") as f: json.dump({ "exported_at": datetime.utcnow().isoformat() + "Z", "total": len ...[truncated 2696 chars]
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
references/supabase-setup.md:19
Finding

Setup instructions provision broad Supabase access and unrelated unauditable components

Content
View full analysis
supabase functions deploy lead-admin-export --project-ref supabase functions deploy capture-lead --project-ref supabase functions deploy stripe-webhook --project-ref ``` ```bash supabase secrets set \ RENATUS_USERNAME="" \ RENATUS_PASSWORD="" \ RENATUS_EVENT_ID="" \ SUPABASE_URL="https://.supabase.co" \ SUPABASE_SERVICE_ROLE_KEY="" \ LEAD_ADMIN_TOKEN="" \ --project-ref ``` The same guide lists additional payment secrets: ```markdown | `SUPABASE_SERVICE_ROLE_KEY` | Yes | Service role key | | `LEAD_ADMIN_TOKEN` | Yes (export) | Admin export bearer token | | `STRIPE_SECRET_KEY` | Payments | Stripe secret key | | `STRIPE_WEBHOOK_SECRET` | Payments | Stripe webhook secret | | `TURNSTILE_SECRET_KEY` | No | Cloudflare Turnstile | ``` ### Technical Analysis A Supabase service-role key generally bypasses row-level security and grants broad project-level data access. The guide provisions it as a general required secret rather than assigning narrowly scoped credentials to individual functions. The instructions also deploy `capture-lead` and `stripe-webhook`, but their source code is not included in the audited project. Stripe payment processing is not necessary for the core workflow of generating event pages, registering attendees, exporting leads, or sending campaigns. Users therefore cannot review the components before following the deployment instructions. This conflicts with the Skill's own recommendation to use limited credentials for read-only oper ...[truncated 1289 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • YARA SignaturesMalware Match, Webshell Match, Cryptominer Match
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (48)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 24)May include surrounding context.

md
- `renatus_delete_lead.py` performs deletions — always run with `--dry-run` first

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 43)May include surrounding context.

md
- `renatus_delete_lead.py` performs deletions — always run with `--dry-run` first

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 107)May include surrounding context.

md
- `renatus_delete_lead.py` performs deletions — always run with `--dry-run` first

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 235)May include surrounding context.

md
- `renatus_delete_lead.py` performs deletions — always run with `--dry-run` first

YARA rule 'info_stealer': Information stealer patterns (credential harvesting, browser data theft) [malware]

High
Category
YARA Match
Confidence
98% confidence
Finding

The skill explicitly directs scripts to connect to a local Chrome DevTools endpoint and inspect browser localStorage/cookies to obtain Renatus session tokens. Accessing live browser session material is highly sensitive because any script with CDP access can impersonate the user, extract additional authenticated data, and potentially access unrelated tabs or accounts if browser isolation is weak.

Content

Scanner excerpt · SKILL.md (reported line 28)May include surrounding context.

md
access (not your main browser session)
- `renatus_delete_lead.py` performs deletions — always run with `--dry-run` first
- Rotate credentials after use; revoke tokens that were shared or exposed
- Do not commit real credentials to `config.json` — use the `.example` file and environment variables

**CDP access:** Scripts connect to `http://127.0.0.1:9222` to inspect your browser's localStorage/cookies for Renatus auth tokens. This requires Chrome/Brave launched with `--remote-debugging-port=9222`. The skill does not extract your master Renatus password from CDP — it reads existing session tokens only.

---
name: renatus-icm
description: Run a Renatus event marketing campaign as an ICM (Independent Campaign Manager). Use when managing Renatus event registrations, sending commercial email campaigns, setting up event landing pages, downloading/exporting leads, syncing unsubscribes to Renatus, or performing browser-based guest registration via CDP. Handles: Supabase Edge Function regi

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 43)May include surrounding context.

md
- **CDP Registration** → scripts `renatus_register_guest.py`, `renatus_delete_lead.py`

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 96)May include surrounding context.

md
- **CDP Registration** → scripts `renatus_register_guest.py`, `renatus_delete_lead.py`

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 235)May include surrounding context.

md
- **CDP Registration** → scripts `renatus_register_guest.py`, `renatus_delete_lead.py`

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 52)May include surrounding context.

md
python3 scripts/generate_event_page.py --event-url "https://backoffice.myrenatus.com/Events/EventDetails?eventId=..." --output site/my-event/index.html

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 235)May include surrounding context.

md
python3 scripts/generate_event_page.py --event-url "https://backoffice.myrenatus.com/Events/EventDetails?eventId=..." --output site/my-event/index.html

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 120)May include surrounding context.

md
python3 scripts/add_event.py --event-url "https://backoffice.myrenatus.com/Events/EventDetails?eventId=..." --output site/my-event/index.html

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 235)May include surrounding context.

md
python3 scripts/add_event.py --event-url "https://backoffice.myrenatus.com/Events/EventDetails?eventId=..." --output site/my-event/index.html

YARA rule 'backdoor_persistence': Backdoor persistence with malicious payloads (shell commands, SSH key injection, hidden root users) [malware]

High
Category
YARA Match
Confidence
75% confidence
Finding

YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Content

Scanner excerpt · SKILL.md (reported line 204)May include surrounding context.

rpose | |---|---|---| | RENATUS_USERNAME | Registration | Back office login | | RENATUS_PASSWORD | Registration | Back office password | | RENATUS_EVENT_ID | Registration | Default event GUID | | LEAD_ADMIN_TOKEN | Export | Admin export auth | | SUPABASE_URL | Always | Project URL | | SUPABASE_SERVICE_ROLE_KEY | Always | DB access |

Unsubscribe Sync (Weekly Cron)

bash
# Add to crontab
0 2 * * 0 /home/umbrel/.openclaw/workspace/scripts/weekly_unsubscribe_sync.sh

# Manual run
CDP_URL=http://127.0.0.1:9222 bash scripts/weekly_unsubscribe_sync.sh

Requirements: Chrome CDP at 9222 + active Renatus session. See email-campaign.md.

Bounce Recovery

bash
# Detect bounces
python3 scripts/handle_bounced_emails.py --check

# Export SMS-ready contacts
python3 scripts/handle_bounced_emails.py --export-sms

# Manually mark bounce
python3 scripts/handle_bounced_emails.py --mark-bounced user@example.com

Authentication: Two Options

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 249)May include surrounding context.

md
**Non-CDP scripts:** `renatus_leads.py`, `send_commercial_email_batches.py`, `generate_calendar.py`, `generate_email_template.py`

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
93% confidence
Finding

Documenting lead deletion operations in an email campaign guide introduces destructive administrative capability far beyond simple campaign sending. In the wrong hands or by operator mistake, these commands can permanently remove lead records or process unsubscribe files incorrectly, causing data loss and business impact.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
95% confidence
Finding

The guide includes a Supabase admin export using an admin token, which is a privileged data extraction mechanism unrelated to basic email sending. Embedding this workflow in the skill normalizes broad access to lead data and increases the chance of credential misuse, unauthorized export, or over-collection of personal information.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The page tells users they have been unsubscribed and that their email will be queued for deletion within 24 hours, but the implemented logic only stores the address in browser localStorage and makes an optional best-effort backend call if a config value exists. This is a deceptive privacy/compliance behavior that can cause users to believe a deletion request was completed when it may never have been sent or processed.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The script logs the user's email address to the browser console, exposing personally identifiable information in a location visible to anyone with browser access, support tooling, shared-device users, or captured debug logs. While limited in scope, unnecessary client-side logging of PII increases privacy risk and can violate data-minimization expectations.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
85% confidence
Finding

The guide explicitly supports exporting bounced contacts' phone numbers for SMS follow-up, which expands use of personal data beyond the stated email-campaign purpose. Even if operationally convenient, this creates a secondary-contact workflow without any documented consent, minimization, or compliance controls, increasing privacy and abuse risk.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The SMS follow-up export is presented without any privacy, consent, or lawful-use warning despite involving phone numbers derived from bounced email contacts. That omission makes misuse more likely by implying the workflow is routine and acceptable without validating recipient permissions or communication preferences.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The remote-debugging-based unsubscribe sync enables browser-driven actions inside the Renatus backoffice, effectively granting administrative automation capabilities from an email operations guide. This widens the attack surface because anyone following the guide with an authenticated browser session could perform sensitive backoffice actions through a locally exposed debugging interface.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

Bulk deletion and unsubscribe-processing commands are documented without prominent warnings about irreversible effects or validation steps. This increases the likelihood of accidental destructive use, especially when processing files that may be malformed, stale, or attacker-influenced.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The guide instructs implementers to collect and transmit personally identifiable information including name, email, phone number, and source URL to a backend service, but it does not mention any privacy notice, consent mechanism, retention policy, or data-handling disclosure. In this context, the omission can lead to noncompliant collection of user data and increased legal and trust risk, especially because the page is intended for public lead registration.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The file states that the system exposes an admin export endpoint for downloading leads, which implies access to personal/business contact data. While authentication details are provided later, the document does not include any explicit warning about handling sensitive lead data, protecting exports, or restricting token sharing.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

This section instructs operators to set passwords, service role keys, and admin tokens, but it does not warn that these values are highly sensitive credentials. For a setup guide that handles back-office passwords and privileged Supabase keys, an explicit caution about secure storage, avoiding logs/shell history exposure, and not committing secrets would be expected.

Content

No source excerpt is available for this finding.

Static analysis

Detected: suspicious.exposed_secret_literal, suspicious.secret_argv_exposure

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
references/supabase-setup.md:31

Instructions pass high-value credentials through process argv.

Critical
Code
suspicious.secret_argv_exposure
Location
references/workflows.md:138