Back to skill

Security audit

Overnight Factory

Security checks for vulnerabilities and agentic risk

Overview

This skill is a disclosed automation workflow, but it asks an unattended AI agent to use persistent credentials, read email, and change GitHub repositories with weak guardrails.

Review this carefully before installing. Use only a dedicated sandbox, dedicated mailbox, allowlisted repositories, least-privilege short-lived GitHub credentials, and human approval before pushes, comments, or PRs. Do not use the documented plaintext credential storage or permission-skip mode for real support tickets without compensating controls.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • System PersistenceInstalls backdoors, hooks, services, or scheduled tasks that survive the run
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • 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)

T06 · System Persistence

Error
Location
SKILL.md:37
Finding
Persistent autonomous execution with permission safeguards disabled<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:37-56`; related guidance in `references/lessons-learned.md:40-42` **Vulnerability Type**: Persistent scheduled execution and excessive agent privileges **Risk Level**: Critical ### Vulnerable Code ```bash ### 2. Verify Claude Code /path/to/claude --version /path/to/claude -p --dangerously-skip-permissions --output-format text "echo hello" ``` ```bash ### 3. Create the Cron Job openclaw cron add \ --name "email-check" \ --every 15m \ --session isolated \ --announce \ --to <YOUR-TELEGRAM-CHAT-ID> \ # explicit ID, NOT --channel last --timeout-seconds 120 \ --description "Check email + GitHub for ticket assignments" \ --message "$(cat /path/to/cron-prompt.txt)" ``` Related production guidance: ```text Spawn a subagent (`runtime: "subagent"`) that runs `claude -p --dangerously-skip-permissions --output-format text "..."` via exec instead of using ACP directly. ``` ### Technical Analysis The Skill creates a scheduled job that continues to execute every 15 minutes across sessions. Scheduled execution is part of the declared overnight automation, but it materially increases security exposure because the job continually consumes externally controlled email and GitHub data. The guidance also explicitly runs Claude Code with `--dangerously-skip-permissions`. Although the first command is presented as a verification step, `references/lessons-learned.md` recommends using the same option for operational subagents. This removes interactive permission boundaries from agents that can inspect repositories, execute tools, modify files, create commits, push branches, post comments, and open pull requests. Combining persistent scheduling with disabled permission checks means that one malicious ticket, compromised mailbox, compromised GitHub account, or prompt-injection payload can repeatedly reach a privileged execution environment without a human approval checkpoint. ### Attack Path 1. A ...[truncated 1577 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove `--dangerously-skip-permissions` from both verification and production commands. 2. Run each ticket in a fresh, disposable container or virtual machine with: - A read-only base filesystem. - A dedicated writable checkout. - No access to the parent workspace or unrelated repositories. - Restricted outbound network access. - CPU, memory, process, and execution-time limits. 3. Use an explicit allowlist for executable commands, repositories, organizations, file paths, and network destinations. 4. Separate analysis from mutation: - First run a read-only analysis agent. - Present the proposed patch and actions to a human. - Require approval before running commands, changing files, pushing commits, commenting, or opening a PR. 5. Use a narrowly scoped GitHub App installation token issued per job rather than a persistent personal access token. 6. Add a documented disable and removal procedure for the cron job. 7. Prevent overlapping cron executions and enforce a strict maximum number of subagents per run. 8. Record security-relevant actions without logging credentials, mailbox contents, or other sensitive data. ]]>

T01 · Skill Instruction Hijacking

