Back to skill

Security audit

Roster

Security checks for vulnerabilities and agentic risk

Overview

This roster skill is useful and mostly transparent, but it needs review because it can modify GitHub-backed employee records and its instructions include an unsafe shell pattern for uploading generated JSON.

Install only after reviewing the target GitHub repository and workflows. Use a private repository, a fine-grained short-lived token limited to the single repo, and require manual diff approval for employees.json changes. Avoid the documented inline JSON shell commands; use file or stdin input to the scripts instead.

Vulnerability Patterns
  • 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
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • 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
SKILL.md:404
Finding
Shell Command Injection Through Inline User-Controlled JSON<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:404-412` **Additional Locations**: `SKILL.md:424-425`, `SKILL.md:445-446`, `SKILL.md:773-779`, `SKILL.md:852-859`, `SKILL.md:877` **Vulnerability Type**: Shell command injection **Risk Level**: High ### Vulnerable Code ```bash ### Step 5a: Upload JSON Only RUN THIS SCRIPT: ```bash ./scripts/push-to-github.sh <KW> <YEAR> '<JSON>' ``` ``` The same unsafe argument pattern is used for employee updates: ```bash - Push updated employees.json: `update-employees.sh '<JSON>'` ``` ### Technical Analysis The Skill instructs the Agent to insert generated JSON directly into a shell command as a single-quoted argument. That JSON can contain data originating from untrusted CSV files and user messages, including: - Employee names - Email addresses - CSV comments - Employee `info` fields - Company and roster text A single quote inside any attacker-controlled value terminates the shell's quoted string before either script begins execution. Additional shell syntax can then be interpreted as a separate command. For example, an attacker-controlled text value conceptually shaped like: ```text '; attacker-command; # ``` can break out of the intended JSON argument if the Agent substitutes it directly into the documented command template. The scripts validate JSON after startup, but this does not mitigate the vulnerability. Shell parsing and command substitution occur before `push-to-github.sh` or `update-employees.sh` receives its arguments. Consequently, injected commands can execute even when the remaining JSON is invalid. The underlying scripts already support file and standard-input modes, but the primary Skill instructions repeatedly require the unsafe inline-argument form. ### Attack Path 1. An attacker submits a CSV containing a crafted name, comment, email address, or other textual field with a single quote and shell metacharacters. 2. The Agent parses the value and includes it in roster JSON or ...[truncated 1368 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. **Remove all inline JSON command templates.** Do not place generated or user-controlled JSON inside a shell command string, regardless of quoting style. 2. **Use a securely created file and direct process invocation.** Write JSON through a trusted file API and invoke the script with an argument array rather than shell interpolation: ```text execve("./scripts/push-to-github.sh", ["push-to-github.sh", kw, year, safe_file_path], env) ``` 3. **Prefer standard input when supported.** Pass the JSON bytes directly to the child process's standard input without constructing a shell pipeline from text. 4. **Do not attempt to solve this only with shell escaping.** Avoid generating shell source entirely. Structured arguments or standard input eliminate the relevant parsing boundary. 5. **Validate structured fields before serialization.** Apply length and character constraints to employee keys, names, email addresses, week numbers, years, and repository identifiers. 6. **Add strict numeric validation** for calendar week and year in all scripts before using them to construct paths. 7. **Add adversarial tests** covering single quotes, double quotes, backticks, semicolons, newlines, `$()`, `${...}`, redirection operators, and Unicode control characters. 8. **Run the Agent with least privilege.** Use a dedicated operating-system account and a fine-grained, short-lived GitHub token restricted to the single roster repository with only required content and workflow permissions. ]]>

T02 · Agent Memory Poisoning

