Back to skill

Security audit

Steam & PC Gaming Companion

Security checks for vulnerabilities and agentic risk

Overview

This Steam companion skill is coherent and purpose-aligned, but users should handle Steam and IGDB credentials carefully.

Install only if you are comfortable giving the agent access to your Steam API key, Steam ID, and public Steam library, wishlist, and achievement data. Avoid pasting a real Twitch client secret directly into the documented curl command; use a safer prompt, secret manager, or rotate the secret afterward if exposed. Be aware that optional IGDB lookups may send searched or library-derived game titles to Twitch/IGDB APIs.

Vulnerability Patterns
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • 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)

T09 · Insecure Skill Coding Practices

Warning
Location
SKILL.md:61
Finding

OAuth Client Secret Exposed Through Shell Command History

Content
View full analysis

Vulnerability Details

File Location: SKILL.md, lines 61–64
Vulnerability Type: OAuth client-secret exposure through command-line arguments
Risk Level: Medium

Vulnerable Code

sh
curl -X POST 'https://id.twitch.tv/oauth2/token' \
  -d 'client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET&grant_type=client_credentials'

The same unsafe pattern is repeated at SKILL.md, lines 850–854:

sh
curl -X POST 'https://id.twitch.tv/oauth2/token' \
  -d 'client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET&grant_type=client_credentials'

Technical Analysis

The instructions require users to substitute their Twitch application client secret directly into an interactive shell command. Once expanded, the secret can be retained in shell history and exposed through terminal transcripts, command auditing, copied diagnostic output, or process inspection available to other sufficiently privileged local users.

The request uses HTTPS and is directed to Twitch's declared OAuth token endpoint. Therefore, the network transfer is required for the optional IGDB integration and is not evidence of malicious exfiltration. The vulnerability is the handling of the secret on the local system before and during transmission, rather than the intended HTTPS recipient.

Attack Path

  1. A user replaces YOUR_CLIENT_SECRET with the real Twitch application secret.
  2. The user executes the documented curl command in an interactive shell.
  3. The expanded command is retained in shell history, terminal logging, command-audit records, or observable process arguments.
  4. Another local user, administrator, support recipient, or log consumer obtains that record.
  5. The party extracts the client ID and client secret.
  6. The party submits those credentials to Twitch's OAuth token endpoint and requests a client-credentials access token.
  7. The resulting token can be used within the permissions and service sco ...[truncated 614 chars]
Remediation
View remediation

Remediation Suggestions

  1. Do not place the client secret literally in an interactive command.

  2. Prompt for it without terminal echo and pass it to curl without embedding it in shell history. For example:

    sh
    read -rsp "Twitch client secret: " IGDB_CLIENT_SECRET
    printf '\n'
    curl --fail-with-body --silent --show-error \
      -X POST 'https://id.twitch.tv/oauth2/token' \
      --data-urlencode "client_id=${IGDB_CLIENT_ID}" \
      --data-urlencode "client_secret=${IGDB_CLIENT_SECRET}" \
      --data-urlencode 'grant_type=client_credentials'
    unset IGDB_CLIENT_SECRET
    
  3. Warn users that environment variables may still be visible to processes with sufficient local privileges and should not be printed or included in diagnostics.

  4. Where supported, use a protected secret manager or a configuration file readable only by the current user rather than persistent command-line text.

  5. Avoid enabling shell tracing while handling credentials and redact secrets from logs and error reports.

  6. Document secret rotation steps so users can revoke and replace a credential after suspected exposure.

  7. Apply the correction to both occurrences at lines 61–64 and 850–854.

Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Rogue AgentSelf-Modification, Session Persistence
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (19)

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

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

  1. Name: anything (e.g. steam-companion), OAuth Redirect: http://localhost, Category: Application Integration
  2. Click Manage on your new app, copy the Client ID
  3. Generate a Client Secret and copy it
  4. Get an access token by running:
    text
    curl -X POST 'https://id.twitch.tv/oauth2/token' \
      -d 'client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET&grant_type=client_credentials'
    

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

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

  1. Name: anything (e.g. steam-companion), OAuth Redirect: http://localhost, Category: Application Integration
  2. Click Manage on your new app, copy the Client ID
  3. Generate a Client Secret and copy it
  4. Get an access token by running:
    text
    curl -X POST 'https://id.twitch.tv/oauth2/token' \
      -d 'client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET&grant_type=client_credentials'
    

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

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

