Back to skill

Security audit

Moodle Web Services Skill

Security checks for vulnerabilities and agentic risk

Overview

This Moodle skill has legitimate LMS-management functionality, but it also ships under-documented scripts that can delete courses or categories and send broad messages without strong safeguards.

Install only if you are comfortable giving it a Moodle web-service token with meaningful LMS authority. Use a least-privilege token, verify the configured Moodle URL, avoid running the maintenance deletion scripts unless you have independently reviewed the target list, and expect bulk messaging or course/category changes to execute immediately if invoked.

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 (3)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/mantenimiento/borrar_vacios.py:14
Finding

Predictable Shared Temporary File Controls Destructive Course Deletion

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/mantenimiento/limpiar_categorias.py:11
Finding

Destructive Moodle Operations Lack Confirmation and Are Not Disclosed by the Skill Documentation

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/moodle_ws.py:18
Finding

Moodle Token May Be Sent to an Untrusted or Plaintext Endpoint

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (22)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

A skill that advertises enrollment, activity creation, and grading but actually performs different actions such as course duplication and mass messaging is behaviorally misleading. In a school platform context, undeclared bulk messaging or duplication can trigger spam, privacy issues, and accidental changes at scale because operators cannot accurately judge what will happen from the manifest alone.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

A skill that advertises enrollment, activity creation, and grading but actually performs different actions such as course duplication and mass messaging is behaviorally misleading. In a school platform context, undeclared bulk messaging or duplication can trigger spam, privacy issues, and accidental changes at scale because operators cannot accurately judge what will happen from the manifest alone.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

A skill that advertises enrollment, activity creation, and grading but actually performs different actions such as course duplication and mass messaging is behaviorally misleading. In a school platform context, undeclared bulk messaging or duplication can trigger spam, privacy issues, and accidental changes at scale because operators cannot accurately judge what will happen from the manifest alone.

Content

No source excerpt is available for this finding.

Tainted flow: 'config' from open (line 7, file read) → requests.post (network output)

High
Category
Data Flow
Confidence
80% confidence
Finding

File contents flow to a network sink. This may indicate data exfiltration of sensitive files.

Content

Scanner excerpt · scripts/mantenimiento/borrar_vacios.py (reported line 11)May include surrounding context.

python
def call(fn, p={}):
    d = {"wstoken": config["token"], "wsfunction": fn, "moodlewsrestformat": "json", **p}
    return requests.post(config["baseUrl"] + "/webservice/rest/server.php", data=d).json()

ids = json.load(open("/tmp/vacios.json"))
print(f"Cursos a borrar: {len(ids)}")

Missing User Warnings

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The script performs irreversible deletions in a loop based only on IDs from /tmp/vacios.json, with no interactive confirmation, dry-run gate, secondary approval, or provenance validation of the input list. In an agent or automation context, a mistaken or manipulated input file could cause bulk destruction of courses with minimal friction and little opportunity for human intervention.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

This script deletes Moodle courses, which is a destructive capability not disclosed in the skill manifest, creating a dangerous mismatch between declared and actual behavior. Hidden destructive operations materially increase the chance of unauthorized or unexpected data loss, especially in an agent setting where operators may rely on the manifest to understand blast radius.

Content

No source excerpt is available for this finding.

Tainted flow: 'config' from open (line 4, file read) → requests.post (network output)

High
Category
Data Flow
Confidence
80% confidence
Finding

File contents flow to a network sink. This may indicate data exfiltration of sensitive files.

Content

Scanner excerpt · scripts/mantenimiento/check_cursos.py (reported line 8)May include surrounding context.

python
def call(fn, p={}):
    d = {"wstoken": config["token"], "wsfunction": fn, "moodlewsrestformat": "json", **p}
    return requests.post(config["baseUrl"] + "/webservice/rest/server.php", data=d).json()

# Borra categorías vacías de años anteriores al actual
años_viejos = {"2017","2018","2019","2020","2021","2022","2023","2024","2025"}

Tainted flow: 'config' from open (line 4, file read) → requests.post (network output)

High
Category
Data Flow
Confidence
80% confidence
Finding

File contents flow to a network sink. This may indicate data exfiltration of sensitive files.

