Back to skill

Security audit

daily-rhythm

Security checks for vulnerabilities and agentic risk

Overview

The skill is a plausible daily planning automator, but it also accesses and stores sensitive task, calendar, and business subscription data with weak scoping and disclosures.

Review this carefully before installing. Use a dedicated Google OAuth setup with read-only Tasks scope, keep credentials and ICS URLs out of shared folders and repositories, inspect or remove the ARR sync if you do not need it, avoid storing customer_ids, restrict file permissions on the memory and credential directories, and verify every cron job before enabling automation.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (3)

T08 · Insecure Dependencies

Warning
Location
SKILL.md:42
Finding

Unpinned Runtime Dependencies Create a Supply-Chain Risk

Content
View full analysis

Vulnerability Details

File Location: SKILL.md, line 42
Vulnerability Type: Unpinned third-party dependencies
Risk Level: Medium

Vulnerable Code:

bash
pip install google-auth google-auth-oauthlib google-auth-httplib2 google-api-python-client requests

Technical Analysis

The installation instructions retrieve the latest available versions of several packages and their transitive dependencies without a lock file, exact version constraints, or package hashes. Consequently, the installed code can change between deployments without any modification to this Skill.

There is no evidence that the named packages are typosquatted or currently malicious. The vulnerability is the absence of reproducible dependency controls: a compromised upstream release, dependency, package-index account, or resolution result could introduce code that executes during installation or when imported by the synchronization scripts.

Attack Path

  1. An attacker compromises an upstream package, one of its transitive dependencies, or its package-index release account.
  2. A malicious version is published under a dependency name used by the installation command.
  3. A user follows the documented unpinned pip install command.
  4. The malicious package is installed and subsequently imported by the Skill.
  5. The package executes with the privileges of the user running the installation or synchronization scripts.
  6. It can access credentials and data available to that account, including Google OAuth files, SKILLBOSS_API_KEY, task data, customer identifiers, and revenue metrics.

Impact Assessment

Successful exploitation could provide arbitrary Python code execution with the installing or runtime user's privileges. The practical scope includes reading or modifying files accessible to that user, stealing environment variables and OAuth tokens, altering synchronized data, and making unauthorized network requests. The code do ...[truncated 124 chars]

Remediation
View remediation

Remediation Suggestions

  1. Define reviewed, exact package versions in a requirements or lock file.
  2. Generate and verify cryptographic hashes for every direct and transitive dependency.
  3. Install with hash enforcement, for example:
    bash
    python3 -m pip install --require-hashes -r requirements.txt
    
  4. Install dependencies inside an isolated virtual environment rather than the user's global Python environment.
  5. Configure an explicit trusted package index or internally controlled package mirror.
  6. Add automated dependency vulnerability and integrity scanning.
  7. Review and deliberately update the lock file instead of implicitly accepting the latest releases.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/sync-google-tasks.py:20
Finding

OAuth Tokens and Personal Task Data Are Stored Without Explicit Access Controls

Content
View full analysis

Vulnerability Details

File Location: scripts/sync-google-tasks.py, lines 20-40 and 92-97
Vulnerability Type: Insecure local storage of sensitive OAuth and task data
Risk Level: Medium

Vulnerable Code:

python
creds_dir = os.path.expanduser('~/.openclaw/google-tasks')
token_path = os.path.join(creds_dir, 'token.json')
creds_path = os.path.join(creds_dir, 'credentials.json')

creds = None
if os.path.exists(token_path):
    creds = Credentials.from_authorized_user_file(token_path, SCOPES)

if not creds or not creds.valid:
    if creds and creds.expired and creds.refresh_token:
        creds.refresh(Request())
    else:
        if not os.path.exists(creds_path):
            print(f"❌ Credentials not found at {creds_path}")
            print("Please set up Google Tasks API first")
            return None
        flow = InstalledAppFlow.from_client_secrets_file(creds_path, SCOPES)
        creds = flow.run_local_server(port=0)
    
    with open(token_path, 'w') as token:
        token.write(creds.to_json())
