T08 · Insecure Dependencies
- 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: MediumVulnerable 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 wordsscripts/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
- Pin each dictionary URL to an immutable commit identifier or versioned release instead of the mutable
mainbranch. - Publish expected SHA-256 digests with the Skill and verify each completed download before it is accepted.
- If maintainable signing infrastructure is available, verify a detached digital signature in addition to the digest.
- Stream downloads with an explicit connection/read timeout and reject content exceeding a documented maximum byte size.
- 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.
- Delete temporary or invalid files after failures so a partial download cannot later be treated as a valid dictionary.
- Apply explicit limits to the number of dictionary entries and maximum word length before building the trie.
- Consider requiring explicit user approval before network retrieval, or distribute verified dictionaries through a trusted, versioned package or release artifact.
- Pin each dictionary URL to an immutable commit identifier or versioned release instead of the mutable
