T09 · Insecure Skill Coding Practices
- Location
scripts/mantenimiento/borrar_vacios.py:14- Finding
Predictable Shared Temporary File Controls Destructive Course Deletion
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
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.
scripts/mantenimiento/borrar_vacios.py:14Predictable Shared Temporary File Controls Destructive Course Deletion
scripts/mantenimiento/limpiar_categorias.py:11Destructive Moodle Operations Lack Confirmation and Are Not Disclosed by the Skill Documentation
scripts/moodle_ws.py:18Moodle Token May Be Sent to an Untrusted or Plaintext Endpoint
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.
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.
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.
File contents flow to a network sink. This may indicate data exfiltration of sensitive files.
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)}")
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.
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.
File contents flow to a network sink. This may indicate data exfiltration of sensitive files.
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"}
File contents flow to a network sink. This may indicate data exfiltration of sensitive files.
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"}
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
No suspicious patterns detected.