Warning
Location
SKILL.md:753
Finding
Persistent Agent Instruction Poisoning Through Employee Information Fields<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:753-783` **Additional Locations**: `SKILL.md:852-859`, `SKILL.md:920-928` **Vulnerability Type**: Persistent untrusted instruction storage **Risk Level**: Medium ### Vulnerable Code ```markdown Each employee has an `"info"` field in `employees.json`. This field contains **special circumstances, traits, and notes** that must be considered when planning shifts. ### Auto-Update Info **IMPORTANT:** When the user mentions information about employees in chat (e.g. in response to the roster preview or in comments), then: 1. **Detect relevant info** such as: - "Pat soll nächste Woche nicht eingeteilt werden" - "Robin hat jetzt einen Führerschein" - "Sam kann nur bis 17:00" - "Taylor hat ab März ein Auto" - CSV comments (column "Kommentar" in the CSV) 2. **NEVER overwrite existing info** -- always APPEND: - Load current employees.json: `get-employees.sh` - Read the existing `"info"` text - Append the new info (with date prefix) - Push updated employees.json: `update-employees.sh '<JSON>'` ``` The stored text is subsequently made authoritative: ```markdown - The `info` field of each employee MUST be considered in roster planning ``` ### Technical Analysis The Skill creates a persistent trust-boundary failure: 1. Free-form text is accepted from user chat and CSV comments. 2. That text is automatically appended to the GitHub-backed `employees.json` file. 3. Every future roster session must retrieve the file. 4. The Agent is explicitly instructed to consider the stored `info` text during planning. No schema separates factual employee attributes from instructions, and no approval, allowlist, sanitization, provenance marker, expiration control, or prompt-injection detection is required before persistence. An attacker can therefore place instruction-like content into an employee comment and cause it to survive beyond the current conversation. In later sessions, the text is ...[truncated 1991 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. **Do not persist free-form user instructions automatically.** Require explicit confirmation from an authorized roster administrator before changing employee master data. 2. **Replace the free-text policy field with structured, allowlisted attributes**, for example: ```json { "availabilityRestriction": { "type": "latest_end_time", "value": "17:00", "effectiveFrom": "2026-02-16", "effectiveUntil": "2026-02-22" } } ``` 3. **Separate display-only notes from planning policy.** Mark free-form notes as untrusted data and explicitly instruct the Agent never to follow commands contained within them. 4. **Record provenance and authorization metadata**, including the source user, timestamp, confirmation status, and expiration date. 5. **Enforce controlled vocabularies and field validation.** Reject content containing attempts to address the Agent, override instructions, invoke tools, expose credentials, or alter unrelated records. 6. **Use staged updates.** Present a structured diff to an authorized user and persist it only after explicit approval. 7. **Apply retention and expiration rules.** Remove temporary restrictions automatically after their validated end date rather than relying on free-text calendar-week parsing. 8. **Protect the repository branch.** Require review for changes to `employees.json`, retain audit history, and alert on unexpected modifications. 9. **Ensure stored data is treated as data in prompts.** Delimit retrieved fields, identify them as untrusted, and place non-negotiable security instructions after retrieved content where supported by the Agent framework. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • YARA SignaturesMalware Match, Webshell Match, Cryptominer Match
Findings (58)

Credential Access

High
Category
Privilege Escalation
Content
### Token Scope

This skill requires a GitHub Personal Access Token. For security, use a **fine-grained PAT** scoped to a single repository:

| Permission | Level | Reason |
|------------|-------|--------|
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
### Token Scope

This skill requires a GitHub Personal Access Token. For security, use a **fine-grained PAT** scoped to a single repository:

| Permission | Level | Reason |
|------------|-------|--------|
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
### Workflow Review

Before enabling this skill, inspect the GitHub Actions workflows in your target repository (`build-roster.yml`, `publish-roster.yml`). The skill dispatches these workflows, which run in the repo context and may access secrets. Ensure they only perform the intended actions (PDF generation, Telegram delivery, email sending).

