Back to skill

Security audit

Daily Briefing

Security checks for vulnerabilities and agentic risk

Overview

This daily briefing skill is mostly clear about collecting personal briefing data, but it handles sensitive contacts, calendar, email, and credential data in unsafe local ways that need review before installation.

Review before installing. Use only the integrations you need, keep email disabled unless necessary, avoid storing mail passwords in openclaw.json, and treat /tmp/daily_briefing_data.json as sensitive because it may contain contacts, birthdays, calendar events, reminders, email senders, subjects, previews, location, and timezone. Prefer a version that writes to a private 0600 file or in-memory channel, avoids passing full config through process arguments, and minimizes contact export.

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 (4)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/daily_briefing_orchestrator.sh:10
Finding

Personal briefing data is written to predictable, insufficiently protected temporary files

Content
View full analysis
/dev/null || true exit 0 fi ``` ```bash } >"$OUT" 2>/dev/null # Atomic publish cp -f "$OUT" "${CANON}.tmp" && mv -f "${CANON}.tmp" "$CANON" ``` ### Technical Analysis The orchestrator writes the aggregated daily briefing to the system-wide `/tmp` directory without first setting a restrictive `umask`, creating a private directory, or explicitly applying permissions such as `0600`. The generated JSON may contain: - Contact names and email addresses - Birthdays - Calendar event titles and times - Reminder titles and due dates - Email senders, subjects, and previews - Location and timezone information The per-run filename includes a timestamp, process ID, and shell pseudorandom value, but it is still created directly in a shared directory and remains present after successful publication. The cleanup handler only runs when the script is explicitly invoked with `--cleanup`. The canonical staging path `/tmp/daily_briefing_data.json.tmp` is completely predictable. Because `cp -f` generally follows an existing symbolic link at the destination, another local process may pre-create that path as a symlink. If the invoking user has permission to write to the symlink target, briefing content may be written to an unintended file before the subsequent `mv`. No evidence indicates that these files are deliberately transmitted to an unrelated external service. The principal risk is local disclosure and unsafe filesystem interaction. ### Att ...[truncated 1226 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/daily_briefing_orchestrator.sh:165
Finding

Configuration-derived user names are interpolated into executable JavaScript and Python source

Content
View full analysis
/dev/null || echo "false") ``` `USER_FULL_NAME` is populated from configuration or operating-system account metadata: ```bash USER_FULL_NAME=$(get_config "user.name" "") if [[ -z "$USER_FULL_NAME" ]]; then USER_FULL_NAME=$(id -F 2>/dev/null || echo "") fi ``` ### Technical Analysis `USER_FULL_NAME` is treated as source code rather than data. It is inserted between single quotes inside dynamically generated JavaScript and Python programs without language-aware escaping. A value containing a single quote can terminate the intended string literal. Additional JavaScript or Python syntax can then be introduced before commenting out or otherwise neutralizing the remaining generated statement. Shell quoting does not make this safe. Bash expands the variable while constructing the argument, after which `osascript` or `python3` parses the resulting string as executable source. The JavaScript branch is particularly sensitive because it executes through JXA and accesses `Contacts.app`. It runs when birthday collection is enabled and the contacts source is selected. The Python branch is reached while checking whether the current day is the user's birthda ...[truncated 1347 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/daily_briefing_orchestrator.sh:31
Finding

The complete OpenClaw configuration, including email credentials, is exposed through process arguments

Content
View full analysis
/dev/null || echo '{}') else CONFIG_JSON='{}' fi # Extract config values using python3 (available on macOS) get_config() { local path="$1" local default="$2" python3 -c " import json, sys path = sys.argv[1] default = sys.argv[2] json_str = sys.argv[3] try: data = json.loads(json_str) keys = path.split('.') val = data for k in keys: if isinstance(val, dict): val = val.get(k) else: val = None if val is None: break if val is None: print(default) elif isinstance(val, bool): print('true' if val else 'false') elif isinstance(val, list): print(json.dumps(val)) else: print(val) except: print(default) " "$path" "$default" "$CONFIG_JSON" } ``` ```bash EMAILS_ICLOUD_PASSWORD=$(get_config "skills.entries.daily-briefing.config.emails.icloudPassword" "") ``` The documented configuration stores the credential directly in JSON: ```json "emails": { "enabled": false, "icloudPassword": "", "limit": 10, "sortNewest": true, "starredFirst": true, "unreadOnly": true } ``` ### Technical Analysis Each call to `get_config` supplies the entire contents of `~/.openclaw/openclaw.json` as `sys.argv[3]` to a new Python process. Command-line arguments can be exposed through process-inspection interfaces and diagnostic tooling. This exposure is broader than the email password alone. If the OpenClaw configuration contains unrelated tokens, credentials, endpoints, or personal settings, all of them are repeatedly copied into Pyt ...[truncated 1794 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
install.sh:54
Finding