Content

Scanner excerpt · scripts/mantenimiento/limpiar_categorias.py (reported line 8)May include surrounding context.

python
def call(fn, p={}):
    d = {"wstoken": config["token"], "wsfunction": fn, "moodlewsrestformat": "json", **p}
    return requests.post(config["baseUrl"] + "/webservice/rest/server.php", data=d).json()

# Borra categorías vacías de años anteriores al actual
años_viejos = {"2017","2018","2019","2020","2021","2022","2023","2024","2025"}

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

This script performs destructive deletion of Moodle course categories, but that capability is not described in the skill manifest, which claims course, enrollment, activity, grading, listing, and messaging operations. Hidden destructive behavior expands the effective privilege of the skill and can lead to unauthorized or unexpected data loss if the script is invoked.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

seguimiento_todos iterates through all courses and messages all non-excluded enrolled users with no confirmation or execution guard. Because it operates platform-wide, a single mistaken or malicious invocation can generate large-scale spam and reputational or compliance harm across the institution.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
84% confidence
Finding

The skill declares access to a local secrets file and is intended to call Moodle REST APIs, which implies filesystem and network use, but it does not explicitly restrict or document tool scope. In an agent environment, missing permissions or allowed-tools increases the chance of overbroad execution, unauthorized file access, or unintended network actions with sensitive credentials.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
86% confidence
Finding

The script reads credentials from ~/.openclaw/workspace/secrets/moodle-ws.json and sends the token to a remote Moodle webservice via HTTP requests. While this is likely necessary for the script's function, the file lacks any docstring or explicit warning that it accesses local secrets and transmits them over the network.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The script loads a secret token from a workspace secrets file and uses it in requests to a remote Moodle webservice. There is no confirmation prompt, warning comment, docstring, or other visible disclosure in this file explaining that credentials will be read and sent over the network.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The script writes course metadata and enrollment-derived information to fixed files under /tmp, which is a shared world-accessible location on many systems. This can expose potentially sensitive educational data to other local users or processes, and fixed filenames also increase the risk of overwriting, symlink abuse, or unintended disclosure.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
85% confidence
Finding

The script loads a Moodle web-service token from a secrets path and includes it in outbound POST requests. There is no docstring, comment, or user-facing notice explaining that sensitive credentials are accessed and sent to a remote service.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The script deletes categories immediately after only printing the count, with no interactive confirmation, no dry run, and no recovery path. Because deletion is irreversible in practice and the selection logic is based on broad name matching for years, an operator mistake or unexpected category state could cause significant accidental loss.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

mensaje_a_todos performs a state-changing bulk messaging action to all enrolled users in a course immediately, with no dry-run, confirmation, or recipient review. This creates a real risk of accidental spam, disclosure of inappropriate content, or abuse if an agent is induced to send messages without human verification.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The skill can broadcast messages across every course via seguimiento_todos, which materially exceeds the narrower messaging description and enables mass unsolicited contact of students. In an agent setting, undocumented bulk-reach functionality is dangerous because a user prompt, misconfiguration, or prompt injection could trigger high-scale actions that operators did not intend to expose.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

crear_curso_completo creates remote Moodle resources immediately based on CLI input, without any confirmation or validation of intent. In an agent workflow, this can lead to accidental creation of unwanted courses, namespace clutter, or misuse of privileged tokens to alter LMS state unexpectedly.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

duplicar_curso performs a state-changing duplication of an existing course with no confirmation, preview, or policy check. This can replicate content, settings, and structure into unintended categories, causing operational disruption or unauthorized proliferation of course materials if triggered improperly.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

The natural-language description and examples are entirely Spanish, which can amount to a language/locale policy constraint if users are not given an explicit choice. The file does not state that the skill is region-specific or that Spanish is optional, so it may force a specific language without opt-in.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Low
Category
Not specified by scanner
Confidence
90% confidence
Finding

The manifest says this skill should be used for creating courses, enrolling or unenrolling users, managing activities, sending grades, listing courses/students, or sending internal messages. The code also exposes duplicar_curso, which clones an existing course via core_course_duplicate_course, a materially different capability not mentioned in the manifest description.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.