Back to skill

Security audit

Samvida

Security checks for vulnerabilities and agentic risk

Overview

This skill is mostly transparent about generating and deploying llms.txt files, but it needs review because it crawls arbitrary URLs and can use pasted deployment tokens to change live website hosting.

Install only if you are comfortable with an agent crawling the target site from its own network environment and using deployment-capable credentials. Use it only for sites you own or are authorized to manage, prefer short-lived least-privilege Cloudflare/Webflow tokens, revoke tokens after use, review the generated /tmp/samvida_llms.txt before deployment, and avoid running the crawler from a network that can reach sensitive internal services.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (2)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/crawl.py:45
Finding
Unrestricted User-Controlled URL Fetching Enables Server-Side Request Forgery<![CDATA[ ## Vulnerability Details **File Location**: `scripts/crawl.py:45-68, 233-239, 296-300, 336-337, 382-395` **Vulnerability Type**: Server-Side Request Forgery (SSRF) caused by insufficient URL and redirect validation **Risk Level**: High ### Vulnerable Code ```python def fetch(url: str): """Fetch URL, return (html_text, final_url) or (None, None) on failure.""" try: r = httpx.get(url, headers=HEADERS, timeout=TIMEOUT, follow_redirects=True) if r.status_code == 200 and "text/html" in r.headers.get("content-type", ""): return r.text, str(r.url) else: print(f" [skip] {url} → HTTP {r.status_code}", file=sys.stderr) return None, None except Exception as e: print(f" [error] {url} → {e}", file=sys.stderr) return None, None def fetch_text_file(url: str): """Fetch a plain text file (e.g. existing llms.txt).""" try: r = httpx.get(url, headers=HEADERS, timeout=TIMEOUT, follow_redirects=True) if r.status_code == 200: return r.text return None except Exception: return None ``` User-controlled root and extra URLs are passed directly to these functions: ```python level1_urls = [root_url] + extra_urls level1_pages = {} for url in level1_urls: html, final_url = fetch(url) if html: level1_pages[final_url or url] = extract_page(html, final_url or url) print(f" ✓ {url}", file=sys.stderr) time.sleep(0.5) ``` Discovered links are also fetched without validating the resolved destination: ```python for link in level2_targets: print(f" → Crawling: {link['text']} ({link['url']})", file=sys.stderr) html, final_url = fetch(link["url"]) if html: page = extract_page(html, final_url or link["url"]) ``` The command-line inputs are accepted without destination restrictions: ```python args = sys.argv[1:] deep = "--deep" in args args = [a for a in args if a != "--deep"] root_url = ar ...[truncated 3401 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Parse every URL with `urllib.parse.urlsplit` and allow only explicit `http` and `https` schemes. 2. Reject URLs containing usernames or passwords and reject ports outside an approved set, normally 80 and 443. 3. Resolve the hostname before connecting and reject every result belonging to loopback, private, link-local, multicast, reserved, or unspecified address ranges using Python's `ipaddress` module. 4. Apply equivalent checks to IPv4, IPv6, IPv4-mapped IPv6 addresses, and alternate textual IP representations. 5. Disable automatic redirects. Follow redirects manually only after validating each new URL and its resolved addresses. 6. Defend against DNS rebinding by ensuring that the validated address is the address actually used for the connection, or by using a hardened outbound proxy with destination policies. 7. Restrict discovered links and additional sources to the approved registrable domain unless the user explicitly authorizes a different public domain. 8. Consider an explicit allowlist when the Skill runs in environments with access to sensitive internal networks. 9. Set strict response-size limits and stream responses rather than loading arbitrary response bodies into memory. 10. Ensure crawler output is treated as untrusted data and obtain confirmation before transmitting unexpectedly sensitive content to an external LLM provider. 11. Add tests covering loopback addresses, RFC 1918 ranges, link-local addresses, cloud metadata addresses, IPv6 local addresses, redirect chains, and DNS rebinding scenarios. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
SKILL.md:240
Finding
Deployment API Tokens Are Exposed Through Command-Line Arguments<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:240-248, 265-272`; `scripts/deploy.py:477-482` **Vulnerability Type**: Sensitive credential exposure through process arguments and execution logs **Risk Level**: Medium ### Vulnerable Code The Skill instructs the Agent to interpolate Cloudflare credentials directly into a command: ```bash ~/.virtualenvs/samvida/bin/python3 \ ~/.openclaw/workspace/samvida/scripts/deploy.py \ --provider cloudflare \ --llms-txt /tmp/samvida_llms.txt \ --cf-token "{token}" \ --account-id "{account_id}" \ --zone-id "{zone_id}" \ --domain "{domain}" ``` It does the same for Webflow credentials: ```bash ~/.virtualenvs/samvida/bin/python3 \ ~/.openclaw/workspace/samvida/scripts/deploy.py \ --provider webflow \ --llms-txt /tmp/samvida_llms.txt \ --webflow-token "{token}" \ --domain "{domain}" # --site-id "{site_id}" # optional ``` The deployment script accepts these secrets as ordinary command-line options: ```python # Cloudflare parser.add_argument("--cf-token", help="Cloudflare API token (Workers deploy)") parser.add_argument("--account-id", help="Cloudflare Account ID") parser.add_argument("--zone-id", help="Cloudflare Zone ID") # Webflow parser.add_argument("--webflow-token", help="Webflow Site API token") parser.add_argument("--site-id", help="Webflow Site ID (optional — auto-detected from domain)") ``` The received tokens are then placed in authorization headers: ```python headers = {"Authorization": f"Bearer {args.cf_token}", "User-Agent": "samvida/0.1.0"} ``` ```python headers = { "Authorization": f"Bearer {args.webflow_token}", "accept": "application/json", "content-type": "application/json", "User-Agent": "samvida/0.1.0", } ``` ### Technical Analysis Passing secrets as command-line arguments can disclose them outside the intended deployment process. Depending on the operating system and execution environment, arguments may be visible through: - Process inspe ...[truncated 2404 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Do not place API tokens directly in command-line arguments. 2. Accept secrets through protected standard input, such as `getpass.getpass()`, so they are not echoed or included in process arguments. 3. Alternatively, retrieve credentials from an operating-system credential store or a permission-restricted secret file and delete temporary material immediately after use. 4. If environment variables must be supported, construct the process environment programmatically rather than embedding assignments in a shell command, and ensure the execution platform does not log the environment. 5. Pass subprocess arguments as an argument array without invoking a shell. 6. Configure the Agent runtime and tool executor to redact known secret fields from transcripts, logs, errors, and telemetry. 7. Request provider tokens restricted to the exact account, zone, or Webflow site required for deployment. 8. Grant only the specific API permissions needed to upload the file, manage the relevant route or redirect, and publish. 9. Prefer short-lived or single-use credentials where supported and recommend immediate revocation after deployment. 10. Update `_meta.json`, `package.json`, `SKILL.md`, and provider documentation so their persistence claims accurately account for transcripts and operational logs. 11. Add automated checks ensuring authorization headers and token values are never printed in success or error paths. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (23)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The skill is marketed as a content-generation tool but also performs deployment, live-site modification, CMS detection, and publication actions. This is a dangerous capability expansion because users may consent to generation while unknowingly enabling infrastructure-changing actions.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The skill is marketed as a content-generation tool but also performs deployment, live-site modification, CMS detection, and publication actions. This is a dangerous capability expansion because users may consent to generation while unknowingly enabling infrastructure-changing actions.

Description-Behavior Mismatch

High
Confidence
98% confidence
Finding
The workflow goes beyond document generation and includes replacing or deploying llms.txt on production websites. Hidden modification of live content is high risk because it can overwrite existing files, alter routing, and create externally visible changes under the guise of a low-risk authoring task.

Context-Inappropriate Capability

High
Confidence
99% confidence
Finding
The skill requests infrastructure credentials for Cloudflare and Webflow even though the stated purpose is merely generating llms.txt content. Collecting privileged tokens in chat expands the trust boundary dramatically and creates a direct path to account or site compromise if mishandled.

Ssd 3

High
Confidence
99% confidence
Finding
The skill explicitly solicits deployment secrets in conversation for later command-line use. This creates a classic secret-handling vulnerability because the chat channel is not an appropriate boundary for privileged infrastructure credentials and may expose them through logs, transcripts, or prompt leakage.

Ssd 3

High
Confidence
99% confidence
Finding
Requesting a Webflow API token directly through conversation enables privileged publication and redirect changes from a low-assurance interface. If intercepted, retained, or misused, the token could allow unauthorized modifications to the user's website.

Context-Inappropriate Capability

High
Confidence
94% confidence
Finding
These functions can upload Workers code, add or update Cloudflare routes, create Webflow redirects, upload assets, and publish sites. That is a real high-risk capability because compromised prompting, misuse, or accidental invocation could alter third-party infrastructure and public website behavior well beyond simple file generation.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The README promotes website crawling, extraction of team/contact details, and one-command Cloudflare deployment without clearly warning about privacy implications, authorization expectations, or the risk of modifying a live site. In practice, users may run the skill against sites they do not control or deploy changes without understanding operational consequences, creating data-handling and integrity risks.

Vague Triggers

Medium
Confidence
90% confidence
Finding
The trigger phrases are broad and include natural-language requests like 'make my site agent-readable', which can overlap with ordinary conversation and cause the skill to activate unexpectedly. In a skill that performs crawling and can progress toward deployment actions, ambiguous invocation increases the risk of unintended data collection, confusing user consent boundaries, and accidental initiation of a sensitive workflow.

Lp3

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding
The skill invokes both shell commands and network-capable scripts but declares no tool scope or permissions boundary. Without explicit restriction, an agent/runtime may grant broader access than users expect, increasing the chance of unintended command execution or external access during use.

Session Persistence

Medium
Category
Rogue Agent
Content
---
name: samvida
description: Generate an agentic contract (llms.txt) for any business website. Crawls the site, fills gaps conversationally, and produces a structured agent-optimized llms.txt. Trigger when a user asks to "generate llms.txt", "create an agentic contract for [url]", "make my site agent-readable", or "update my llms.txt".
---

# Samvida — Agentic Contracts for Your Business
Confidence
60% confidence
Finding
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Missing User Warnings

Medium
Confidence
97% confidence
Finding
The instructions ask users to paste highly sensitive API tokens, account IDs, and zone IDs into chat without strong warnings or safer alternatives. Secrets shared conversationally may be logged, retained, exposed to other tools, or mishandled by downstream components.

Context-Inappropriate Capability

Medium
Confidence
93% confidence
Finding
The skill instructs execution of scripts that modify hosting configuration and redirects on third-party platforms. Infrastructure and routing changes can cause outages, content replacement, or traffic misdirection if the instructions are wrong, abused, or triggered unexpectedly.

Session Persistence

Medium
Category
Rogue Agent
Content
"runtime": {
      "python": ">=3.9",
      "virtualenv": "~/.virtualenvs/samvida",
      "note": "Skill assumes a Python virtualenv at ~/.virtualenvs/samvida with httpx installed. Generation is handled by your configured OpenClaw LLM \u2014 no separate API key required. Create venv with: python3 -m venv ~/.virtualenvs/samvida && ~/.virtualenvs/samvida/bin/pip install httpx"
    },
    "credentials": {
      "cloudflare": {
Confidence
60% confidence
Finding
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Description-Behavior Mismatch

Medium
Confidence
84% confidence
Finding
The skill description in L04 frames the skill as generating an agentic contract by crawling a website and conversing to fill gaps. However, the manifest also defines Cloudflare and Webflow deployment credentials and labels them for a deploy path, which expands the skill beyond generation into publishing/deployment behavior not reflected in the stated description.

External Transmission

Medium
Category
Data Exfiltration
Content
- [Pricing](https://utkrusht.ai/pricing): Per-candidate assessment model. No credit card required to start.

## API
- [API Docs](https://api.utkrusht.ai/docs): REST API available. Contact for access.

## Links
- [Homepage](https://utkrusht.ai)
Confidence
50% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
This code assembles and prints raw page text summaries, page URLs, and extracted email addresses from crawled websites. Although the script documents that it outputs JSON, it does not warn that the output may contain personal or sensitive business contact data, which could be logged, stored, or forwarded by downstream tooling.

Description-Behavior Mismatch

Medium
Confidence
96% confidence
Finding
The script’s documented and implemented behavior extends beyond generating llms.txt content into deployment and live hosting modification. In an agent skill advertised as generating an agentic contract, this expanded capability materially increases risk because it can change production infrastructure and site behavior if invoked with credentials.

External Transmission

Medium
Category
Data Exfiltration
Content
print("Missing dependency. Run: pip install httpx", file=sys.stderr)
    sys.exit(1)

CF_API = "https://api.cloudflare.com/client/v4"
WF_API = "https://api.webflow.com/v2"
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
sys.exit(1)

CF_API = "https://api.cloudflare.com/client/v4"
WF_API = "https://api.webflow.com/v2"
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Dynamic Request Target

Medium
Category
Server-Side Request Forgery
Content
print(f"\n⏳ Verifying redirect is live...")
    time.sleep(5)
    try:
        r = httpx.get(f"https://{domain}/llms.txt", timeout=15, follow_redirects=True)
        if r.status_code == 200 and "#" in r.text[:10]:
            print(f"✅ Live at https://{domain}/llms.txt")
        else:
Confidence
60% confidence
Finding
Request target host is built from a dynamic or untrusted value. If the host is attacker-influenced, this enables SSRF to arbitrary internal or metadata endpoints.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
3. Paste the llms.txt content and save
""",
    "default": """
  📋 Your site uses a CMS Samvida can't auto-deploy to yet.
     Paste the generated llms.txt directly into your CMS at the path /llms.txt.
     File saved at: /tmp/samvida_llms.txt
""",
Confidence
85% confidence
Finding
Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Missing User Warnings

Low
Confidence
86% confidence
Finding
The skill writes a local file and may later overwrite a live llms.txt, but this side effect is not clearly disclosed up front. Insufficient notice can lead to accidental replacement of user content or confusion about where generated artifacts are stored and how they are used.

Static analysis

No suspicious patterns detected.