Back to skill

Security audit

Taste

Security checks for vulnerabilities and agentic risk

Overview

The skill is a real taste-modeling tool, but it asks for broad access to sensitive personal accounts and includes update, backup, and credential-fallback behavior that users should review carefully.

Install only if you are comfortable granting access to Gmail, Calendar, Spotify listening history, and transaction-derived consumption records. Before use, disable or tightly control self-update and backups, verify which Google account is authenticated, avoid the known broken historical scan path, and confirm how stored signals/extractions can be deleted.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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)

T05 · Unauthorized Access and Privilege Escalation

Error
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: High

Vulnerable 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

  1. 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.

  2. 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.

  3. 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.

  4. Do not infer identity from token filenames. Symlinks or replaced files can make names such as operator_email.json misleading. Validate the identity represented by the credential itself.

  5. Restrict scopes per service. Construct Gmail credentials only with the required Gmail read-only scope and Calendar credentials only with required Calendar scopes.

  6. 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.

  7. 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.

Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (173)

Intent-Code Divergence

Critical
Category
Not specified by scanner
Confidence
99% confidence
Finding

This is a true vulnerability because the documented behavior causes historical scans to defeat their stated purpose, converting a year of history into a cluster of apparently current events. For a taste-modeling skill built on behavioral consumption signals, this makes downstream preference inference unreliable and can silently pollute the persistent dataset, especially when paired with broken deduplication.

Content

No source excerpt is available for this finding.

