T05 · Unauthorized Access and Privilege Escalation
- Location
scripts/taste_scan.py:127- Finding
Cross-Account Gmail Access Through Unrestricted Credential Fallback
- Content
View full analysis
Vulnerability Details
File Location:
scripts/taste_scan.py:127-156
Vulnerability Type: Cross-account authorization failure
Risk Level: HighVulnerable Code
python # Google Workspace MCP credentials — each account uses its own OAuth client token_paths = [ Path(os.environ.get( "GOOGLE_CREDS_DIR", os.path.expanduser("~/.google_workspace_mcp/credentials") )) / "operator_email.json", # operator (user) — primary for email/calendar Path(os.environ.get( "GOOGLE_CREDS_DIR", os.path.expanduser("~/.google_workspace_mcp/credentials") )) / "agent_email.json", # Indigo Karasu (agent) — fallback ] for token_path in token_paths: if not token_path.exists(): continue try: token_data = json.loads(Path(token_path).read_text()) token_scopes = token_data.get( 'scopes', [ 'https://www.googleapis.com/auth/gmail.readonly', 'https://www.googleapis.com/auth/calendar.readonly' ] ) creds = Credentials.from_authorized_user_file( str(token_path), token_scopes ) if not creds.valid: if creds.expired and creds.refresh_token: creds.refresh(Request()) try: with open(token_path, 'w') as f: f.write(creds.to_json()) except PermissionError: print( f"Warning: cannot write refreshed token to " f"{token_path} (read-only), continuing with " f"in-memory token" ) else: print( f"Skipping {token_path.name}: credentials invalid " f"and cannot be refreshed" ) continue self.gmail_service = build('gmail', 'v1', credentials=creds) self.calendar_servic ...[truncated 3383 chars]- Remediation
View remediation
Remediation Suggestions
-
Separate Gmail and Calendar authentication. Create distinct initialization paths so the operator credential is mandatory for Gmail, while an explicitly authorized fallback may be considered independently for Calendar.
-
Fail closed for Gmail. If the operator credential is missing or invalid, return an authentication error without creating a Gmail client from
agent_email.json. -
Verify the authenticated identity. After initializing Gmail, call the appropriate profile endpoint and compare the authenticated email address against an explicit expected operator identity. Abort on mismatch.
-
Do not infer identity from token filenames. Symlinks or replaced files can make names such as
operator_email.jsonmisleading. Validate the identity represented by the credential itself. -
Restrict scopes per service. Construct Gmail credentials only with the required Gmail read-only scope and Calendar credentials only with required Calendar scopes.
-
Require explicit authorization for cross-account Calendar fallback. If fallback remains necessary, expose it as an opt-in configuration or command flag and record the selected principal in the scan result.
-
Add regression tests. Test that an invalid operator token combined with a valid agent token causes email scanning to fail, while any deliberately supported Calendar-only fallback cannot initialize or access Gmail.
-