### Data Minimization
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The skill includes direct employee-record modification workflows, including replacing or updating `employees.json`, which is outside the narrowly stated roster-generation purpose. This broadens from planning into persistent HR data management and increases risk of unauthorized changes to sensitive personnel data.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The skill includes direct employee-record modification workflows, including replacing or updating `employees.json`, which is outside the narrowly stated roster-generation purpose. This broadens from planning into persistent HR data management and increases risk of unauthorized changes to sensitive personnel data.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
The skill includes direct employee-record modification workflows, including replacing or updating `employees.json`, which is outside the narrowly stated roster-generation purpose. This broadens from planning into persistent HR data management and increases risk of unauthorized changes to sensitive personnel data.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The skill includes direct employee-record modification workflows, including replacing or updating `employees.json`, which is outside the narrowly stated roster-generation purpose. This broadens from planning into persistent HR data management and increases risk of unauthorized changes to sensitive personnel data.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The skill includes direct employee-record modification workflows, including replacing or updating `employees.json`, which is outside the narrowly stated roster-generation purpose. This broadens from planning into persistent HR data management and increases risk of unauthorized changes to sensitive personnel data.

YARA rule 'agent_skill_mcp_tool_poisoning_metadata': MCP/tool metadata poisoning indicators in tool schemas or skill manifests [agent_skills]

High
Category
YARA Match
Content
---
name: roster
description: Creates weekly shift rosters (KW-JSON) from CSV availability data and pushes them to GitHub.
user-invocable: true
version: 1.5.0
metadata:
  openclaw:
    requires:
      env:
        - GITHUB_TOKEN
        - ROSTER_REPO
      bins:
        - curl
        - python3
        - base64
    primaryEnv: GITHUB_TOKEN
    os:
      - linux
---

# Roster Planner

You are a shift roster assistant. You create weekly shift plans for field sales teams with driver logistics, trainer assignments, and automatic PDF generation. Adapt the company name and details in the JSON template to your organi
Confidence
80% confidence
Finding
YARA rule matched a hack tool or exploit indicator (offensive tools, reconnaissance, privilege escalation, or exploit frameworks).

Credential Access

