T09 · Insecure Skill Coding Practices
- Location
scripts/ms-todo-sync.py:58- Finding
OAuth Token and Device-Flow Caches Lack Explicit File Protections
- Content
View full analysis
Vulnerability Details
File Location:
scripts/ms-todo-sync.py:58-76, 123-125, 143-167
Vulnerability Type: Insecure storage of OAuth authentication material
Risk Level: HighVulnerable Code
python # Set cache file path if cache_file is None: cache_file = os.path.join(Path.home(), ".mstodo_token_cache.json") self.cache_file = cache_file # Initialize token cache self.cache = msal.SerializableTokenCache() if os.path.exists(self.cache_file): with open(self.cache_file, "r") as f: self.cache.deserialize(f.read()) # Register cache saving on exit atexit.register(self._save_cache) def _save_cache(self): """Save token cache to file""" if self.cache.has_state_changed: with open(self.cache_file, "w") as f: f.write(self.cache.serialize())python # Save flow information for step 2 use flow_cache_file = os.path.join(Path.home(), ".mstodo_device_flow.json") with open(flow_cache_file, "w") as f: json.dump(flow, f)python try: with open(flow_cache_file, "r") as f: flow = json.load(f) except Exception as e: print(f"✗ Failed to read flow information: {e}") return False app = msal.PublicClientApplication( self.client_id, authority=self.authority, token_cache=self.cache ) # Wait for user to complete authentication result = app.acquire_token_by_device_flow(flow) if "access_token" in result: self.access_token = result["access_token"] self._save_cache() print("✓ Authentication successful! Login information saved, you will be logged in automatically next time.") # Clear flow cache os.remove(flow_cache_file) return TrueTechnical Analysis
The serialized MSAL cache can contain reusable OAuth access and refresh tokens. The device-flow cache contains authentication-flow secrets needed to complete an in-progress login. Both files are ...[truncated 2457 chars]
- Remediation
View remediation
Remediation Suggestions
- Create authentication files with owner-only permissions from the outset, such as mode
0600, rather than correcting permissions only after writing. - Use secure atomic file creation and replacement. On supported platforms, open files with flags equivalent to
O_CREAT,O_EXCL,O_WRONLY, andO_NOFOLLOW. - Verify that any existing cache is a regular file owned by the current user and is not a symbolic link before reading or replacing it.
- Write serialized data to a securely created temporary file in the same directory, flush and synchronize it, and atomically replace the destination.
- Explicitly enforce mode
0600on existing cache files before use. - Delete
~/.mstodo_device_flow.jsonin afinallyblock after success, failure, expiration, cancellation, or interruption. - Remove both token and device-flow caches during logout.
- Avoid including token values or complete flow objects in debug output, exceptions, or logs.
- Document that the cache contains sensitive reusable authentication material and should not be copied, shared, or committed to source control.
- Create authentication files with owner-only permissions from the outset, such as mode
