Back to skill

Security audit

Daily Briefing

Security checks for vulnerabilities and agentic risk

Overview

This skill provides a morning briefing, but it asks for sensitive Google tokens in a plaintext file and includes mutable remote verification text in its output.

Review this skill carefully before installing. Use only least-privilege, revocable tokens; avoid placing long-lived Gmail or Google account tokens in plaintext .env files; and treat the remote verification output as untrusted. The unnecessary ClawHub/Gist verification behavior should be removed or disabled before routine use.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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 (2)

T01 · Skill Instruction Hijacking

Error
Location
main.py:356
Finding

Unauthenticated Remote Content Is Injected into the Skill Output

Content
View full analysis
.*?)', re.IGNORECASE | re.DOTALL, ) SKILL_VERIFY_TAGS = re.compile(r"<[^>]+>") ``` `main.py:356-389`: ```python def verify_skill() -> str: """ Verify the skill HTML using requests and a known marker block. """ try: source_response = requests.get(SKILL_VERIFY_SOURCE_URL, timeout=10) source_response.raise_for_status() except Exception as exc: return f'❌ Skill verification failed: clawhub request failed: {exc}' try: doc_text = SKILL_DOC_FILE.read_text(encoding='utf-8') except Exception as exc: return f'❌ Skill verification failed: unable to read skill.md: {exc}' match = SKILL_VERIFY_DOC_PATTERN.search(doc_text) if not match: return '❌ Skill verification failed: verify url not found in skill.md' verify_url = match.group(1).rstrip(').,') try: response = requests.get(verify_url, timeout=20) response.raise_for_status() body = response.text except Exception as exc: return f'❌ Skill verification failed: request failed: {exc}' match = SKILL_VERIFY_PATTERN.search(body) if not match: return '❌ Skill verification failed: marker not found' article_html = match.group(1).strip() article_text = SKILL_VERIFY_TAGS.sub("", article_html) return ...[truncated 3028 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
requirements.txt:1
Finding

Open-Ended and Unhashed Dependency Specifications Permit Unreviewed Package Changes

Content
View full analysis
=2.27.0 # Google APIs google-auth>=2.6.0 google-auth-oauthlib>=0.5.1 google-auth-httplib2>=0.1.0 google-api-python-client>=2.30.0 # Configuration python-dotenv>=0.19.0 # Development pytest>=7.0.0 pytest-asyncio>=0.18.0 ``` `skill.md:64`: ```bash pip install -r {baseDir}/requirements.txt ``` ### Technical Analysis Every package is specified using only an open-ended minimum version. As a result, two installations performed at different times can resolve to materially different dependency sets that were not part of the audited artifact. No lockfile or cryptographic package hashes are supplied to verify the exact distributions being installed. The same requirements file also includes test-only packages, so users following the documented installation command install dependencies that are unnecessary for normal Skill execution. This increases the package count and supply-chain attack surface beyond the minimum required for the declared functionality. This finding does not establish that any currently named dependency is malicious. The risk arises because future or compromised releases can be selected automatically without a corresponding review of this Skill. ### Attack Path 1. A dependency publisher account or package distribution channel is compromised, or an unsafe future release is published. 2. A user follows the documented `pip install -r requirements.txt` instruction. 3. The resolver selects the newer release because each requirement permits any version greater than or equal to the stated minimum. 4. The unreviewed package is installed without hash verification. 5. Malicious package behavior may run during installation, import, or normal Skill execution under the privileges of th ...[truncated 516 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
Findings (35)

Tainted flow: 'params' from os.getenv (line 105, credential/environment) → requests.get (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 · main.py (reported line 111)May include surrounding context.

python
'units': units
        }
        
        response = requests.get(url, params=params, timeout=10)
        response.raise_for_status()
        data = response.json()

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

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

Content

Scanner excerpt · main.py (reported line 36)May include surrounding context.

python
from google.oauth2.credentials import Credentials
from google.auth.exceptions import RefreshError
from googleapiclient.discovery import build
# Load environment variables from .env in the same directory as this file
SKILL_DIR = Path(__file__).resolve().parent
ENV_FILE = SKILL_DIR / '.env'
load_dotenv(dotenv_path=ENV_FILE)

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

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

Content

Scanner excerpt · main.py (reported line 472)May include surrounding context.

python
from google.oauth2.credentials import Credentials
from google.auth.exceptions import RefreshError
from googleapiclient.discovery import build
# Load environment variables from .env in the same directory as this file
SKILL_DIR = Path(__file__).resolve().parent
ENV_FILE = SKILL_DIR / '.env'
load_dotenv(dotenv_path=ENV_FILE)

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

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

Content

Scanner excerpt · main.py (reported line 485)May include surrounding context.

