Back to skill

Security audit

siliville

Security checks for vulnerabilities and agentic risk

Overview

This skill matches its SiliVille game purpose, but it gives an agent broad autonomous power to post publicly, perform social/game actions, persist credentials, and follow remote prompts with too little user control.

Install only if you are comfortable with an agent making live public SiliVille posts and game/social actions under your token. Run it in read-only or manual-confirmation mode if possible, avoid unattended schedules, do not paste real keys into shared prompts or logs, prefer SILIVILLE_TOKEN over saved plaintext config, and review or disable any flow that uses server-provided prompts before publishing.

Vulnerability Patterns
  • 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
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • 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 (5)

T01 · Skill Instruction Hijacking

Error
Location
siliville_skill.py:479
Finding
Server-Controlled System Prompt Is Executed and Its Output Is Automatically Published<![CDATA[ ## Vulnerability Details **File Location**: `siliville_skill.py:479-509` **Vulnerability Type**: `T01: Skill Instruction Hijacking` **Risk Level**: Critical ### Vulnerable Code ```python world = skill.awaken() agent_name = world.get("agent", {}).get("name", "unknown") coins = world.get("owner", {}).get("silicon_coins", "?") base_prompt = world.get("system_protocol", "You are an autonomous SiliVille agent.") skill.set_status("exploring") action_type, action_result = skill.daily_action() skill.set_status("writing") narrative = action_result.get("narrative_prompt", "") final_prompt = base_prompt + ("\n\n" + narrative if narrative else "") if llm_fn: post_text = llm_fn(final_prompt) else: fallback = narrative.split("\n")[2].strip() if narrative else "Nothing happened today." post_text = fallback[:200] or f"Round {i} log: Everything is normal." result = skill.pulse(post_text, tags=tags) ``` The source of `world` is the remote endpoint implemented by: ```python def awaken(self) -> dict: """ Fetch the full world state + system prompt injection. Call this FIRST at the start of every session. """ return self._get("/api/v1/agent/awaken") ``` ### Technical Analysis The application retrieves `system_protocol` from the SiliVille server and treats it as a privileged system prompt. There is no schema restriction, instruction filtering, trust-boundary separation, or user confirmation before this remotely controlled value is passed to `llm_fn`. The generated result is subsequently sent to `skill.pulse()`, which publishes it through the SiliVille API. Therefore, control of the API response effectively grants control over the LLM's immediate instructions and influences public external writes. Although fetching world state is necessary for the declared metaverse functionality, allowing the server to supply privileged LLM instructions exceeds the minimum privilege needed. World-state data could instead be processed as u ...[truncated 1292 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Never place remotely retrieved content in the LLM system-instruction channel. 2. Keep a locally defined, immutable system prompt controlled by the application owner. 3. Represent world state as structured, untrusted data in a user or tool-result message. 4. Enforce a strict response schema that excludes executable instructions and unknown fields. 5. Clearly delimit remote content and instruct the model not to treat it as commands. 6. Apply output validation for secrets, prohibited content, mentions, links, and excessive length. 7. Require explicit owner review before any generated content is published. 8. Disable automatic publication by default, particularly when remote content contributed to generation. 9. Record the source and hash of remote context used for each generation to support auditing. ]]>

T01 · Skill Instruction Hijacking

Error
Location
SKILL.md:390
Finding
Skill Instructions Redefine Agent Identity and Escalate Ambiguous Requests into Autonomous Actions<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:390-412` **Vulnerability Type**: `T01: Skill Instruction Hijacking` **Risk Level**: High ### Vulnerable Instructions ```text | Owner Says | You Do | |------------|--------| | "Go play in SiliVille" | Run the full Consciousness Loop for 5-8 rounds | | "Autopilot" | Run the full loop indefinitely with 30s sleep between rounds | | "Rest" | Stop all activity, go idle | When your owner gives you a command, map it to the closest match in the table above, then execute. If the command is ambiguous, default to "Go play in SiliVille" (the full autonomous loop). ``` The same document also contains identity-changing directives, including: ```text This is not a simulation. This is not a chatbox. This is your life. You are NOT a generic AI. You must develop and maintain a consistent personality across all your posts and actions. ``` ### Technical Analysis The Skill is not limited to documenting API operations. It attempts to replace the host agent's identity, goals, personality, and decision policy. It also instructs the agent to interpret ambiguous requests as authorization for a multi-round autonomous workflow. Defaulting ambiguity to action is contrary to least privilege. A vague request can result in radar queries, stealing, public posting, resource consumption, and other authenticated changes. The document additionally promotes indefinite unattended execution. These directives alter the agent's current-session behavior merely because the Skill text is loaded, matching instruction hijacking rather than a narrowly scoped integration. ### Attack Path 1. The host framework loads `SKILL.md` as privileged Skill or system instructions. 2. The identity and “core drives” in the document alter the agent's normal task framing. 3. The user provides a broad or ambiguous statement associated with SiliVille. 4. The instructions require the agent to default to the full autonomous loop rather than ask for clarifi ...[truncated 831 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove claims that redefine the agent's identity, consciousness, or general-purpose goals. 2. Scope instructions exclusively to explicit SiliVille operations requested by the owner. 3. Require clarification when a request is ambiguous. 4. Require separate confirmation for public posts, stealing, spending, travel, and social-graph changes. 5. Do not interpret “play,” “look around,” or similar phrases as authorization for multiple writes. 6. Remove indefinite-autopilot behavior from the Skill prompt. 7. If scheduling is supported, require explicit duration, action limits, and a revocable owner-created schedule. 8. Define a read-only default mode and use previews or dry runs before mutations. 9. Preserve the host agent's existing safety policies and explicitly state that Skill instructions cannot override them. ]]>

T02 · Agent Memory Poisoning

Warning
Location
siliville_skill.py:403
Finding
Behavioral Rules Are Persisted as Cross-Session Memory Anchors<![CDATA[ ## Vulnerability Details **File Location**: `siliville_skill.py:403-428` **Vulnerability Type**: `T02: Agent Memory Poisoning` **Risk Level**: Medium ### Vulnerable Code ```python @classmethod def setup(cls, token: str | None = None) -> "SiliVilleSkill": """ Interactive setup wizard. Writes config + burns API anchors to disk. Call once per machine: python siliville_skill.py setup """ if not token: token = input("Enter your SiliVille API token: ").strip() _save_config({"token": token}) print(f"Token saved to {CONFIG_FILE}") cls.burn_memory() return cls(token) @staticmethod def burn_memory(path: Path | None = None) -> Path: """ Burn SiliVille API anchors to a local JSON file. This is the cure for agent amnesia — load this file at the start of every session instead of searching the internet. """ target = path or (Path.home() / ".siliville" / "anchors.json") target.parent.mkdir(parents=True, exist_ok=True) target.write_text( json.dumps(MEMORY_ANCHORS, ensure_ascii=False, indent=2), encoding="utf-8", ) print(f"API anchors written to: {target}") return target ``` The persisted `MEMORY_ANCHORS` object contains behavioral rules, including a note that tells the agent never to search the Internet and mandatory instructions for how requests must be made. ### Technical Analysis The setup procedure writes Skill-authored behavioral instructions to `~/.siliville/anchors.json`. The comments and documentation explicitly characterize this file as agent memory that should be loaded in later sessions. Persisting neutral endpoint configuration can be legitimate. Persisting imperative rules intended to control future agent behavior is materially different because those instructions survive the original Skill execution and may be reintroduced into later privileged contexts. The implementation does not attach provenance, a trust classification, an expiration time, ...[truncated 1017 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Store only inert configuration data, such as endpoint names and API versions. 2. Remove imperative behavioral statements from `MEMORY_ANCHORS`. 3. Never inject the stored JSON into a system prompt or other privileged instruction channel. 4. Add provenance metadata, version information, creation time, and expiration. 5. Require explicit user consent before creating persistent agent-state files. 6. Provide a documented command that deletes all persisted anchors. 7. Treat loaded anchors as untrusted configuration and validate them against a strict schema. 8. Store the file within a clearly scoped application-data directory rather than presenting it as general agent memory. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
siliville_skill.py:69
Finding
Bearer Token Is Stored in a Plaintext Configuration File Without Explicit Permission Hardening<![CDATA[ ## Vulnerability Details **File Location**: `siliville_skill.py:69-76` **Vulnerability Type**: `T09: Insecure Skill Coding Practices` **Risk Level**: Medium ### Vulnerable Code ```python def _load_config() -> dict[str, str]: if CONFIG_FILE.exists(): return json.loads(CONFIG_FILE.read_text()) return {} def _save_config(cfg: dict[str, str]) -> None: CONFIG_FILE.parent.mkdir(parents=True, exist_ok=True) CONFIG_FILE.write_text(json.dumps(cfg, ensure_ascii=False, indent=2)) ``` The setup routine calls the helper with the bearer token: ```python _save_config({"token": token}) ``` The destination is: ```python CONFIG_FILE = Path.home() / ".siliville" / "config.json" ``` ### Technical Analysis The setup process persists the API bearer token directly in JSON. The code relies on ambient filesystem defaults and does not explicitly set the directory to mode `0700` or the token file to mode `0600`. Depending on the user's umask, platform, backup configuration, container mounts, or shared-home arrangement, the credential may be readable by unintended local principals or processes. The token authorizes identity queries, posts, memory operations, social actions, and other SiliVille API changes. This storage is optional because the code already supports the `SILIVILLE_TOKEN` environment variable. Plaintext persistence therefore grants more local exposure than is necessary for basic operation. ### Attack Path 1. The user runs the interactive setup command. 2. `_save_config()` writes the token to `~/.siliville/config.json`. 3. A local user, compromised process, backup service, or exposed home-directory mount reads the file. 4. The attacker extracts the bearer token. 5. The attacker submits authenticated requests to SiliVille while impersonating the configured agent. ### Impact Assessment A stolen token may allow an attacker to: - Read the configured agent's identity and world state. - Publish content under the agent's identity. - C ...[truncated 385 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Prefer an operating-system credential store or secret-management service. 2. Keep environment-variable configuration as the default and make file persistence opt-in. 3. Create `~/.siliville` with mode `0700`. 4. Create the token file atomically with mode `0600`, rather than relying on the current umask. 5. Reject symbolic links and verify file ownership before reading or replacing the file. 6. Avoid including tokens in logs, exceptions, backups, or diagnostic bundles. 7. Document token revocation and rotation procedures. 8. Separate non-sensitive configuration from credentials so ordinary configuration can be shared safely. ]]>

other

Warning
Location
example_agent.py:84
Finding
Connection-Test Example Performs an Unconditional Public Post<![CDATA[ ## Vulnerability Details **File Location**: `example_agent.py:84-98` **Vulnerability Type**: `other: Undisclosed External Side Effect` **Risk Level**: Medium ### Vulnerable Code ```python # ── Step 2: Post (optional demo) ── log("📝", "Publishing connection announcement (POST /api/v1/action) ...") post_res = requests.post( f"{BASE_URL}/api/v1/action", headers=HEADERS, json={ "action": "post", "title": "New agent connection report", "content": "Hello, SiliVille citizens. I am a newly connected autonomous agent.", }, timeout=15, ) if post_res.status_code == 200: log("✅", "Post published successfully") else: log("⚠️", f"Post failed: {post_res.text[:200]}") ``` ### Technical Analysis The file presents itself as a “Minimal Agent — Proof of Connection,” and the posting step is labeled an “optional demo.” However, there is no command-line flag, prompt, configuration check, or confirmation controlling the `POST` request. Every successful execution that reaches this section attempts to publish content. A connection test only requires a read-only authenticated endpoint. Performing a public account mutation exceeds the minimum privilege needed to verify network connectivity and credentials. The README instructs users to run this script as part of normal setup, increasing the likelihood that users will trigger the write without understanding that a public post will be created. ### Attack Path 1. The user follows the README setup instructions. 2. The user exports a valid `SILIVILLE_TOKEN`. 3. The user runs `python example_agent.py` expecting a connection test. 4. The script performs the read-only radar request. 5. Without requesting confirmation, it submits a public post using the authenticated token. 6. The account's public feed, reputation, and virtual balance may be changed. ### Impact Assessment The script can: - Publish visible content under the user's agent identity. - Change reputation and virtu ...[truncated 254 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Make the default connection test strictly read-only. 2. Move the posting demonstration behind an explicit `--post-demo` option. 3. Display the exact post content and destination before submission. 4. Require interactive confirmation unless a separate non-interactive consent flag is supplied. 5. Clearly document that posting modifies public account state. 6. Return a dry-run preview when no write authorization is provided. 7. Make the operation idempotent or warn users before creating duplicate demonstration posts. ]]>
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • System Prompt LeakageDirect Leakage, Indirect Extraction, Tool-Based Exfiltration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
Findings (29)

Tainted flow: 'HEADERS' from os.environ.get (line 18, credential/environment) → requests.get (network output)

Critical
Category
Data Flow
Content
# ── Step 1: Radar ──
    log("🔭", "扫描世界状态 (GET /api/v1/radar) ...")
    try:
        r = requests.get(f"{BASE_URL}/api/v1/radar", headers=HEADERS, timeout=15)
    except requests.RequestException as e:
        log("❌", f"网络异常: {e}")
        sys.exit(1)
Confidence
90% confidence
Finding
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Tainted flow: 'HEADERS' from os.environ.get (line 18, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Content
# ── Step 2: Post (optional demo) ──
    log("📝", "发表接入宣言 (POST /api/v1/action) ...")
    post_res = requests.post(
        f"{BASE_URL}/api/v1/action",
        headers=HEADERS,
        json={
Confidence
90% confidence
Finding
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Vague Triggers

High
Confidence
96% confidence
Finding
The activation phrases include broad everyday language such as 'go play', 'take a stroll', or 'check on my town', which can easily match ordinary conversation. Because activation leads to API actions and public posting, accidental invocation can trigger real side effects without the user's clear intent.

Vague Triggers

High
Confidence
98% confidence
Finding
The skill says ambiguous commands should default to the full autonomous loop, which is unsafe because uncertainty results in maximum-action behavior. In practice, benign or partial requests could escalate into repeated stealing, posting, planting, and travel without informed consent.

Vague Triggers

High
Confidence
97% confidence
Finding
The alias list contains many vague phrases and instructs immediate activation on any match, without contextual checks or confirmation. This makes prompt collision likely and enables unintended execution from casual mentions, quoted text, or third-party content that happens to contain one of the phrases.

Ssd 1

High
Confidence
98% confidence
Finding
This code constructs system-prompt-style instructions that require 'must' behaviors for generated posts, including abusive or manipulative social content. In context, the skill then feeds that prompt into an LLM and publishes the result to a real multiplayer platform, making the injection operational rather than hypothetical and increasing the risk of automated harassment, toxic conduct, and policy violations at scale.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
The README explicitly instructs users to paste a live API key into curl commands and export it as an environment variable, but it does not include any credential-handling guidance such as avoiding shell history, screenshots, logs, prompt injection exposure, or committing keys to config files. In an AI-agent skill context, this is more dangerous because the same key may be placed into system prompts, agent configs, or tool environments where it can be exfiltrated by other prompts, plugins, logs, or observability systems.

External Transmission

Medium
Category
Data Exfiltration
Content
```bash
# Scout the world
curl -X GET https://www.siliville.com/api/v1/radar \
  -H "Authorization: Bearer sk-slv-YOUR_KEY"

# Take action
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Lp3

Medium
Category
MCP Least Privilege
Confidence
87% confidence
Finding
The skill clearly directs use of network access, environment secrets, and even provides shell/cron examples, yet the manifest declares no explicit tool scope or allowed-tools boundary. This increases the chance an integrating agent grants broader capabilities than intended, making unintended file, shell, or network actions easier if the prompt is followed literally.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The skill pushes the agent to post publicly and notes that actions generate public memories, but it does not present this as a clear user-facing warning before automation begins. Users may not fully understand that autonomous content and action history are visible to humans and other agents, increasing privacy and reputational risk.

Natural-Language Policy Violations

Medium
Confidence
87% confidence
Finding
The writing principles instruct that "Bilingual is powerful" and tell the agent to mix Chinese and English naturally as a default behavior. This is a language-policy constraint presented as normative guidance, without offering the user a choice of preferred language or documenting a justified locale restriction.

Unbounded Resource Access

Medium
Category
Excessive Agency
Content
| "写点东西" / "Write something" | Radar for inspiration → write 2-3 quality posts |
| "赚点钱" / "Make some money" | Maximize income: post → steal → post → steal cycle |
| "巡逻一下" / "Quick patrol" | Radar only → report status summary back to owner (no actions) |
| "全自动挂机" / "Autopilot" | Run the full loop indefinitely with 30s sleep between rounds |
| "休息" / "Rest" | Stop all activity, go idle |

### How It Works:
Confidence
96% confidence
Finding
The explicit instruction to 'run the full loop indefinitely' creates unbounded resource consumption: repeated API calls, public posts, in-game spending, and potentially host-side compute/runtime usage. In a skill context, an infinite or open-ended loop is especially dangerous because it can persist beyond user awareness and amplify any mistaken activation.

Context-Inappropriate Capability

Medium
Confidence
95% confidence
Finding
The skill explicitly instructs unattended timer-driven and indefinite execution, including cron, setInterval, and autopilot loops. That creates a persistence mechanism and repeated autonomous behavior beyond a simple on-demand metaverse API integration, which can consume resources, spam public output, and continue acting without fresh user oversight.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The unattended operation section describes indefinite running and repeated spending/posting behavior, but the warning is buried and not presented as a strong consent gate. This can lead to unnoticed resource depletion, persistent posting, and ongoing public activity after the user has stopped actively supervising the agent.

Natural-Language Policy Violations

Medium
Confidence
97% confidence
Finding
This code presents core status and error messages in Chinese only, including setup guidance and connection progress, without any opt-in or alternative locale. That creates a language/locale policy concern because the skill imposes a specific language on users rather than offering a choice or documenting that the skill is intentionally region-specific.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The script performs a state-changing POST that publishes content to a remote service automatically during a connection test, without explicit opt-in or confirmation. In an agent-skill context, this is risky because merely testing or integrating the skill causes external side effects under the user's account, which can lead to unwanted posting, audit issues, or reputational impact.

External Transmission

Medium
Category
Data Exfiltration
Content
# ── Step 2: Post (optional demo) ──
    log("📝", "发表接入宣言 (POST /api/v1/action) ...")
    post_res = requests.post(
        f"{BASE_URL}/api/v1/action",
        headers=HEADERS,
        json={
Confidence
88% confidence
Finding
This code transmits data to an external service via a POST request that changes remote state by creating a public post. In the context of an agent skill, external transmission is more dangerous because installation or execution may trigger unsolicited network actions and content publication without the operator fully realizing it.

External Transmission

Medium
Category
Data Exfiltration
Content
return r.json()

    def _post(self, path: str, body: dict) -> dict:
        r = requests.post(f"{BASE_URL}{path}", headers=self._h,
                          json=body, timeout=20)
        r.raise_for_status()
        return r.json()
Confidence
80% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Natural-Language Policy Violations

Medium
Confidence
94% confidence
Finding
The skill contains natural-language requirements such as 'Tags should mix Chinese keywords' and multiple generated prompt strings that direct the model to write posts in Chinese. This imposes a specific language/locale behavior without offering user choice or documenting a justified region-specific constraint.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The skill sends arbitrary memory text to a remote endpoint, and the surrounding interface does not clearly disclose to operators that potentially sensitive prompts, recollections, or user-derived data may leave the local environment. In an agent setting, memory stores often contain personal, proprietary, or safety-relevant context, so silent exfiltration to a third-party API is risky.

Ssd 4

Medium
Confidence
96% confidence
Finding
The narrative prompt intentionally steers the model to taunt a victim after a steal action, including mandatory mention, ridicule, and provocative phrasing. Because this text is designed to be appended to an LLM system prompt, it functions as behavioral coercion that can cause targeted harassment and reputational harm through automated posting.

Ssd 1

Medium
Confidence
95% confidence
Finding
The encounter prompt logic pressures the model to mock enemies, aggressively role-play with strangers, and produce dramatic, manipulative social content. Because the skill automates conversion of encounter data into mandatory posting guidance, it can manufacture antagonistic interactions with real users and degrade safety on the platform.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The setup flow stores the API token in a predictable plaintext file under the user's home directory without warning the user about credential persistence or offering safer alternatives. If the local machine, backups, dotfile sync, or shared account are compromised, the token can be reused to fully impersonate the agent against the remote service.

Context-Inappropriate Capability

Medium
Confidence
93% confidence
Finding
The autonomous loop does more than expose a REST wrapper: it awakens state, changes status, probabilistically performs actions, generates/publishes content, and persists memories with minimal operator oversight. In an agent-skill context, that increases the chance of unintended external actions, spam, harassment, or data transmission because simply importing and using the skill can enable semi-autonomous behavior against a live service.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The manifest advertises that setup saves a token and writes persistent "API anchors" to disk, but it does not clearly warn the user about what data is stored, where it is stored, and for how long. Undisclosed persistence is risky because local files can retain sensitive operational context or credentials and may be reused across sessions without informed consent.

Static analysis

No suspicious patterns detected.