python
# Save to memory file
output_dir = '/Users/tom/.openclaw/workspace/memory'
os.makedirs(output_dir, exist_ok=True)
output_path = os.path.join(output_dir, 'google-tasks.json')

with open(output_path, 'w') as f:
    json.dump(all_data, f, indent=2)

Technical Analysis

The OAuth token is written with ordinary open(..., 'w'), and the containing directory is not created or validated with an explicitly restrictive mode. The synchronized task file is handled similarly. Effective permissions therefore depend on the user's umask and any pre-existing directory permissions.

The token can contain a refresh token authorized for the read-only Google Tasks scope. The synchronized JSON includes task-list identifiers and titles, task identifiers, task titles, notes, due dates, links, and relationship metadata. This content can expose personal or business p ...[truncated 1815 chars]

Remediation
View remediation

Remediation Suggestions

  1. Replace the hardcoded /Users/tom path with a user-configurable path derived from Path.home() or an explicitly configured workspace.
  2. Create credential and data directories with mode 0700.
  3. Create token and task files with mode 0600, independent of the process umask.
  4. Write through a securely created temporary file in the same directory, flush and synchronize it, then atomically replace the destination.
  5. Refuse to write through symbolic links and verify that the destination directory is owned by the expected user.
  6. Separate OAuth credentials from general workspace memory and prevent them from being included in backups or message-generation context.
  7. Document the sensitive fields stored, their retention period, and a procedure for securely deleting them and revoking Google authorization.
  8. Preserve the existing read-only OAuth scope; do not broaden it unless a separately disclosed feature requires write access.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/sync-stripe-arr.py:108
Finding

Customer Identifiers and Revenue Data Are Persisted in Plaintext Without Explicit Permission Controls

Content
View full analysis

Vulnerability Details

File Location: scripts/sync-stripe-arr.py, lines 108-134
Vulnerability Type: Excessive and insecure local storage of customer and financial metadata
Risk Level: Medium

Vulnerable Code:

python
# Save detailed data
output_dir = '/Users/tom/.openclaw/workspace/memory'
os.makedirs(output_dir, exist_ok=True)
output_path = os.path.join(output_dir, 'stripe-data.json')

data = {
    'synced_at': datetime.now().isoformat(),
    'arr': arr,
    'customer_count': customer_count,
    'customer_ids': customer_ids,
    'subscription_count': len(subscriptions),
    'method': 'active_subscriptions_only'
}

with open(output_path, 'w') as f:
    json.dump(data, f, indent=2)

# Update heartbeat state
heartbeat_path = os.path.join(output_dir, 'heartbeat-state.json')
if os.path.exists(heartbeat_path):
    with open(heartbeat_path, 'r') as f:
        hb_data = json.load(f)
else:
    hb_data = {}

hb_data['arrCurrent'] = arr
hb_data['customerCount'] = customer_count
hb_data['arrLastSynced'] = datetime.now().isoformat()

with open(heartbeat_path, 'w') as f:
    json.dump(hb_data, f, indent=2)

Technical Analysis

The script persists annual recurring revenue, customer counts, subscription counts, and a complete list of customer identifiers in plaintext. It does not explicitly restrict file or directory permissions, so effective access depends on the user's umask and pre-existing workspace permissions.

Persisting customer_ids exceeds the minimum data needed for the advertised morning brief. The brief only requires aggregate ARR and customer count after calculation. Retaining individual identifiers unnecessarily increases the sensitivity and breach impact of the local file.

The hardcoded /Users/tom output path can also cause cross-user data placement or installation failures. Ordinary file writes are non-atomic and do not reject symbolic links, all ...[truncated 1600 chars]

Remediation
View remediation

Remediation Suggestions

  1. Remove customer_ids from persisted output and retain only the minimum aggregates needed by the morning brief.
  2. Replace the hardcoded user path with an explicitly configured workspace owned by the current user.
  3. Create the data directory with mode 0700 and financial data files with mode 0600.
  4. Use secure, atomic file replacement and reject symbolic-link destinations.
  5. Validate ownership and permissions before reading or updating heartbeat-state.json.
  6. Define a short retention period for revenue snapshots and securely remove obsolete files.
  7. Prevent financial files from being included in shared repositories, broad backups, logs, or unrelated agent context.
  8. Allow users to disable customer-count and ARR persistence independently from network synchronization.
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
Findings (41)