Installation guidance uses unpinned third-party packages with access to sensitive user data

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
Findings (15)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The documented behavior goes far beyond a simple daily briefing: it aggregates sensitive personal data from contacts, calendars, reminders, email metadata, config files, and location, then writes the combined dataset to /tmp/daily_briefing_data.json. That mismatch materially increases privacy and data exposure risk because users may authorize a benign-sounding briefing skill without realizing it performs broad local collection and creates a potentially accessible temporary file.

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

md
- The runner script executes `scripts/daily_briefing_orchestrator.sh`.

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
95% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · scripts/daily_briefing_orchestrator.sh (reported line 17)May include surrounding context.

sh
# Cleanup handler
if [[ "${1:-}" == "--cleanup" ]]; then
  rm -f /tmp/daily_briefing_data.*.json /tmp/daily_briefing_data.json 2>/dev/null || true
  exit 0
fi

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The README highlights convenience features but does not prominently warn that the skill accesses highly sensitive personal data, including email, calendars, reminders, contacts, and potentially location. This can lead users to install and enable the skill without fully understanding the privacy implications, increasing the risk of inadvertent data exposure through chat, logs, cron output, or shared terminals.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding

The skill instructs the agent to invoke shell scripts and use curl, but it does not declare any explicit tool scope such as allowed-tools or permissions. That creates an authorization gap where a user or platform cannot clearly constrain what command execution the skill requires, increasing the risk of unintended shell access and making review and enforcement harder.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The skill collects and semantically analyzes highly sensitive personal data from calendars, reminders, contacts, and emails, and also sends user location to an external weather service, yet the description lacks a clear privacy warning. In this context, omission is dangerous because the skill is user-invocable and presents itself as a harmless daily summary, reducing informed consent and increasing the chance of overbroad data access.

Content

No source excerpt is available for this finding.

Session Persistence

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

md
**If non-interactive (cron/automation):**
- Do NOT ask questions (cron-safe). Use defaults.
- Do NOT create/modify any files.
- Do NOT spawn background tasks/sub-agents.
- **Omit weather** if location is unavailable.

### Step 2: Invoke the Data Gatherer

Session Persistence

Medium
Category
Rogue Agent
Confidence
88% confidence
Finding

The generated runner executes the orchestrator via bash -l, which starts a login shell and loads user shell startup files such as profiles/rc scripts before running the target script. That creates a persistence and trust-boundary problem: any malicious or compromised shell initialization content can alter execution, inject commands, or manipulate environment variables each time the runner is used.

Content

Scanner excerpt · install.sh (reported line 22)May include surrounding context.

sh
# Make orchestrator executable
chmod +x "$ORCHESTRATOR"

# Create runner script that simply invokes the orchestrator
cat > "$RUNNER_SCRIPT" << 'RUNNER_EOF'
#!/bin/bash
# run_daily_briefing.sh - Runs the daily briefing data gatherer

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The script collects birthday information from Contacts and Google Contacts without any visible disclosure or confirmation step. Birthdays are personal data, and aggregating them into a general-purpose output file increases the risk of unintended disclosure to other components or users on the system.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The script retrieves email metadata and snippets from Gmail and iCloud and writes them into a shared temporary JSON file without any explicit disclosure or runtime consent flow. Even if this is feature-related, email subjects, senders, and previews are sensitive data whose collection broadens the privacy risk of the skill.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The script exports the user's full contacts dataset when email support is enabled, even though the stated purpose is only to help classify important emails in a daily briefing. That is excessive collection of personal data and increases privacy exposure if the JSON file is read by other local processes, logs, or downstream agents.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The script reads and exports contacts data from Contacts.app and Google Contacts with no user-facing notice in the code path. Contacts are highly sensitive personal data, and exporting them into the aggregated JSON creates unnecessary secondary exposure beyond the immediate tool access.

Content

No source excerpt is available for this finding.

Vague Triggers

Low
Category
Not specified by scanner
Confidence
91% confidence
Finding

The suggested invocation phrase is generic enough to plausibly match ordinary user conversation, which can cause unintended skill activation. In a skill that aggregates calendars, reminders, contacts, and email summaries, accidental triggering increases the chance of exposing sensitive personal data in the wrong context or channel.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
98% confidence
Finding

The skill says the closing line is required and must use quote from the gathered JSON, and further states the orchestrator provides a random motivational quote each run. However, the only JSON schema shown for /tmp/daily_briefing_data.json contains no quote field, creating a direct contradiction between the documented data contract and the generation instructions.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
89% confidence
Finding

This shell script removes an existing runner script with rm -rf and then recreates it via shell redirection, which are file-destructive/write operations. While the script prints general progress messages, it does not explicitly warn the user that an existing file will be deleted and replaced.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.