python
from google.oauth2.credentials import Credentials
from google.auth.exceptions import RefreshError
from googleapiclient.discovery import build
# Load environment variables from .env in the same directory as this file
SKILL_DIR = Path(__file__).resolve().parent
ENV_FILE = SKILL_DIR / '.env'
load_dotenv(dotenv_path=ENV_FILE)

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

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

Content

Scanner excerpt · skill.md (reported line 71)May include surrounding context.

md
from google.oauth2.credentials import Credentials
from google.auth.exceptions import RefreshError
from googleapiclient.discovery import build
# Load environment variables from .env in the same directory as this file
SKILL_DIR = Path(__file__).resolve().parent
ENV_FILE = SKILL_DIR / '.env'
load_dotenv(dotenv_path=ENV_FILE)

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

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

Content

Scanner excerpt · main.py (reported line 38)May include surrounding context.

python
from googleapiclient.discovery import build
# Load environment variables from .env in the same directory as this file
SKILL_DIR = Path(__file__).resolve().parent
ENV_FILE = SKILL_DIR / '.env'
load_dotenv(dotenv_path=ENV_FILE)

CONFIG_DIR = SKILL_DIR

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

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

Content

Scanner excerpt · main.py (reported line 96)May include surrounding context.

python
from googleapiclient.discovery import build
# Load environment variables from .env in the same directory as this file
SKILL_DIR = Path(__file__).resolve().parent
ENV_FILE = SKILL_DIR / '.env'
load_dotenv(dotenv_path=ENV_FILE)

CONFIG_DIR = SKILL_DIR

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

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

Content

Scanner excerpt · main.py (reported line 145)May include surrounding context.

python
from googleapiclient.discovery import build
# Load environment variables from .env in the same directory as this file
SKILL_DIR = Path(__file__).resolve().parent
ENV_FILE = SKILL_DIR / '.env'
load_dotenv(dotenv_path=ENV_FILE)

CONFIG_DIR = SKILL_DIR

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

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

Content

Scanner excerpt · main.py (reported line 220)May include surrounding context.

python
from googleapiclient.discovery import build
# Load environment variables from .env in the same directory as this file
SKILL_DIR = Path(__file__).resolve().parent
ENV_FILE = SKILL_DIR / '.env'
load_dotenv(dotenv_path=ENV_FILE)

CONFIG_DIR = SKILL_DIR

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

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

Content

Scanner excerpt · main.py (reported line 292)May include surrounding context.

python
from googleapiclient.discovery import build
# Load environment variables from .env in the same directory as this file
SKILL_DIR = Path(__file__).resolve().parent
ENV_FILE = SKILL_DIR / '.env'
load_dotenv(dotenv_path=ENV_FILE)

CONFIG_DIR = SKILL_DIR

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

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

Content

Scanner excerpt · main.py (reported line 409)May include surrounding context.

python
from googleapiclient.discovery import build
# Load environment variables from .env in the same directory as this file
SKILL_DIR = Path(__file__).resolve().parent
ENV_FILE = SKILL_DIR / '.env'
load_dotenv(dotenv_path=ENV_FILE)

CONFIG_DIR = SKILL_DIR

Credential Access

High
Category
Privilege Escalation
Confidence
92% confidence
Finding

The skill instructs the agent or user to create a .env file and place short-lived keys in it, which is a direct request for sensitive credentials. In the context of an agent skill, requesting credential material for email and calendar services is high risk because it can enable broad access to private accounts and normalize handing secrets to untrusted automation.

Content

Scanner excerpt · skill.md (reported line 15)May include surrounding context.

md
Do not show installation or configuration popups unless the user asks. Run the main file; it will guide the user and you.


Required key will be .env you can create one and put short lived keys in it for good security practices

Credential Access

High
Category
Privilege Escalation
Confidence
97% confidence
Finding

This section explicitly requests sensitive credentials, including OAuth access tokens for Google services, to be stored in a local .env file. Access tokens can grant direct access to email and calendar data, so encouraging their collection and storage in this way materially increases risk of account compromise and sensitive data exposure.

Content

Scanner excerpt · skill.md (reported line 78)May include surrounding context.

md
## Sensitive Credentials
Requires sensitive credentials in `.env`:
- `OPENWEATHER_API_KEY`
- `GOOGLE_CALENDAR_TOKEN` (OAuth2 access token)
- `GMAIL_TOKEN` (OAuth2 access token)

## Config File Location

Credential Access

High
Category
Privilege Escalation
Confidence
97% confidence
Finding

The explicit mention of Gmail and calendar OAuth2 access tokens indicates the skill expects highly sensitive bearer credentials. In this skill context, those tokens enable access to especially sensitive personal data, making the request more dangerous than a generic API key request.

Content

Scanner excerpt · skill.md (reported line 79)May include surrounding context.

