Back to skill

Security audit

Boggle Solver

Security checks for vulnerabilities and agentic risk

Overview

This Boggle skill does what it claims, but it downloads missing dictionary files from GitHub when first run.

Install only if you are comfortable with the skill downloading large dictionary text files from GitHub on first use. For stricter environments, pre-download or vendor the dictionaries from a trusted source and consider adding checksum verification or blocking network access after setup.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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 (1)

T08 · Insecure Dependencies

Warning
Location
scripts/solve.py:25
Finding

Unverified Downloads from a Mutable Upstream Source

Content
View full analysis

Vulnerability Details

File Location: scripts/solve.py:25-36, scripts/solve.py:65-77, scripts/solve.py:201; data/download.py:4-12
Vulnerability Type: Unverified remote dependency retrieval
Risk Level: Medium

Vulnerable Code

scripts/solve.py:25-36:

python
def ensure_dictionaries(paths):
    """Auto-download dictionary files from GitHub if missing."""
    import urllib.request
    BASE_URL = 'https://raw.githubusercontent.com/christianhaberl/boggle-openclaw-skill/main/data'
    for path in paths:
        if not os.path.exists(path):
            fname = os.path.basename(path)
            url = f'{BASE_URL}/{fname}'
            print(f'Downloading {fname}...', file=sys.stderr)
            os.makedirs(os.path.dirname(path), exist_ok=True)
            urllib.request.urlretrieve(url, path)
            print(f'  -> {path}', file=sys.stderr)

scripts/solve.py:65-77:

python
def load_dictionaries(paths, min_word_len=DEFAULT_MIN_WORD_LEN):
    words = set()
    for path in paths:
        if not os.path.exists(path):
            print(f"WARNING: Dictionary not found: {path}", file=sys.stderr)
            continue
        before = len(words)
        with open(path, 'r', encoding='utf-8', errors='ignore') as f:
            for line in f:
                w = line.strip().lower()
                if len(w) >= min_word_len and w.isalpha():
                    words.add(w)
        added = len(words) - before
        print(f"Loaded {os.path.basename(path)}: {added} new words ({len(words)} total)", file=sys.stderr)
    return words

scripts/solve.py:201:

python
    ensure_dictionaries(dict_paths)

data/download.py:4-12:

python
DATA_DIR = os.path.dirname(os.path.abspath(__file__))
BASE_URL = "https://raw.githubusercontent.com/christianhaberl/boggle-openclaw-skill/main/data"
FILES = ["words_english_boggle.txt", "words_german_boggle.
...[truncated 2580 chars]
Remediation
View remediation

Remediation Suggestions

  1. Pin each dictionary URL to an immutable commit identifier or versioned release instead of the mutable main branch.
  2. Publish expected SHA-256 digests with the Skill and verify each completed download before it is accepted.
  3. If maintainable signing infrastructure is available, verify a detached digital signature in addition to the digest.
  4. Stream downloads with an explicit connection/read timeout and reject content exceeding a documented maximum byte size.
  5. Download into a securely created temporary file in the destination directory. Validate its size and digest, flush it, and atomically rename it to the final path only after all checks succeed.
  6. Delete temporary or invalid files after failures so a partial download cannot later be treated as a valid dictionary.
  7. Apply explicit limits to the number of dictionary entries and maximum word length before building the trie.
  8. Consider requiring explicit user approval before network retrieval, or distribute verified dictionaries through a trusted, versioned package or release artifact.
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (6)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The skill is presented as using bundled dictionaries, but the documentation also states that dictionaries are auto-downloaded from GitHub on first run if missing. This hidden network behavior expands the trust boundary, creates supply-chain and privacy risks, and can lead to execution in environments where users or policy expect an offline-only word solver.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding

The skill declares no explicit tool scope even though its documented behavior includes reading local files and potentially using the network. Missing permission boundaries makes the skill's actual capabilities less transparent to reviewers and enforcement systems, which can allow unintended file or network access in environments that rely on manifest-declared scopes.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The instruction says to "Always run English and German SEPARATELY" and present both sections every time. This forces a specific language/locale behavior regardless of the user's preference, which matches the policy category for language or locale constraints without user opt-in.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The documentation claims dictionaries are auto-loaded from local paths, but the implementation may fetch them remotely if absent. This mismatch is security-relevant because reviewers and users may make incorrect assumptions about offline behavior and data flow, reducing their ability to assess or restrict network access appropriately.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The solver silently downloads missing dictionaries from GitHub at runtime, which expands the skill's trust boundary beyond local bundled assets. This creates an unnecessary supply-chain and privacy risk: execution now depends on external network availability and on the integrity of a remote repository, despite the skill description implying local-only operation.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

Runtime network access is not required to solve a Boggle board and is inconsistent with the stated purpose of using included dictionaries. Unnecessary outbound requests can leak usage metadata, introduce nondeterministic behavior, and expose the skill to remote content tampering or dependency takeover if the source changes.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.