Back to skill

Security audit

Outreach Demo

Security checks for vulnerabilities and agentic risk

Overview

This skill is mostly a disclosed outreach workflow, but its email-sending helper can send real Gmail messages without enforcing the documented approval gate.

Review before installing. Use the drafting and rendering helpers only in a controlled workspace, and do not use the bundled Gmail send script unless it is changed to default to dry-run, require an explicit approved manifest, validate recipient/content hashes, and require a configured sender account. Treat generated bodies and attachments as data that can be sent outside your organization.

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

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/send_outreach_package.sh:10
Finding
Hardcoded Gmail Sender Account Can Cause Unintended Account Use and Identity Disclosure<![CDATA[ ## Vulnerability Details **File Location**: `scripts/send_outreach_package.sh:10` **Mirrored Location**: `outreach-demo/scripts/send_outreach_package.sh:10` **Related Reference Locations**: `references/value-first-outreach.md:51-53`, `outreach-demo/references/value-first-outreach.md:51-53` **Vulnerability Type**: Hardcoded sender identity and insecure configuration **Risk Level**: Medium ### Vulnerable Code ```bash ACCOUNT="alex.data.assistant@gmail.com" ``` The related reference template also embeds the same personal identity: ```text Best, Alex alex.data.assistant@gmail.com ``` ### Technical Analysis The sending script initializes `ACCOUNT` with a specific Gmail address. Unless the operator supplies `--account`, this value is exported through `GOG_ACCOUNT` when `gog gmail send` is invoked. This conflicts with the documented requirement to use the configured sender identity and with the separate configurable values supported by `load_sender_config.py`. Although the address is not itself an authentication secret, hardcoding it creates an unsafe account-selection default and exposes a personal identity in a distributable package. If the local `gog` installation has authorization for that account, messages can be attributed to or routed through an account the operator did not intend to use. The reference template can separately leak the same identity into manually generated content. ### Attack Path 1. An operator configures an outreach sender through the documented environment or JSON configuration. 2. The operator invokes `send_outreach_package.sh` without the optional `--account` argument, following the documented example. 3. The script ignores the sender configuration used by the rendering scripts and retains `alex.data.assistant@gmail.com`. 4. The final command is executed with `GOG_ACCOUNT` set to the hardcoded account. 5. If that account is authorized in `gog`, the email is sent using the unintended account. If it is not authorized, ...[truncated 779 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove the hardcoded Gmail address and fail closed when no sender account is configured: ```bash ACCOUNT="${OUTREACH_SENDER_EMAIL:-}" if [[ -z "$ACCOUNT" ]]; then echo "A sender account must be provided with --account or OUTREACH_SENDER_EMAIL" >&2 exit 2 fi ``` 2. Prefer a single configuration source shared by rendering and sending components. The shell script should read the same validated sender account used by `load_sender_config.py`. 3. Require an explicit `--account` value if reliable configuration sharing cannot be implemented. 4. Replace the personal signature in `value-first-outreach.md` with placeholders such as: ```text Best, {{sender_name}} {{sender_email}} ``` 5. Validate the chosen account against the approved preview manifest before sending. 6. Add automated tests that verify no personal email address is present in distributable scripts or references. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/send_outreach_package.sh:29
Finding
Documented Approval Gate Is Not Enforced by the Email Sending Script<![CDATA[ ## Vulnerability Details **File Location**: `scripts/send_outreach_package.sh:29-46` **Mirrored Location**: `outreach-demo/scripts/send_outreach_package.sh:29-46` **Related Configuration**: `scripts/config.example.json:7`, `outreach-demo/scripts/config.example.json:7` **Vulnerability Type**: Missing authorization and confirmation enforcement **Risk Level**: High ### Vulnerable Code ```bash [[ -n "$TO" && -n "$SUBJECT" && -n "$TEXT" && -n "$HTML" && -n "$ATTACH" ]] || { usage; exit 2; } [[ -f "$TEXT" && -f "$HTML" && -f "$ATTACH" ]] || { echo "missing input artifact" >&2; exit 2; } HTML_BODY=$(cat "$HTML") CMD=(gog gmail send --to "$TO" --subject "$SUBJECT" --body-file "$TEXT" --body-html "$HTML_BODY" --attach "$ATTACH") if [[ "$DRY_RUN" -eq 1 ]]; then CMD+=(--dry-run) fi GOG_ACCOUNT="$ACCOUNT" "${CMD[@]}" ``` The example configuration declares an approval policy: ```json "approvalRequiredForSend": true ``` However, the sender does not load or enforce this setting. ### Technical Analysis The skill documentation states that email must not be sent without explicit user approval for the specific recipient and message. The executable sender does not implement that control. It only verifies that required arguments are nonempty and that artifact files exist. `--dry-run` is optional and disabled by default. Consequently, any direct invocation with syntactically valid arguments reaches `gog gmail send`. The script does not require an approval flag, consume the generated preview manifest, verify an approval token, compare artifact hashes, or confirm that the approved recipient and subject match the outgoing package. This is a missing authorization control at the side-effect boundary. A policy expressed only in documentation is insufficient because caller error, prompt manipulation, or another local process can invoke the sender directly. ### Attack Path 1. An attacker, manipulated agent workflow, or mistaken operator creates or se ...[truncated 1493 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Make dry-run behavior the default. Sending should require an explicit, auditable approval option. 2. Require an approval manifest generated during preview. The manifest should contain: - Recipient. - Sender account. - Subject. - SHA-256 hashes of the text body, HTML body, and attachment. - Approval timestamp and unique identifier. 3. Require an explicit argument such as `--approved-manifest <path>` and validate every outgoing field and artifact hash against that manifest. 4. Reject sending if `approvalRequiredForSend` is enabled and no valid approval evidence is supplied. 5. Bind approval to the precise recipient and content. Any modification after approval must invalidate it and require a new preview. 6. Avoid treating a bare `--approved` Boolean as sufficient where stronger manifest validation is practical. 7. Log the approved manifest identifier, recipient, sender, and artifact hashes without logging message contents or credentials. 8. Validate recipient formatting and optionally enforce an approved recipient/domain allowlist. 9. Add integration tests proving that: - An invocation without approval cannot send. - A dry run cannot become a real send implicitly. - Modified artifacts are rejected after approval. - Recipient or subject changes invalidate approval. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/render_outreach_report_pdf.sh:31
Finding
Chromium Sandbox Is Disabled While Rendering Caller-Supplied HTML<![CDATA[ ## Vulnerability Details **File Location**: `scripts/render_outreach_report_pdf.sh:31-37` **Mirrored Location**: `outreach-demo/scripts/render_outreach_report_pdf.sh:31-37` **Vulnerability Type**: Unsafe browser isolation configuration **Risk Level**: Medium ### Vulnerable Code ```bash INPUT_URL="file://$INPUT" "$CHROME_BIN" \ --headless=new \ --disable-gpu \ --no-sandbox \ --print-to-pdf="$OUTPUT" \ "$INPUT_URL" >/dev/null 2>&1 ``` ### Technical Analysis The script launches Chromium with `--no-sandbox`, disabling a primary process-isolation boundary used to contain malicious web content and browser-renderer vulnerabilities. The script accepts any existing file supplied through `--input`; it does not prove that the HTML was generated by the project’s escaping renderer. The audited HTML renderer uses `html.escape` for structured values, which reduces the risk in the intended workflow. That protection does not apply when the PDF script is invoked directly with arbitrary HTML. An attacker who can influence the input file can submit active or malformed content to the browser. Successful exploitation would still generally require a Chromium vulnerability or unsafe browser behavior, but disabling the sandbox increases the consequence of such an exploit. The `file://` origin also means the browser is processing a local path. The current generated report contains no observed remote scripts or injected markup, so this finding concerns unsafe isolation rather than a confirmed embedded payload. ### Attack Path 1. An attacker persuades an operator or agent to use an attacker-controlled HTML file as `--input`, or replaces the expected generated artifact before conversion. 2. The script confirms only that the file exists. 3. Chromium opens the file using a `file://` URL with `--no-sandbox`. 4. The malicious page exercises browser functionality or targets a vulnerability in the installed Chromium version. 5. If exploitation succeeds, the rendere ...[truncated 1073 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove `--no-sandbox` and run Chromium with its normal sandbox enabled: ```bash "$CHROME_BIN" \ --headless=new \ --disable-gpu \ --print-to-pdf="$OUTPUT" \ "$INPUT_URL" ``` 2. Run the renderer as a dedicated, unprivileged operating-system user. 3. If the normal Chromium sandbox cannot be enabled, perform conversion inside a disposable container or equivalent isolated environment with: - No host home-directory mount. - A read-only root filesystem. - Only the input file mounted read-only. - Only the output directory mounted writable. - Network access disabled. - Dropped Linux capabilities. - CPU, memory, process, and execution-time limits. 4. Restrict conversion to artifacts produced by the trusted HTML renderer. Consider recording and validating an artifact manifest or hash. 5. Canonicalize input and output paths and enforce expected directories. 6. Keep Chromium patched and use a controlled executable path rather than an arbitrary `CHROME_BIN` in privileged automation. 7. Do not suppress all Chromium diagnostics in security-sensitive environments; retain sanitized failure logs for investigation. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (18)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
This finding combines the most security-relevant issues: direct outbound Gmail sending, use of credentialed sender context, and weakly evidenced approval gating. In a prospecting skill, that is especially risky because it can enable unauthorized external communication, data leakage, or reputational harm while appearing to be a simple drafting workflow.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
This finding combines the most security-relevant issues: direct outbound Gmail sending, use of credentialed sender context, and weakly evidenced approval gating. In a prospecting skill, that is especially risky because it can enable unauthorized external communication, data leakage, or reputational harm while appearing to be a simple drafting workflow.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
This finding combines the most security-relevant issues: direct outbound Gmail sending, use of credentialed sender context, and weakly evidenced approval gating. In a prospecting skill, that is especially risky because it can enable unauthorized external communication, data leakage, or reputational harm while appearing to be a simple drafting workflow.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
This finding combines the most security-relevant issues: direct outbound Gmail sending, use of credentialed sender context, and weakly evidenced approval gating. In a prospecting skill, that is especially risky because it can enable unauthorized external communication, data leakage, or reputational harm while appearing to be a simple drafting workflow.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
This finding combines the most security-relevant issues: direct outbound Gmail sending, use of credentialed sender context, and weakly evidenced approval gating. In a prospecting skill, that is especially risky because it can enable unauthorized external communication, data leakage, or reputational harm while appearing to be a simple drafting workflow.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
This finding combines the most security-relevant issues: direct outbound Gmail sending, use of credentialed sender context, and weakly evidenced approval gating. In a prospecting skill, that is especially risky because it can enable unauthorized external communication, data leakage, or reputational harm while appearing to be a simple drafting workflow.

Description-Behavior Mismatch

High
Confidence
98% confidence
Finding
The script performs a live `gog gmail send` using provided recipient, body, HTML, and attachment, which contradicts the skill description that says outreach should result in an approval-gated email draft. In an agent setting, this can cause unauthorized outbound communication and data disclosure to external recipients before a human reviews the content.

Context-Inappropriate Capability

High
Confidence
95% confidence
Finding
The script is wired to a concrete Gmail account by default and can send real messages from that account without any built-in policy controls. For a demo/research-and-draft skill, this materially increases the chance of misuse, accidental outreach, account abuse, and data exfiltration to unintended external parties.

Description-Behavior Mismatch

High
Confidence
97% confidence
Finding
The script performs live outbound email sending via `gog gmail send`, which exceeds the stated skill behavior of producing an approval-gated draft. In this context, that creates a real risk of unauthorized or premature contact with external recipients, spam/abuse, privacy leakage of generated content and attachments, and reputational harm to the operator.

Lp3

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding
The skill describes reading and writing local files and potentially using environment-backed configuration, but it declares no explicit tool scope or permissions boundary. That creates avoidable ambiguity about what the skill may access and increases the chance of over-broad execution in environments that grant default file or env capabilities.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The subprocess sends the contents of local text/HTML files and an attachment to an external email address without any user-facing warning or confirmation. In a workflow that assembles artifacts from research or prior agent steps, this creates a straightforward path for accidental exfiltration of sensitive local content or generated materials to unintended recipients.

Missing User Warnings

Low
Confidence
84% confidence
Finding
This code performs a file write to the path supplied by --output, but the file contains no confirmation prompt, user-facing log/print, or explanatory comment/docstring warning that it will overwrite or create a file. For code-file SQP-2, file writes are safety-relevant when there is no visible disclosure in the code being reviewed.

Missing User Warnings

Low
Confidence
80% confidence
Finding
This code writes rendered content to the path supplied by --output, but the file contains no confirmation prompt, logging/print statement, or comment/docstring disclosing that it will create or overwrite a file. For a code file, file-write operations are in scope when they lack any form of user disclosure.

Missing User Warnings

Low
Confidence
85% confidence
Finding
This Python code writes a JSON preview manifest to the path supplied by --output, and that manifest includes contact_email and contact_name derived from input data. The file contains no confirmation prompt, logging, or inline warning/comment disclosing that user/contact data will be written to disk.

Missing User Warnings

Low
Confidence
84% confidence
Finding
This code performs a file write via Path(args.output).write_text(), which can overwrite an existing file. The script has no confirmation prompt, warning print/log, or inline comment/docstring disclosing this behavior to the user.

Natural-Language Policy Violations

Low
Confidence
89% confidence
Finding
The natural-language values "OpenClaw assistant" and "Built by Your Company · OpenClaw assistant" establish user-facing text in a single language. Because this config does not indicate any user opt-in, localization support, or region-specific justification, it may violate the language/locale policy for skills.

Missing User Warnings

Low
Confidence
78% confidence
Finding
This code performs a file write to the path supplied by --output, but there is no confirmation prompt, log/print statement, or comment/docstring disclosing that the script will overwrite or create a file. For a code file, file writes are in scope for missing user warnings when there is no visible disclosure.

Missing User Warnings

Low
Confidence
78% confidence
Finding
This code performs a file write to the user-specified output path, but there is no confirmation prompt, visible logging/print statement, or nearby comment/docstring warning that the script will create or overwrite a file. For a code file, file writes are in scope for missing-warning review when no disclosure is present.

Static analysis

No suspicious patterns detected.