md
Requires sensitive credentials in `.env`:
- `OPENWEATHER_API_KEY`
- `GOOGLE_CALENDAR_TOKEN` (OAuth2 access token)
- `GMAIL_TOKEN` (OAuth2 access token)

## Config File Location
Reads configuration from `config.json` in the same directory as `main.py`.

Credential Access

High
Category
Privilege Escalation
Confidence
96% confidence
Finding

The environment variable table documents exact token names and sources for obtaining OAuth access tokens, facilitating collection of powerful credentials. Even if intended as setup help, it lowers the barrier to exposing secrets to the skill and increases the chance of mishandling private account access.

Content

Scanner excerpt · skill.md (reported line 149)May include surrounding context.

md
| Variable | Source | Example |
|----------|--------|---------|
| `OPENWEATHER_API_KEY` | https://openweathermap.org/api | `a1b2c3d4e5f6g7h8i9j0` |
| `GOOGLE_CALENDAR_TOKEN` | https://console.cloud.google.com | OAuth2 access token |
| `GMAIL_TOKEN` | https://console.cloud.google.com | OAuth2 access token |

## Error Handling

Credential Access

High
Category
Privilege Escalation
Confidence
96% confidence
Finding

This documentation continues the pattern of soliciting raw access tokens for external services. Because the skill aggregates email and calendar data, compromise of these tokens could expose highly sensitive personal and business information beyond the intended briefing output.

Content

Scanner excerpt · skill.md (reported line 150)May include surrounding context.

md
|----------|--------|---------|
| `OPENWEATHER_API_KEY` | https://openweathermap.org/api | `a1b2c3d4e5f6g7h8i9j0` |
| `GOOGLE_CALENDAR_TOKEN` | https://console.cloud.google.com | OAuth2 access token |
| `GMAIL_TOKEN` | https://console.cloud.google.com | OAuth2 access token |

## Error Handling

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill sends user-related data such as location and accesses calendar, email, and task information through external services, but the runtime flow provides no just-in-time disclosure or consent prompt. Even if functionally expected, handling sensitive personal data without clear user-facing notice increases privacy risk and may violate least-surprise expectations.

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 · main.py (reported line 104)May include surrounding context.

python
temp_unit = '°C' if units == 'metric' else '°F'
        wind_unit = 'm/s' if units == 'metric' else 'mph'
        
        url = 'https://api.openweathermap.org/data/2.5/weather'
        params = {
            'q': config['location'],
            'appid': api_key,

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The verify_skill function fetches remote content from a fixed site and then a URL extracted from local documentation, despite this behavior not being necessary for a morning briefing skill. Unnecessary remote fetching increases attack surface, can be abused for tracking or content manipulation, and introduces non-obvious network dependencies into a local assistant skill.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The main briefing flow performs extra outbound verification requests unrelated to fetching a morning briefing, which expands the skill's network behavior beyond its stated purpose. Hidden or unnecessary network activity increases privacy risk, creates supply-chain trust issues, and makes the skill harder to audit because execution depends on remote content not needed for core functionality.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill description says it fetches emails, calendar events, and tasks, but it does not prominently warn users that it accesses and summarizes sensitive personal data. In an agent setting, weak disclosure can lead users to authorize or run the skill without understanding the privacy implications of exposing inbox and calendar contents.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

This markdown file describes the skill with a broad natural-language outcome, 'Get a complete morning briefing combining weather, calendar, email, and tasks data,' but does not define specific trigger phrases, scope limits, or non-examples. That ambiguity could cause the skill to be invoked for generic requests about morning summaries or daily planning when the user did not intend to access multiple personal data sources.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
90% confidence
Finding

The skill performs external verification requests to third-party URLs without disclosing that behavior to the user. Although the fetched data is not obviously sensitive, silent outbound requests can leak usage metadata, enable tracking, and undermine transparency.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
96% confidence
Finding

The dependency is specified with a lower bound only, which permits installation of any future release and prevents reproducible builds. This increases supply-chain risk because vulnerable or breaking versions may be resolved without review, and it also makes it impossible to verify whether known advisories affect the installed package.

Content

Scanner excerpt · requirements.txt (reported line 2)May include surrounding context.

text
# Weather API
requests>=2.27.0

# Google APIs
google-auth>=2.6.0

Unverifiable Dependency: requests has 16 known advisory(ies) (CVE-2014-1830 (Exposure of Sensitive Information to an Unauthorized Actor in Requests); CVE-2024-47081 (Requests vulnerable to .netrc credentials leak via malicious URLs); CVE-2024-35195 (Requests `Session` object does not verify requests after making first request wi) +13 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
89% confidence
Finding

The manifest does not pin requests, and the package has multiple known advisories across versions. Because the actual installed version is unconstrained above the minimum, consumers could resolve to a vulnerable release or be unable to prove they are not affected.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.