T05 · Unauthorized Access and Privilege Escalation
- Location
scripts/youtube.py:68- Finding
OAuth Scopes Grant Unnecessary YouTube Account Permissions
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This YouTube skill largely matches its media purpose, but it asks for broader Google account authority than its read-style features need and stores reusable OAuth tokens in a risky way.
Review before installing. Use this only with a Google/YouTube account you are comfortable exposing to the skill, and preferably after the publisher narrows OAuth scopes to read-only, removes the unrelated gogcli credential fallback, replaces pickle token storage with a safer format, documents token storage clearly, and pins dependencies. I did not find direct exfiltration, destructive actions, or prompt hijacking in the artifact, so this is Review rather than malicious.
scripts/youtube.py:68OAuth Scopes Grant Unnecessary YouTube Account Permissions
scripts/youtube.py:107Unsafe Deserialization of Persistent OAuth Token File
scripts/youtube.py:2Runtime Dependencies Are Not Pinned or Integrity Verified
The metadata and description understate the actual capabilities by omitting OAuth authentication, access to authenticated/private YouTube account data, comment retrieval, and local token storage. This is dangerous because users and reviewers may grant or install the skill based on an incomplete understanding of the data it can access and persist, increasing the risk of over-privileged use and unintended exposure of personal account information.
The requested OAuth scopes include broad write-capable permissions (youtube and youtube.force-ssl) even though the implemented functionality is primarily read/list/download oriented. Overbroad scopes violate least privilege and make any token theft or misuse significantly more damaging because the credential could potentially modify or act on the user's YouTube account.
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
CONFIG_DIR = Path.home() / '.config' / 'youtube-skill'
CREDENTIAL_PATHS = [
Path.home() / '.config' / 'youtube-skill' / 'credentials.json',
Path.home() / '.config' / 'gogcli' / 'credentials.json',
]
DEFAULT_ACCOUNT = 'default'
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
CONFIG_DIR = Path.home() / '.config' / 'youtube-skill'
CREDENTIAL_PATHS = [
Path.home() / '.config' / 'youtube-skill' / 'credentials.json',
Path.home() / '.config' / 'gogcli' / 'credentials.json',
]
DEFAULT_ACCOUNT = 'default'
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
CONFIG_DIR = Path.home() / '.config' / 'youtube-skill'
CREDENTIAL_PATHS = [
Path.home() / '.config' / 'youtube-skill' / 'credentials.json',
Path.home() / '.config' / 'gogcli' / 'credentials.json',
]
DEFAULT_ACCOUNT = 'default'
The script searches an additional unrelated path (~/.config/gogcli/credentials.json) for OAuth client secrets, creating unexpected cross-tool credential reuse. This broadens the trust boundary and can cause the skill to consume credentials intended for a different application, surprising users and potentially exposing or misusing credentials across tools.
CONFIG_DIR = Path.home() / '.config' / 'youtube-skill'
CREDENTIAL_PATHS = [
Path.home() / '.config' / 'youtube-skill' / 'credentials.json',
Path.home() / '.config' / 'gogcli' / 'credentials.json',
]
DEFAULT_ACCOUNT = 'default'
The skill advertises network and shell-capable behavior but does not declare any explicit tool scope such as permissions or allowed-tools. That omission weakens least-privilege controls and makes it harder for reviewers and runtime policy engines to constrain what the skill may access, especially because the file also emphasizes trust signals like 'security reviewed' instead of enforceable restrictions.
The skill description emphasizes transcripts, downloads, and exploration, but the code also accesses authenticated personal YouTube data including subscriptions, playlists, liked videos, and the user's own channel. This mismatch increases privacy risk because users may authorize the skill without realizing it can enumerate account-level data beyond the advertised purpose.
The script silently reads and writes OAuth credentials and tokens to local files without clearly warning the user about storage location, persistence, or required protections. In a skill context, that can lead users to unknowingly leave reusable account tokens on disk, increasing exposure if the workstation is shared, backed up insecurely, or otherwise compromised.
pickle.load() will execute attacker-controlled objects during deserialization if the token file is replaced or tampered with. Because the file is loaded automatically from a predictable path in the user's home directory, any local compromise, unsafe file sharing, or symlink/path abuse could turn this into arbitrary code execution when the skill runs.
creds = None
if token_file.exists():
with open(token_file, 'rb') as token:
creds = pickle.load(token)
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
cmd.append(url)
print(f"Downloading: {url}")
subprocess.run(cmd)
def cmd_download_audio(args):
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
cmd.append(url)
print(f"Downloading: {url}")
subprocess.run(cmd)
def cmd_download_audio(args):
No suspicious patterns detected.