Back to skill

Security audit

dxh141130

Security checks for vulnerabilities and agentic risk

Overview

This skill matches its punch-clock purpose, but it handles payroll-related actions and stored credentials in ways that need review before installation.

Review this skill carefully before installing. It stores WPS Time credentials in macOS Keychain, can clock in/out or start/end breaks and lunch, takes screenshots of the timeclock page, and currently submits credentials through an HTTP URL. Prefer not to use the chat-based credential setup, require explicit confirmation before any punch action, and only install after the login flow is changed to HTTPS with origin validation.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/punchclock.mjs:9
Finding

Credentials May Be Disclosed Through a Plaintext HTTP Login Flow

Content
View full analysis
null), page.locator('input[name="inpLogin"]').click() ]); ``` The same insecure endpoint is also documented in `references/PUNCHCLOCK_RUNBOOK.md:21-22`: ```markdown ## Site - Login URL: http://www.wpstime.com/NetTime/Login.asp ``` ### Technical Analysis The automation begins at an unencrypted HTTP URL and subsequently fills the page with the company identifier, username, and password retrieved from macOS Keychain. The script does not require HTTPS and does not verify the final URL, protocol, hostname, or certificate-backed origin before entering credentials. Even if the legitimate server normally redirects HTTP requests to HTTPS, the initial HTTP request is not authenticated. An attacker capable of intercepting or modifying network traffic can suppress the redirect and return a counterfeit page containing the expected input selectors. Playwright would then fill Keychain credentials into that attacker-controlled page. This is an insecure transport and origin-validation flaw involving sensitive authentication data. ### Attack Path 1. A victim invokes the punch-clock status or time-punch workflow. 2. The script retrieves the victim's company ID, username, and password from macOS Keychain. 3. Pl ...[truncated 1141 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
SKILL.md:48
Finding

Chat-Based Credential Setup Permits Shell Command Injection

Content
View full analysis
" security add-generic-password -U -s "wpstime-punchclock" -a "" -w "" ``` ``` ### Technical Analysis The documented workflow directs the agent to place user-controlled values directly into shell command text. Wrapping those values in double quotes is not sufficient shell escaping. Shell constructs such as command substitution using `$(...)` or backticks remain active inside double quotes, while embedded quote characters can terminate the intended argument and introduce additional shell syntax. The interactive `scripts/setup.mjs` implementation avoids this weakness by invoking `security` with `execFile` and an argument array. The chat workflow bypasses that safe implementation and instead presents shell command templates that encourage unsafe textual interpolation. The workflow also places the plaintext password in the shell command's argument list. Depending on the operating system and execution environment, command-line arguments may be visible to process-monitoring tools or captured in command execution logs. ### Attack Path 1. A user requests the chat-bas ...[truncated 1308 chars]
Remediation
View remediation
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 (26)

Missing User Warnings

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The login URL uses plain HTTP, so company ID, username, and password may be exposed to interception or modification by a network attacker during transit. Because the script then automates authenticated actions, a man-in-the-middle could steal credentials or tamper with punch operations.

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 · scripts/punchclock.mjs (reported line 12)May include surrounding context.

js
const LOGIN_URL = 'http://www.wpstime.com/NetTime/Login.asp';