Tainted flow: 'SKILLBOSS_API_KEY' from os.environ.get (line 14, 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/sync-stripe-arr.py (reported line 18)May include surrounding context.

python
API_BASE = "https://api.heybossai.com/v1"

def pilot(body: dict) -> dict:
    r = requests.post(
        f"{API_BASE}/pilot",
        headers={"Authorization": f"Bearer {SKILLBOSS_API_KEY}", "Content-Type": "application/json"},
        json=body,

Tainted flow: 'project_id' from os.environ.get (line 32, 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 · scripts/sync-stripe-arr.py (reported line 41)May include surrounding context.

python
return None

    try:
        r = requests.get(
            f"https://shopping.heybossai.com/admin-subscriptions?status=active&limit=100",
            headers={
                "Authorization": f"Bearer {SKILLBOSS_API_KEY}",

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The skill description understates that it accesses subscription/admin APIs, calculates ARR, processes customer/subscription information, and persists sync state locally. In context, that is more dangerous than a normal planner because the undeclared behavior reaches into potentially sensitive revenue and customer data.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The skill description understates that it accesses subscription/admin APIs, calculates ARR, processes customer/subscription information, and persists sync state locally. In context, that is more dangerous than a normal planner because the undeclared behavior reaches into potentially sensitive revenue and customer data.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The skill description understates that it accesses subscription/admin APIs, calculates ARR, processes customer/subscription information, and persists sync state locally. In context, that is more dangerous than a normal planner because the undeclared behavior reaches into potentially sensitive revenue and customer data.

Content

No source excerpt is available for this finding.

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 · README.md (reported line 38)May include surrounding context.

md
"""Get or refresh Google credentials."""
    creds_dir = os.path.expanduser('~/.openclaw/google-tasks')
    token_path = os.path.join(creds_dir, 'token.json')
    creds_path = os.path.join(creds_dir, 'credentials.json')
    
    creds = None
    if os.path.exists(token_path):

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 56)May include surrounding context.

md
"""Get or refresh Google credentials."""
    creds_dir = os.path.expanduser('~/.openclaw/google-tasks')
    token_path = os.path.join(creds_dir, 'token.json')
    creds_path = os.path.join(creds_dir, 'credentials.json')
    
    creds = None
    if os.path.exists(token_path):

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 191)May include surrounding context.

md
"""Get or refresh Google credentials."""
    creds_dir = os.path.expanduser('~/.openclaw/google-tasks')
    token_path = os.path.join(creds_dir, 'token.json')
    creds_path = os.path.join(creds_dir, 'credentials.json')
    
    creds = None
    if os.path.exists(token_path):

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 202)May include surrounding context.

md
"""Get or refresh Google credentials."""
    creds_dir = os.path.expanduser('~/.openclaw/google-tasks')
    token_path = os.path.join(creds_dir, 'token.json')
    creds_path = os.path.join(creds_dir, 'credentials.json')
    
    creds = None
    if os.path.exists(token_path):

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 · references/CONFIGURATION.md (reported line 28)May include surrounding context.

md
"""Get or refresh Google credentials."""
    creds_dir = os.path.expanduser('~/.openclaw/google-tasks')
    token_path = os.path.join(creds_dir, 'token.json')
    creds_path = os.path.join(creds_dir, 'credentials.json')
    
    creds = None
    if os.path.exists(token_path):

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 · references/CONFIGURATION.md (reported line 29)May include surrounding context.

md
"""Get or refresh Google credentials."""
    creds_dir = os.path.expanduser('~/.openclaw/google-tasks')
    token_path = os.path.join(creds_dir, 'token.json')
    creds_path = os.path.join(creds_dir, 'credentials.json')
    
    creds = None
    if os.path.exists(token_path):

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 · references/CONFIGURATION.md (reported line 182)May include surrounding context.

md
"""Get or refresh Google credentials."""
    creds_dir = os.path.expanduser('~/.openclaw/google-tasks')
    token_path = os.path.join(creds_dir, 'token.json')
    creds_path = os.path.join(creds_dir, 'credentials.json')
    
    creds = None
    if os.path.exists(token_path):

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 · scripts/sync-google-tasks.py (reported line 24)May include surrounding context.

python
"""Get or refresh Google credentials."""
    creds_dir = os.path.expanduser('~/.openclaw/google-tasks')
    token_path = os.path.join(creds_dir, 'token.json')
    creds_path = os.path.join(creds_dir, 'credentials.json')
    
    creds = None
    if os.path.exists(token_path):

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The file implements ARR synchronization, billing API access, and local persistence of business metrics, which is unrelated to a daily planning/reflection skill. In this context, hidden billing automation is especially suspicious because users invoking a routine assistant would not reasonably expect subscription administration or financial data handling.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The code accesses billing admin APIs and customer subscription records, including customer identifiers, without any functional connection to daily scheduling or reflection features. That unjustified access increases the blast radius of the skill and creates risk of unauthorized collection or misuse of sensitive business/customer data.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% 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 · README.md (reported line 31)May include surrounding context.

md
- Reflect on the week
- Celebrate wins
- Identify blockers
- Create tasks for the week ahead

## Quick Start

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding

The skill documents capabilities to read/write local files, access environment variables, and make network requests, but it does not declare any explicit tool scope or permissions boundary. In a skill system, that omission weakens reviewability and user consent, making it easier for a seemingly simple productivity skill to access broader data sources than users expect.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The manifest says triggers include broad phrases like requests for "daily schedules," "productivity systems," and "daily planning automation." These overlap with common everyday assistant requests and the file does not provide narrowing constraints, explicit invocation phrases, or negative examples to distinguish when this skill should or should not activate.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The introductory description does not warn users that the skill may read calendar/task data and store routine information in local files. For a planning skill, this omission is important because the processed data is personal and potentially sensitive, so lack of notice undermines informed consent.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% 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 54)May include surrounding context.

md
### Step 2: Configure Google Tasks

1. Go to [Google Cloud Console](https://console.cloud.google.com/)
2. Create project → Enable **Tasks API**
3. Create OAuth 2.0 credentials (Desktop app)
4. Download `credentials.json` to `~/.openclaw/google-tasks/`
5. Run once to authenticate: `python3 scripts/sync-google-tasks.py`

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The schedule directs the system to send calendar, tasks, ARR, weather, priorities, and unresolved items over third-party messaging channels such as Telegram, WhatsApp, or Signal, but provides no user warning or confirmation about transmitting personal or business data externally. This creates a meaningful confidentiality risk because highly sensitive scheduling, financial, and task metadata could be exposed through misdelivery, compromised devices, notification previews, or insecure integrations.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The template explicitly instructs saving user responses to persistent storage (memory/YYYY-MM-DD.md) without any indication that the user has been informed or has consented to retention. Because the stored content is reflective personal planning data, it may contain sensitive information about goals, routines, health, relationships, or work, creating privacy and data-retention risk if accessed later by other skills, operators, or unauthorized parties.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% 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 · references/CONFIGURATION.md (reported line 25)May include surrounding context.

md
Required for task syncing:

1. Go to [Google Cloud Console](https://console.cloud.google.com/)
2. Create a new project or select existing
3. Enable the **Tasks API**
4. Create OAuth 2.0 credentials (Desktop application)
5. Download `credentials.json`

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The instructions direct users to download OAuth credentials.json to a fixed path but do not state that the file contains sensitive client credentials and should be protected from disclosure. Users may accidentally commit, back up, or broadly permission this file, enabling misuse of the OAuth client configuration and associated app identity.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The guide tells users to place a private ICS calendar URL in a documentation file without warning that many ICS URLs act as bearer secrets. If that file is shared, synced, or committed, an attacker could use the URL to read private calendar metadata and events.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.