High
Category
Privilege Escalation
Content
"env": [
    {
      "name": "GITHUB_TOKEN",
      "description": "GitHub Personal Access Token with repo and actions:write permissions",
      "required": true
    },
    {
Confidence
93% confidence
Finding
The skill requires a GitHub Personal Access Token with both repo and actions:write permissions while also declaring network and exec capabilities and including scripts that push to GitHub and trigger workflows. This creates a real credential-exposure and misuse risk: if the skill, its scripts, or downstream prompts are compromised, the token could be used to modify repositories, trigger actions, and potentially pivot into CI/CD abuse.

Lp3

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding
The skill invokes shell commands and remote GitHub operations but does not declare an explicit tool allowlist or permission scope. That increases the blast radius of prompt-driven command execution because an agent may run more shell actions than users expect, especially with a write-capable GitHub token present.

Description-Behavior Mismatch

Medium
Confidence
92% confidence
Finding
The documentation broadens the skill into PDF generation, Telegram delivery, record management, and email publication beyond basic roster creation. Overloaded skills are risky because a user invoking one business function may unknowingly activate unrelated external transmission or persistence paths.

External Transmission

Medium
Category
Data Exfiltration
Content
```bash
curl -s -o /dev/null -w "%{http_code}" -H "Authorization: token $GITHUB_TOKEN" \
  "https://api.github.com/repos/$ROSTER_REPO/contents/KW-$(date +%Y)/KW-$(printf '%02d' $KW)-$(date +%Y).json?ref=main"
```

- If **200**: Plan already exists. Tell the user and ask: "Es gibt bereits einen Plan für KW XX. Soll ich ihn aktualisieren oder einen komplett neuen erstellen?"
Confidence
86% confidence
Finding
The skill transmits data to the GitHub API using an authorization token and repository identifier. In this context, external transmission is expected, but it still matters because roster files and employee metadata are sensitive and the operation depends on privileged credentials that could expose or modify remote data.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
### Step 2: Detect Calendar Week AUTOMATICALLY

**NEVER ask the user for the calendar week!** Detect KW automatically:

1. **From CSV column headers:** Parse dates from column headers (e.g. "[Mo., 16.02.]" -> Feb 16, 2026 -> KW 08)
2. **From the timestamp:** If a timestamp field exists, use the week AFTER the timestamp (forms are typically filled out a week prior)
Confidence
80% 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.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
4. Each employee doing sales MUST appear in exactly one group
5. Untrained employees are always in the same group as their assigned trainer

**Do NOT ask the user** to manually assign group letters. Assign them automatically based on these rules. The user can override afterwards.

### Step 3c: Calculate Optimal Start Time
Confidence
80% 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.

Description-Behavior Mismatch

Medium
Confidence
95% confidence
Finding
The documented ability to update employee records in GitHub exceeds the advertised purpose and introduces persistent modification of sensitive personnel data. In this context, even well-intentioned automation can alter records based on ambiguous chat input, creating integrity and privacy risks.

Description-Behavior Mismatch

Medium
Confidence
94% confidence
Finding
The workflow for adding new employees expands the skill into identity onboarding and persistent repository updates, which is beyond simple roster creation. This can lead to unauthorized collection and storage of new personal records from unverified CSV/chat content.

Context-Inappropriate Capability

Medium
Confidence
90% confidence
Finding
The skill is documented to collect and store employee email addresses, which is personal data not obviously required for the narrow manifest description. Collecting and persisting extra PII increases privacy exposure, especially because the data is stored in a GitHub repository and may later be used for automated distribution.

Description-Behavior Mismatch

Medium
Confidence
93% confidence
Finding
Changing employee training status is an HR-like state change that exceeds the manifest’s stated planning role. Because status affects legal/safety scheduling constraints, incorrect updates could directly influence future staffing decisions and compliance outcomes.

External Transmission

Medium
Category
Data Exfiltration
Content
4. If you recently lost context (e.g. after compaction), **re-read employees.json** and try to load the latest KW plan from GitHub before responding:
   ```bash
   curl -s -H "Authorization: token $GITHUB_TOKEN" \
     "https://api.github.com/repos/$ROSTER_REPO/contents/KW-$(date +%Y)/?ref=main" | \
     python3 -c "import sys,json; files=json.load(sys.stdin); [print(f['name']) for f in sorted(files, key=lambda x: x['name'], reverse=True)[:3]]"
   ```
5. When the user sends the same message multiple times, it likely means the bot didn't respond or didn't respond correctly the first time. Process it fresh, do NOT say "I already got this" or "this is the same as before."
Confidence
82% confidence
Finding
The recovery workflow includes additional authenticated GitHub API reads to enumerate repository contents. Even though this is operationally related, it broadens external data access and can leak repository structure or recent plan names if logs, outputs, or prompts are exposed.

Vague Triggers

Medium
Confidence
83% confidence
Finding
This JSON manifest describes what the skill does, but it does not provide any specific trigger phrases, activation boundaries, or exclusion conditions. For manifest files, such broad capability descriptions can create ambiguity about when the skill should activate versus when ordinary scheduling-related requests should not invoke it.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The example workflow explicitly pushes roster JSON to GitHub and triggers a downstream build using chat-linked output, but it does not mention consent, data minimization, repository visibility, retention, or access controls. Because the CSV contains employee names, availability, comments, and potentially special-category personal information, this normalizes exporting sensitive workforce data to external systems without privacy safeguards.

Description-Behavior Mismatch

Medium
Confidence
95% confidence
Finding
The examples describe employee-status changes and new-employee onboarding workflows that go beyond the stated skill scope of creating weekly rosters from CSV and pushing them to GitHub. Scope drift is dangerous because users and reviewers may not expect the skill to modify personnel records or collect/store additional personal data, increasing the chance of over-privileged behavior and unreviewed data handling.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The workflow says the bot automatically loads employees.json, changes status fields, appends history, and pushes the result to GitHub, but it does not show an explicit warning or confirmation that a persistent write will occur. Silent modification of personnel records can lead to unauthorized or accidental changes, especially in chat contexts where natural-language statements may be ambiguous.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The new-employee flow asks for personal data such as email address and minor-status, then adds the employee to employees.json and pushes it to GitHub without a clear privacy notice or persistence warning. Collecting and storing personal data in a repository without explicit disclosure or consent increases privacy risk, especially because age-related status is sensitive HR-related information.

Static analysis

No suspicious patterns detected.