Tainted flow: 'redirect_uri' from os.getenv (line 58, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/spotify_auth_helper.py (reported line 83)May include surrounding context.

python
def exchange_code(code, client_id, client_secret, redirect_uri):
    resp = requests.post(
        TOKEN_ENDPOINT,
        data={
            "grant_type": "authorization_code",

Tainted flow: 'refresh_token' from os.getenv (line 30, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/spotify_history_puller.py (reported line 56)May include surrounding context.

python
msg += ". The refresh token requires completing the OAuth Authorization Code flow interactively."
        raise ValueError(msg)
    
    response = requests.post(
        "https://accounts.spotify.com/api/token",
        data={
            "grant_type": "refresh_token",

Tainted flow: 'req' from os.environ.get (line 891, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/taste_scan.py (reported line 902)May include surrounding context.

python
method='POST'
        )

        with urllib.request.urlopen(req, timeout=10) as resp:
            data = json.loads(resp.read().decode('utf-8'))

        places = data.get('places', [])

Self-Modification

High
Category
Rogue Agent
Confidence
90% confidence
Finding

Skill modifies its own code, configuration, or behavior at runtime. Self-modification enables an agent to escalate privileges, disable safety constraints, or install persistent backdoors.

Content

Scanner excerpt · CHANGELOG.md (reported line 40)May include surrounding context.

md
- Gmail OR/AND query pitfall is now a single line inside the email/calendar scan workflow with the corrected snippet inline (was a standalone "Known pitfall" block).
- Calendar multi-scope scanning, cross-calendar dedup, venue-name cleanup, and venue-detection heuristics are now numbered markdown steps inside the scan workflow (previously Python-with-commentary).
- OAuth patterns (Gmail multi-profile, Spotipy, Spotify token refresh pitfall) moved to `references/api_auth.md` with a `<!-- TODO: migrate OAuth to ocas-auth skill -->` marker.
- Default `config.json` moved to `references/config.default.json`; self-update procedure moved to `references/self_update.md`; OKR YAML block replaced by a compact table.

### Added
- `## Installation` section in README.md covering Python venv setup, Spotify MCP `config.yaml` block, and cron registration.

Self-Modification

High
Category
Rogue Agent
Confidence
90% confidence
Finding

Skill modifies its own code, configuration, or behavior at runtime. Self-modification enables an agent to escalate privileges, disable safety constraints, or install persistent backdoors.

Content

Scanner excerpt · CHANGELOG.md (reported line 40)May include surrounding context.

md
- Gmail OR/AND query pitfall is now a single line inside the email/calendar scan workflow with the corrected snippet inline (was a standalone "Known pitfall" block).
- Calendar multi-scope scanning, cross-calendar dedup, venue-name cleanup, and venue-detection heuristics are now numbered markdown steps inside the scan workflow (previously Python-with-commentary).
- OAuth patterns (Gmail multi-profile, Spotipy, Spotify token refresh pitfall) moved to `references/api_auth.md` with a `<!-- TODO: migrate OAuth to ocas-auth skill -->` marker.
- Default `config.json` moved to `references/config.default.json`; self-update procedure moved to `references/self_update.md`; OKR YAML block replaced by a compact table.

### Added
- `## Installation` section in README.md covering Python venv setup, Spotify MCP `config.yaml` block, and cron registration.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The README describes scanning user email and calendar for behavioral signals but does not present an explicit privacy warning, consent model, or data-handling boundaries. Because these are highly sensitive personal data sources, omission of clear notice and controls increases the risk of unauthorized collection, overcollection, and downstream profiling without informed consent.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The README explicitly instructs use of inline Python via terminal() and direct urllib calls as a preferred operational path. That effectively authorizes arbitrary command execution beyond the declared skill purpose, creating a direct avenue for executing unbounded code, exfiltrating data, or modifying local state on systems where the agent has terminal access.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

A self-update/code-retrieval path from GitHub is operationally unrelated to ordinary taste-model generation and expands the attack surface to remote code changes. If invoked automatically or without strict pinning, it can introduce supply-chain risk and unexpected behavior changes in a high-privilege skill.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

A self-update/code-retrieval path from GitHub is operationally unrelated to ordinary taste-model generation and expands the attack surface to remote code changes. If invoked automatically or without strict pinning, it can introduce supply-chain risk and unexpected behavior changes in a high-privilege skill.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

A self-update/code-retrieval path from GitHub is operationally unrelated to ordinary taste-model generation and expands the attack surface to remote code changes. If invoked automatically or without strict pinning, it can introduce supply-chain risk and unexpected behavior changes in a high-privilege skill.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

A self-update/code-retrieval path from GitHub is operationally unrelated to ordinary taste-model generation and expands the attack surface to remote code changes. If invoked automatically or without strict pinning, it can introduce supply-chain risk and unexpected behavior changes in a high-privilege skill.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

A self-update/code-retrieval path from GitHub is operationally unrelated to ordinary taste-model generation and expands the attack surface to remote code changes. If invoked automatically or without strict pinning, it can introduce supply-chain risk and unexpected behavior changes in a high-privilege skill.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

A self-update/code-retrieval path from GitHub is operationally unrelated to ordinary taste-model generation and expands the attack surface to remote code changes. If invoked automatically or without strict pinning, it can introduce supply-chain risk and unexpected behavior changes in a high-privilege skill.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

A self-update/code-retrieval path from GitHub is operationally unrelated to ordinary taste-model generation and expands the attack surface to remote code changes. If invoked automatically or without strict pinning, it can introduce supply-chain risk and unexpected behavior changes in a high-privilege skill.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding

A self-update/code-retrieval path from GitHub is operationally unrelated to ordinary taste-model generation and expands the attack surface to remote code changes. If invoked automatically or without strict pinning, it can introduce supply-chain risk and unexpected behavior changes in a high-privilege skill.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
88% confidence
Finding

A self-update/code-retrieval path from GitHub is operationally unrelated to ordinary taste-model generation and expands the attack surface to remote code changes. If invoked automatically or without strict pinning, it can introduce supply-chain risk and unexpected behavior changes in a high-privilege skill.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

A self-update/code-retrieval path from GitHub is operationally unrelated to ordinary taste-model generation and expands the attack surface to remote code changes. If invoked automatically or without strict pinning, it can introduce supply-chain risk and unexpected behavior changes in a high-privilege skill.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
92% confidence
Finding

A self-update/code-retrieval path from GitHub is operationally unrelated to ordinary taste-model generation and expands the attack surface to remote code changes. If invoked automatically or without strict pinning, it can introduce supply-chain risk and unexpected behavior changes in a high-privilege skill.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

A self-update/code-retrieval path from GitHub is operationally unrelated to ordinary taste-model generation and expands the attack surface to remote code changes. If invoked automatically or without strict pinning, it can introduce supply-chain risk and unexpected behavior changes in a high-privilege skill.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

A self-update/code-retrieval path from GitHub is operationally unrelated to ordinary taste-model generation and expands the attack surface to remote code changes. If invoked automatically or without strict pinning, it can introduce supply-chain risk and unexpected behavior changes in a high-privilege skill.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The skill processes highly sensitive personal consumption data from email, calendars, transactions, and external enrichment services, yet the description does not clearly foreground the privacy implications or off-device transmission. Users may unknowingly authorize broad behavioral surveillance and sharing of location/consumption signals with third parties like Google Places or search services.

Content

No source excerpt is available for this finding.

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 118)May include surrounding context.

md
**IMPORTANT:** `taste_scan.py` must be run with Python 3.13 (`<hermes-venv>/bin/python3.13`), NOT the ocas-taste venv's Python 3.14 (which lacks `googleapiclien

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 368)May include surrounding context.

md
**IMPORTANT:** `taste_scan.py` must be run with Python 3.13 (`<hermes-venv>/bin/python3.13`), NOT the ocas-taste venv's Python 3.14 (which lacks `googleapiclien

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 374)May include surrounding context.

md
**IMPORTANT:** `taste_scan.py` must be run with Python 3.13 (`<hermes-venv>/bin/python3.13`), NOT the ocas-taste venv's Python 3.14 (which lacks `googleapiclien