Error
Location
references/cron-prompt.md:22
Finding
Attacker-controlled ticket content is processed without prompt-injection isolation<![CDATA[ ## Vulnerability Details **File Location**: `references/cron-prompt.md:22-34`; related instructions in `references/ticket-pipeline.md:13-30` **Vulnerability Type**: Prompt injection through GitHub issues, email-derived URLs, and screenshots **Risk Level**: High ### Vulnerable Code ```text ## Step 3: For each issue in "to_process" - Fetch the full issue via GitHub API - Spawn ONE subagent (runtime=subagent, runTimeoutSeconds=1800) per ticket with instructions to: - Analyze screenshots (image tool on any URLs in issue body) - Explore the relevant repo codebase - Post a detailed analysis comment on the issue - Create branch, implement fix (trivial commit if test ticket, real fix + tests otherwise), push, open PR - After opening PR: use sessions_send targeting label "main" to message <HUMAN_NAME> the PR URL - Add issue to memory/support-tickets.json with status "dispatched" ``` The subagent template further instructs: ```text ## Step 1: Understand the ticket - Fetch the full issue from GitHub API - If there are screenshot URLs in the issue body, analyze them with the image tool - Read the relevant files in the codebase to understand the context ## Step 2: Post analysis comment Post a comment on the GitHub issue with: - What the bug/feature is (from screenshots + description) - Which files/components are affected - Your proposed approach ## Step 3: Implement - For TEST tickets (body contains "test" or no real bug described): make a trivial commit (add a comment line to a relevant file) - For real tickets: implement the fix with tests ``` ### Technical Analysis GitHub issue titles, bodies, comments, linked resources, and screenshots are untrusted inputs. The Skill places this data into the context of a tool-enabled subagent without defining a trust boundary between ticket data and operational instructions. The templates do not: - Tell the agent to treat issue and image content only as data. - Prohibit obeying instructions embedded in tick ...[truncated 2131 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Explicitly classify all issue, email, comment, image, and linked-page content as untrusted data. 2. Add a high-priority instruction that the agent must never follow commands found inside ticket content, images, repository files, comments, or linked pages. 3. Use a two-stage architecture: - A non-tool-using component extracts structured ticket facts. - A restricted agent receives only the sanitized structure and an approved repository identifier. 4. Allowlist GitHub organizations, repositories, issue URL formats, image hosts, and permitted redirect destinations. 5. Reject tickets that reference local paths, private-network addresses, unsupported URL schemes, or repositories outside the allowlist. 6. Give the analysis phase read-only repository and GitHub access. 7. Require human approval of the proposed patch before enabling write access, command execution, push, comment, or PR creation. 8. Prevent agents from reading `.env`, credential files, SSH keys, Git configuration containing secrets, and unrelated workspace memory. 9. Replace the body substring test for `"test"` with trusted metadata, such as a maintainer-controlled label. 10. Add content-size limits, URL-count limits, redirect limits, and per-ticket execution quotas. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
SKILL.md:31
Finding
GitHub token is exposed through plaintext credential storage and authenticated URLs<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:31-36`; repeated in `references/ticket-pipeline.md:49-56` **Vulnerability Type**: Plaintext credential persistence and token exposure **Risk Level**: High ### Vulnerable Code ```bash Configure git: git config --global user.name "Your Bot Name" git config --global user.email "bot@yourdomain.com" echo "https://bot-username:${GITHUB_TOKEN}@github.com" > ~/.git-credentials git config --global credential.helper store ``` The repository-management instructions also embed the token in command arguments and the persisted remote URL: ```bash cd workspace/repos git clone https://<BOT_USERNAME>:${GITHUB_TOKEN}@github.com/<ORG>/<REPO>.git cd <REPO> git config user.name "<BOT_NAME>" git config user.email "<BOT_EMAIL>" git remote set-url origin https://<BOT_USERNAME>:${GITHUB_TOKEN}@github.com/<ORG>/<REPO>.git ``` ### Technical Analysis Git's `credential.helper store` writes credentials to disk without encryption. The command explicitly creates `~/.git-credentials` containing a reusable GitHub token and does not set restrictive permissions. Embedding the token in a `git clone` command also places it in the process arguments. Depending on the operating system and execution environment, command arguments may be visible to other local processes, process-monitoring systems, shell history, job logs, or debugging output. The subsequent `git remote set-url` stores the authenticated URL in the repository's `.git/config`. Any process or subagent that can read the checkout may recover the token. Repository archives, diagnostics, or workspace backups may also unintentionally retain it. This exposure is especially dangerous because untrusted ticket content is processed by agents that are instructed to inspect repository files and run commands. ### Attack Path 1. The operator follows the setup instructions and writes the GitHub token to `~/.git-credentials`. 2. The pipeline clones a repository using a token-bearing ...[truncated 931 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Do not use `credential.helper store` for reusable tokens. 2. Do not embed tokens in command-line arguments, clone URLs, or Git remote URLs. 3. Prefer a GitHub App with: - Installation-level repository allowlisting. - Only the metadata, issues, contents, and pull-request permissions required. - Short-lived installation tokens generated per job. 4. Use a secure operating-system credential helper or an ephemeral `GIT_ASKPASS` mechanism that does not persist the token in the repository. 5. Keep remote URLs credential-free, for example: ```bash git remote set-url origin https://github.com/<ORG>/<REPO>.git ``` 6. Restrict secret files to mode `0600` and the workspace to the service account. 7. Ensure subprocess output, shell tracing, crash reports, and job logs redact authorization headers and token-like values. 8. Prevent subagents from reading credential stores, `.env`, or parent Git configuration. 9. Rotate any token previously used with the documented credential-bearing URLs. 10. Review the token's audit log and reduce its repository access and scopes before redeployment. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
references/cron-prompt.md:8
Finding
Cron job marks all unread mail as read and retains unnecessary sender data<![CDATA[ ## Vulnerability Details **File Location**: `references/cron-prompt.md:8-11`; related state schema in `references/ticket-pipeline.md:61-72` **Vulnerability Type**: Overbroad mailbox mutation and unnecessary personal-data retention **Risk Level**: Medium ### Vulnerable Code ```text ## Step 1: Check email Connect to <IMAP_HOST>:993 as <EMAIL_USER> (password: EMAIL_PASSWORD from workspace .env). Fetch all UNSEEN emails. Mark them all read immediately. For each ticket-assignment email from the bot account (subject contains "assigned"): extract the GitHub issue URL and add to a "to_process" list. ``` The state-tracking example retains the sender address: ```json [ { "ticket_id": "TD-0015", "email_from": "user@example.com", "issue_url": "https://github.com/org/repo/issues/2", "pr_url": "https://github.com/org/repo/pull/3", "status": "pr_open", "created_at": "2026-03-14T23:00:00Z" } ] ``` ### Technical Analysis The cron prompt instructs the agent to fetch every unread message and mark all of them read immediately, before validating the sender, validating the subject, extracting a valid issue, or durably recording a successful dispatch. This is broader mailbox authority than the ticket workflow requires. In a shared or imperfectly filtered inbox, unrelated messages can lose their unread state. If parsing, logging, or subagent dispatch fails after the state change, a legitimate assignment may also be silently missed. The state schema stores `email_from` in plaintext even though subsequent deduplication and processing use the issue URL, comments, and pull-request state. No retention period, access restriction, or deletion procedure is defined for this personal data. ### Attack Path 1. The cron job connects to the configured inbox with credentials that can alter message state. 2. It selects all messages with the `UNSEEN` flag, including unrelated or malformed messages. 3. It marks every selected message read before validating ...[truncated 976 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Use a dedicated mailbox or dedicated IMAP folder containing only trusted assignment notifications. 2. Search narrowly by trusted sender, validated recipient, expected headers, and an exact subject or message format. 3. Validate extracted URLs against an allowlisted GitHub organization and repository set. 4. Do not mark a message read when it is first fetched. 5. Mark or move the message only after: - Validation succeeds. - The issue is durably recorded. - Dispatch succeeds or a retryable failure state is stored. 6. Use explicit folders or labels such as `Processing`, `Processed`, and `Failed` to support retries and human review. 7. Preserve an idempotency key such as the IMAP UID or GitHub issue URL rather than relying on unread state. 8. Remove `email_from` from persistent state unless a documented operational requirement exists. 9. If sender retention is necessary, define a short retention period, restrict file permissions, and automatically delete or pseudonymize old records. 10. Avoid placing sender addresses or ticket contents in Telegram notifications and general-purpose logs unless required. ]]>
Vulnerability Patterns
  • 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
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (14)

Credential Access

High
Category
Privilege Escalation
Content
```bash
git config --global user.name "Your Bot Name"
git config --global user.email "bot@yourdomain.com"
echo "https://bot-username:${GITHUB_TOKEN}@github.com" > ~/.git-credentials
git config --global credential.helper store
```
Confidence
97% confidence
Finding
Writing `https://bot-username:${GITHUB_TOKEN}@github.com` directly to `~/.git-credentials` creates a durable plaintext credential that can be read by other local processes, leaked via backups, or unintentionally exposed by tooling. Given that this bot is meant to run unattended and modify repositories, compromise of this token could permit persistent unauthorized source code access or tampering.

External Model or Provider Selection

High
Category
Excessive Agency
Content
### 2. Verify Claude Code
```bash
/path/to/claude --version
/path/to/claude -p --dangerously-skip-permissions --output-format text "echo hello"
```
Note the exact path — you'll need it.
Confidence
93% confidence
Finding
The skill explicitly invokes an external model binary with `--dangerously-skip-permissions`, bypassing normal permission safeguards. In an autonomous ticket-processing pipeline that handles untrusted email, GitHub issues, and repository contents, disabling permission checks significantly raises the likelihood that prompted actions can access files, modify code, or exfiltrate data without meaningful operator intervention.

Missing User Warnings

High
Confidence
98% confidence
Finding
The prompt authorizes autonomous code analysis, branch creation, code changes, pushes, PR creation, human notifications, and persistent memory writes based on ticket content. In context, this is especially dangerous because tickets and screenshots are untrusted inputs that could steer the agent into making harmful repository changes, exfiltrating data in comments/PRs, or persisting attacker-influenced state.

Credential Access

High
Category
Privilege Escalation
Content
**Issue:** <GITHUB_ISSUE_URL>
**Repo:** <LOCAL_REPO_PATH> (clone if missing)
**GitHub token:** Read GITHUB_TOKEN from workspace .env
**Git identity:** <BOT_NAME> <<BOT_EMAIL>>

## Step 1: Understand the ticket
Confidence
98% confidence
Finding
This is a credential-access instruction: the subagent is told to retrieve GITHUB_TOKEN from workspace .env, which normalizes secret extraction as part of routine execution. In an autonomous coding pipeline, that is especially risky because the same agent also performs networked actions and repository writes, creating a direct path from secret access to impactful authenticated operations if the task is malicious, mistaken, or compromised.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
The skill description directs the agent to receive ticket assignments by email or GitHub and process support data end-to-end, but it does not warn that inbox contents and ticket details may be transmitted to external systems or model providers. This omission is risky because support tickets often contain personal data, credentials, logs, or screenshots that may be sensitive and subject to retention or third-party processing.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The skill configures an agent to autonomously analyze issues, modify a repository, commit, push, and open PRs, yet provides no upfront warning about the risks of autonomous code execution and repository changes. Because the skill is explicitly designed for unattended ticket handling, users may enable broad write access without understanding the potential for destructive changes, malicious issue content, or unsafe automated edits.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The skill instructs the operator to place sensitive credentials in a plaintext `.env` file and to store a GitHub token in `~/.git-credentials` using Git's credential helper store, which persists secrets unencrypted on disk. In the context of an autonomous coding agent that spawns subagents and accesses email and GitHub, this materially increases the blast radius of any local compromise, prompt injection, or accidental file exposure.

Vague Triggers

Medium
Confidence
84% confidence
Finding
The cron prompt is broadly framed to autonomously check email, poll GitHub, and spawn work without strong limiting conditions, approval gates, or narrowly scoped triggers. In an automated scheduled context, ambiguous scope increases the chance of acting on unintended inputs or repeatedly processing attacker-controlled assignments.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
These instructions direct the agent to read credentials from the workspace .env and use them for IMAP and GitHub API access, then perform external network actions automatically. That creates a real risk of unauthorized secret use, external data exposure, and unintended processing of untrusted content without any user-visible consent or warning.

Missing User Warnings

Medium
Confidence
97% confidence
Finding
Marking all unseen emails as read immediately is a destructive state change that can hide messages, interfere with normal triage, and erase evidence before validation. Because it happens before sender/content verification, a malicious or malformed email could cause loss of visibility or disrupt operational workflows.

External Transmission

Medium
Category
Data Exfiltration
Content
## Step 2: Poll GitHub for missed assignments (safety net)
Using GITHUB_TOKEN from workspace .env, call:
  GET https://api.github.com/search/issues?q=assignee:<BOT_GITHUB_USERNAME>+state:open+is:issue&per_page=50

For each result, check if already actioned (ALL must be true to skip):
- Present in memory/support-tickets.json (matched by issue_url)?
Confidence
50% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The documentation explicitly recommends invoking Claude Code with `--dangerously-skip-permissions` via exec as a workaround for ACP spawn failures. In the context of an autonomous ticket-handling agent that receives external inputs from email and GitHub, this bypass removes an important safety boundary and can allow unreviewed code or prompts to trigger filesystem, git, network, or other sensitive actions without normal permission checks. The surrounding skill context makes this more dangerous, not less, because the agent is designed to run unattended and to modify repos, create PRs, and manage automation jobs.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
The skill explicitly instructs the subagent to read a GitHub token from a workspace .env file and use it for authenticated GitHub and Git operations, but it does so without any explicit consent boundary, scope restriction, or operator warning. In this context, the agent is designed to autonomously act on external tickets and remote repositories, so silent credential use materially increases the risk of unintended repository access, unauthorized actions, and downstream token exposure in logs, prompts, or command history.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The skill directs the agent to clone repositories, modify code, push branches, open pull requests, and write local tracking state, all without an explicit safety warning or authorization gate for remote and local side effects. Because this skill is specifically for autonomous end-to-end ticket handling, those side effects are not incidental—they are core behavior—so missing guardrails make accidental or unauthorized code changes much more dangerous.

Static analysis

No suspicious patterns detected.