Moodle Connector
Security checks across static analysis, malware telemetry, and agentic risk
Overview
This appears to be a real Moodle integration, but it needs review because it handles Moodle login tokens and private course data while using unclear and sometimes weak credential handling.
Review before installing. If you use it, do not rely on the default 'test-pass' password, protect config.json as a secret if it contains a Moodle token, restrict MCP access to trusted local clients, and periodically clear or secure the cache/download directories.
Static analysis
No static analysis findings were reported for this release.
VirusTotal
VirusTotal findings are pending for this skill version.
Risk analysis
Artifact-based informational review of SKILL.md, metadata, install specs, static scan signals, and capability signals. ClawScan does not execute the skill or run runtime probes.
Private Moodle account data could be protected by a widely known default password, or the MCP integration may not use the user-supplied password the documentation says is required.
The MCP server initializes the Moodle connector with a known hard-coded credential password while exposing account-backed Moodle tools. This weakens the boundary around encrypted Moodle tokens or stored credentials.
_connector = MoodleConnector(
config_path=Path('config.json'),
password='test-pass'
)Require a non-default secret such as MOODLE_CRED_PASSWORD, fail closed if it is missing, and never use 'test-pass' for real credentials.
If users rely on the default, local encrypted credential files may be easy to decrypt by anyone who can access them.
The batch downloader also defaults to the same known password for credential encryption/decryption. For a tool handling Moodle login tokens, that is a material credential-handling weakness.
parser.add_argument(
'--password',
default='test-pass',
help='Encryption password for credentials (default: test-pass)'
)Remove the default password, require an explicit secret, and prefer a secure secret store or environment variable with clear user instructions.
A user may store a real Moodle token in a local plaintext config file without realizing it is not covered by the encrypted credential flow.
The documentation makes a broad encrypted-credentials claim while also instructing users to put the Moodle web-service token in config.json. That can give users a false sense that all secrets are encrypted.
**Security** - Encrypted credentials (PBKDF2 + Fernet) ... # Edit config.json with your Moodle web service token
Clearly distinguish plaintext config tokens from encrypted credential storage, warn users about local file exposure, and support encrypted storage for the primary Moodle token.
Any trusted agent or MCP client connected to this server can request private Moodle information such as grades, assignments, deadlines, and materials.
The MCP server exposes Moodle data, including a full course summary, to connected MCP clients. This is purpose-aligned but sensitive.
Tool(
name="summary",
description="Get full summary of all course data"Enable this MCP server only for trusted local clients and review tool calls that retrieve broad summaries or grades.
Private Moodle data may remain on disk after tool use, even though this is expected for caching.
The connector writes cached values to local JSON files. Because the skill fetches Moodle grades, assignments, materials, and announcements, cached data may include private course information.
class DiskCache:
"""Key-value cache backed by JSON files on disk."""
...
p.write_text(json.dumps(entry, ensure_ascii=False), encoding="utf-8")Review the cache directory, TTL settings, and cleanup process; avoid installing in shared or synced folders unless that is intended.
A connected agent may be able to write downloaded files to paths chosen in the tool call.
The MCP download tool accepts a caller-supplied URL and optional output path. File downloading is central to the skill, but the artifact does not show tight path restrictions at the MCP boundary.
name="download",
description="Download a file from Moodle"
...
"output": {
"type": "string",
"description": "Optional: output file pathRestrict downloads to a dedicated directory by default, validate output paths, and require user confirmation before writing outside that directory.
Installation depends on external package and browser downloads, so the installed behavior can depend on current upstream packages.
The provided install script pulls Python dependencies and installs a browser runtime. This is expected for Playwright-based SSO, but it increases dependency/provenance reliance.
"install": "pip install -r requirements.txt && playwright install chromium"
Install from a trusted source, review dependencies, and prefer pinned versions or a lockfile for reproducible installs.