IGDB Token Expired

IGDB access tokens expire after approximately 60 days. If any IGDB API call returns HTTP 401:

text
⚠️ Your IGDB access token has expired.

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

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

IGDB Token Expired

IGDB access tokens expire after approximately 60 days. If any IGDB API call returns HTTP 401:

text
⚠️ Your IGDB access token has expired.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The skill immediately instructs users to connect Steam credentials and summarizes account data such as library contents, play history, achievements, and wishlist information, but it does not present a prominent upfront privacy warning or consent reminder before describing those data-processing features. This increases the risk of users exposing personal gaming profile information without understanding that the skill will retrieve and analyze account-linked data from Steam and related services.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

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

  1. Generate a Client Secret and copy it
  2. Get an access token by running:
    text
    curl -X POST 'https://id.twitch.tv/oauth2/token' \
      -d 'client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET&grant_type=client_credentials'
    
  3. Copy the access_token from the response

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

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

  1. Generate a Client Secret and copy it
  2. Get an access token by running:
    text
    curl -X POST 'https://id.twitch.tv/oauth2/token' \
      -d 'client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET&grant_type=client_credentials'
    
  3. Copy the access_token from the response

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

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

API Call

text
GET https://api.steampowered.com/IPlayerService/GetOwnedGames/v1/

Query parameters:

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

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

API Call

text
GET https://api.steampowered.com/IPlayerService/GetOwnedGames/v1/

Query parameters:

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

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

API Call

text
GET https://api.steampowered.com/IPlayerService/GetOwnedGames/v1/

Query parameters:

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

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

API Call

text
GET https://api.steampowered.com/IPlayerService/GetOwnedGames/v1/

Query parameters:

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

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

API Call

text
GET https://api.steampowered.com/IPlayerService/GetOwnedGames/v1/

Query parameters:

External Transmission

Medium
Category
Data Exfiltration
Confidence
72% confidence
Finding

The recommender sends each candidate game name from the user's library to IGDB or the Steam store, which can disclose aspects of the user's owned titles and inferred preferences to additional third-party endpoints beyond Steam's base account calls. In context this is functionality-related rather than overtly malicious, but the skill does not obtain explicit consent for this enrichment step or explain the privacy implications of transmitting library-derived metadata to optional third parties.

Content

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

md
2. Filter the user's library to games with `playtime_forever < 60` (unplayed) OR `60 <= playtime_forever < 300` (abandoned — gave it a short try).

3. For each candidate game, look up genre data. Use one of these methods:
   - **If IGDB credentials exist**: POST to `https://api.igdb.com/v4/games` with body `search "{game_name}"; fields genres.name, themes.name, total_rating; limit 1;` and headers `Client-ID: {IGDB_CLIENT_ID}`, `Authorization: Bearer {IGDB_ACCESS_TOKEN}`
   - **If no IGDB**: GET `https://store.steampowered.com/api/appdetails?appids={appid}` and extract `data.genres[].description` and `data.short_description`

4. Match games to mood using these genre mappings:

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The achievement API instructions force l=english, and similar hard-coded locale settings appear elsewhere in the document, including l=english and cc=US for store search. This imposes a specific language/region behavior without opt-in or a documented justification, which matches the locale-policy violation criteria.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The schema lookup section explicitly sets l to english, requiring achievement names and descriptions to be fetched in English regardless of user preference. This is a natural-language locale restriction with no opt-in or region-specific justification provided.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

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

If the user says a game name instead of an AppID, resolve it:

text
GET https://api.steampowered.com/ISteamApps/GetAppList/v2/

This returns ALL Steam apps (~180,000). To avoid fetching this every time:

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The fallback search endpoint uses l=english&cc=US, forcing both language and region for game resolution. Since the skill is not documented as US-only or English-only, this creates an avoidable locale-policy issue.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
74% confidence
Finding

Game info lookup prefers IGDB, meaning user-supplied game queries and possibly ownership-derived context may be sent to a third-party service outside Steam. This is not inherently malicious, but without a clear privacy disclosure and opt-in, it expands data sharing beyond what users may expect from a Steam companion skill.

Content

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

Method A: IGDB (preferred, if credentials exist)

text
POST https://api.igdb.com/v4/games

Headers:

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The game info lookup fallback again specifies l=english&cc=US, which forces a particular language and regional store context. The file does not offer users a choice or clearly justify why this locale restriction is necessary.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.