// Preferred keychain service names for this distributable skill.
// Keep backward-compat fallback to the older OpenClaw-specific names.
const KC = {
  company: ['wpstime-punchclock.company', 'openclaw.wpstime.company'],

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/setup.mjs (reported line 59)May include surrounding context.

js
const LOGIN_URL = 'http://www.wpstime.com/NetTime/Login.asp';

// Preferred keychain service names for this distributable skill.
// Keep backward-compat fallback to the older OpenClaw-specific names.
const KC = {
  company: ['wpstime-punchclock.company', 'openclaw.wpstime.company'],

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/setup.mjs (reported line 70)May include surrounding context.

js
const LOGIN_URL = 'http://www.wpstime.com/NetTime/Login.asp';

// Preferred keychain service names for this distributable skill.
// Keep backward-compat fallback to the older OpenClaw-specific names.
const KC = {
  company: ['wpstime-punchclock.company', 'openclaw.wpstime.company'],

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/setup.mjs (reported line 95)May include surrounding context.

js
const LOGIN_URL = 'http://www.wpstime.com/NetTime/Login.asp';

// Preferred keychain service names for this distributable skill.
// Keep backward-compat fallback to the older OpenClaw-specific names.
const KC = {
  company: ['wpstime-punchclock.company', 'openclaw.wpstime.company'],

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/setup.mjs (reported line 96)May include surrounding context.

js
const LOGIN_URL = 'http://www.wpstime.com/NetTime/Login.asp';

// Preferred keychain service names for this distributable skill.
// Keep backward-compat fallback to the older OpenClaw-specific names.
const KC = {
  company: ['wpstime-punchclock.company', 'openclaw.wpstime.company'],

Credential Access

High
Category
Privilege Escalation
Confidence
96% confidence
Finding

This function invokes the macOS security CLI to read generic-password secrets from the user's keychain. While credential retrieval is expected for login automation, it is still sensitive behavior because compromise or misuse of the skill grants access to stored credentials without additional runtime user review.

Content

Scanner excerpt · scripts/punchclock.mjs (reported line 25)May include surrounding context.

js
return def;
}

async function keychainGet(service) {
  try {
    const { stdout } = await execFileAsync('security', ['find-generic-password', '-s', service, '-w'], { maxBuffer: 1024 * 1024 });
    return stdout.trim();

Credential Access

High
Category
Privilege Escalation
Confidence
93% confidence
Finding

This function reads keychain metadata to extract the stored account name associated with the credential. Although it does not retrieve the password directly, it is part of reconstructing a usable credential set and therefore contributes to sensitive credential access.

Content

Scanner excerpt · scripts/punchclock.mjs (reported line 34)May include surrounding context.

js
}
}

async function keychainGetAccount(service) {
  try {
    const { stdout } = await execFileAsync('security', ['find-generic-password', '-s', service], { maxBuffer: 1024 * 1024 });
    const line = stdout.split('\n').find(l => l.includes('"acct"<blob>='));

Credential Access

High
Category
Privilege Escalation
Confidence
97% confidence
Finding

This line retrieves the company identifier from keychain-backed service names as part of assembling login credentials. In context, that secret access becomes more dangerous because the credentials are later submitted to a remote site over HTTP.

Content

Scanner excerpt · scripts/punchclock.mjs (reported line 71)May include surrounding context.

js
return '';
  };

  const companyId = await firstNonEmpty(KC.company, keychainGet);
  const username = await firstNonEmpty(KC.account, keychainGetAccount);
  const password = await firstNonEmpty(KC.account, keychainGet);

Credential Access

High
Category
Privilege Escalation
Confidence
97% confidence
Finding

This line retrieves the username from the keychain entry, contributing to a complete credential set for automated login. While not malicious by itself, it is sensitive because it enables unattended authentication when combined with the password and company ID.

Content

Scanner excerpt · scripts/punchclock.mjs (reported line 72)May include surrounding context.

js
};

  const companyId = await firstNonEmpty(KC.company, keychainGet);
  const username = await firstNonEmpty(KC.account, keychainGetAccount);
  const password = await firstNonEmpty(KC.account, keychainGet);

  if (!companyId || !username || !password) {

Credential Access

High
Category
Privilege Escalation
Confidence
98% confidence
Finding

This line retrieves the password from the macOS keychain, which is highly sensitive secret material. In this skill's context, the risk is elevated because the password is then used for automated login to a plain-HTTP endpoint, increasing exposure to interception.

Content

Scanner excerpt · scripts/punchclock.mjs (reported line 73)May include surrounding context.

js
const companyId = await firstNonEmpty(KC.company, keychainGet);
  const username = await firstNonEmpty(KC.account, keychainGetAccount);
  const password = await firstNonEmpty(KC.account, keychainGet);

  if (!companyId || !username || !password) {
    throw new Error(

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

md
#!/usr/bin/env node
/**
 * Interactive first-time setup.
 * Stores WPS Time / NetTime credentials into macOS Keychain.
 *
 * Services used by this skill (preferred):
 * - wpstime-punchclock.company  (secret = company/common id)

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/punchclock.mjs (reported line 57)May include surrounding context.

js
#!/usr/bin/env node
/**
 * Interactive first-time setup.
 * Stores WPS Time / NetTime credentials into macOS Keychain.
 *
 * Services used by this skill (preferred):
 * - wpstime-punchclock.company  (secret = company/common id)

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/punchclock.mjs (reported line 77)May include surrounding context.

js
#!/usr/bin/env node
/**
 * Interactive first-time setup.
 * Stores WPS Time / NetTime credentials into macOS Keychain.
 *
 * Services used by this skill (preferred):
 * - wpstime-punchclock.company  (secret = company/common id)

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/punchclock.mjs (reported line 79)May include surrounding context.

js
#!/usr/bin/env node
/**
 * Interactive first-time setup.
 * Stores WPS Time / NetTime credentials into macOS Keychain.
 *
 * Services used by this skill (preferred):
 * - wpstime-punchclock.company  (secret = company/common id)

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/setup.mjs (reported line 4)May include surrounding context.

js
#!/usr/bin/env node
/**
 * Interactive first-time setup.
 * Stores WPS Time / NetTime credentials into macOS Keychain.
 *
 * Services used by this skill (preferred):
 * - wpstime-punchclock.company  (secret = company/common id)

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/setup.mjs (reported line 81)May include surrounding context.

js
#!/usr/bin/env node
/**
 * Interactive first-time setup.
 * Stores WPS Time / NetTime credentials into macOS Keychain.
 *
 * Services used by this skill (preferred):
 * - wpstime-punchclock.company  (secret = company/common id)

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/setup.mjs (reported line 82)May include surrounding context.

js
#!/usr/bin/env node
/**
 * Interactive first-time setup.
 * Stores WPS Time / NetTime credentials into macOS Keychain.
 *
 * Services used by this skill (preferred):
 * - wpstime-punchclock.company  (secret = company/common id)

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/setup.mjs (reported line 99)May include surrounding context.

js
#!/usr/bin/env node
/**
 * Interactive first-time setup.
 * Stores WPS Time / NetTime credentials into macOS Keychain.
 *
 * Services used by this skill (preferred):
 * - wpstime-punchclock.company  (secret = company/common id)

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The manifest description contains very broad trigger phrases such as 'status', 'check status', and common setup variants that can easily overlap with ordinary user conversation. This can cause the skill to activate unintentionally and perform real-world side effects like punching in/out or checking attendance status without sufficiently explicit user intent.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The runbook authorizes account-changing actions like clock in/out and break/lunch punches but does not warn that these can alter payroll and attendance records, some of which may be difficult to correct afterward. Without a clear warning or confirmation boundary, users may trigger actions casually and cause timekeeping errors with financial or disciplinary consequences.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The runbook explicitly directs the agent to use stored macOS Keychain credentials and log in without prompting the user, which enables silent access to an authenticated payroll/timekeeping account. This removes an important consent checkpoint and makes accidental or unauthorized account access more likely, especially if the skill is triggered incorrectly or abused by another prompt.

Content

No source excerpt is available for this finding.

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
97% confidence
Finding

The instruction to log in with stored credentials and "do not prompt user" enables autonomous execution of authenticated, state-changing actions without a contemporaneous approval step. In the context of a payroll/timeclock system, this is especially risky because a mistaken invocation can directly alter employment records and create payroll discrepancies.

Content

Scanner excerpt · references/PUNCHCLOCK_RUNBOOK.md (reported line 16)May include surrounding context.

md
Steward should:
1) Open an OpenClaw-managed **isolated browser** (profile `openclaw`).
2) Navigate to WPS Time / NetTime.
3) Login using **macOS Keychain** credentials (do not prompt user).
4) Perform the requested action (select the Action dropdown + click Punch).
5) Read resulting status/time from page.
6) Take screenshot.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The trigger phrase "status / check status" is broad enough to overlap with ordinary conversational requests, increasing the chance the agent invokes this skill when the user did not intend a payroll-related action. In this skill, even adjacent intents can lead to accessing employment records or preparing account actions, so ambiguous routing materially raises the risk of unintended use.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The script accesses macOS Keychain secrets via the security CLI, but this sensitive capability is not reflected in the skill description. That creates a transparency and consent problem: users may invoke a simple 'clock in/out' skill without realizing it will retrieve stored credentials from the local keychain.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.