T09 · Insecure Skill Coding Practices
- Location
scripts/github_explorer.py:217- Finding
Authenticated GitHub repository data may be cached with insufficiently restrictive permissions
- Content
View full analysis
Vulnerability Details
File Location:
scripts/github_explorer.py, lines 217-230
Vulnerability Type: Insecure persistent storage of potentially sensitive repository data
Risk Level: MediumVulnerable Code
python def _cache_set(*parts): result = parts[-1] key_parts = parts[:-1] key = _cache_key(*key_parts) try: os.makedirs(CACHE_DIR, exist_ok=True) path = os.path.join(CACHE_DIR, f"{key}.json") with open(path, "w") as f: json.dump({"_t": time.time(), "_r": result}, f) except OSError: passThe cached data can originate from authenticated repository and README requests:
python def _headers(): headers = { "Accept": "application/vnd.github+json", "User-Agent": "github-explorer-skill", "X-GitHub-Api-Version": "2022-11-28", } token = os.environ.get("GITHUB_TOKEN", "") if token: headers["Authorization"] = f"Bearer {token}" return headerspython detail = _api_get(f"/repos/{repo}") readme = _api_get(f"/repos/{repo}/readme") ... _cache_set("analyze", repo, readme_full, result)Technical Analysis
The Skill optionally authenticates GitHub API requests using
GITHUB_TOKEN. If that token grants access to private repositories, GitHub can return private repository metadata and README content. Theanalyzecommand then stores this response persistently in~/.cache/github-explorer/.The cache directory is created with
os.makedirs()without an explicit0700mode, and cache files are created withopen(path, "w")without an explicit0600mode. Their effective permissions therefore depend on the process umask and the permissions of any pre-existing cache directory. In an environment with a permissive umask, shared user context, exposed home directory, or improperly configured backup process, another local principal or process may be ...[truncated 2050 chars]- Remediation
View remediation
Remediation Suggestions
-
Create and verify the cache directory with owner-only permissions:
python os.makedirs(CACHE_DIR, mode=0o700, exist_ok=True) os.chmod(CACHE_DIR, 0o700)Before using it, verify that the path is a real directory owned by the current user and is not a symbolic link.
-
Create cache files with explicit
0600permissions rather than relying on the process umask. Useos.open()with restrictive flags and wrap the descriptor withos.fdopen(). -
Write through a securely created temporary file in the same directory and atomically publish it with
os.replace(). Reject or avoid symbolic links where the operating system supportsO_NOFOLLOW. -
Disable caching by default for authenticated requests, or require explicit consent before caching responses obtained with
GITHUB_TOKEN. At minimum, provide a dedicated option that prevents caching potentially private data. -
Clearly document that authenticated requests may return and persist private repository information. The existing general cache notice should explicitly mention private metadata and README content.
-
Recommend fine-grained, read-only GitHub tokens restricted to only the required repositories. Avoid recommending broad classic-token scopes such as unrestricted
repoaccess. -
Preserve the existing
--no-cacheoption and advise users to use it whenever analyzing sensitive or private repositories.
-
