Back to skill

Security audit

Hinge Agent - Barney Stinson

Security checks for vulnerabilities and agentic risk

Overview

This skill needs review because it can run autonomous Hinge actions, reuse OpenAI credentials, and store or send sensitive dating data with weak controls.

Install only if you are comfortable with an agent controlling a logged-in Hinge session, potentially sending likes/skips/replies in daemon mode, using OpenAI credentials, and saving dating screenshots/messages locally. Before use, change defaults to queue/read-only behavior, supply a dedicated scoped API key, disable screenshot retention where possible, and regularly delete hinge-data.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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
Findings (5)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/session-utils.js:82
Finding
Send-enabled defaults permit account-changing Hinge actions without explicit opt-in<![CDATA[ ## Vulnerability Details **File Location**: `scripts/session-utils.js:4, 82-109`; `scripts/onboarding.js:85-91`; `scripts/discover-autopilot.js:1017-1069, 1673-1677, 1780-1918` **Vulnerability Type**: Unsafe authorization defaults and excessive autonomous privileges **Risk Level**: High The same affected implementation is duplicated under `clawhub-upload/barney/scripts/`. ### Vulnerable Code ```javascript // scripts/session-utils.js const DEFAULT_AGENT_MODE = 'full_access'; function defaultConfig() { return { // ... automation: { agentMode: DEFAULT_AGENT_MODE, observeBeforeTakeover: true, observeWarmupSeconds: 90, observeSnapshotIntervalMs: 1500, allowComposeFill: false, allowAutoSendReplies: false, allowAutoSendRoses: false, allowAutoSendLikes: true, allowAutoSkipPasses: true, defaultSource: 'discover', activeTabs: ['chats', 'likes', 'discover', 'standouts'], trustMode: 'send', sampleMatches: 8, profileScrollSteps: 3, strongYesScoreThreshold: 7, maybeScoreThreshold: 5, maybeSendScoreThreshold: 5.6, photoLikeTargetRatio: 0.7, likeCommentRatio: 0.3, beautyFloor: 6, discoverBeautySendThreshold: 6, roseScoreThreshold: 8, maxRepliesPerCycle: 2, replyCooldownMinutes: 360, maxDiscoverProfilesPerCycle: 2, maxLikesPerCycle: 2, maxStandoutsPerCycle: 1, quickScreenBudgetMs: 8000, runForeverSleepMs: 4000, tasteRefreshEveryCycles: 5 } }; } ``` ```javascript // scripts/onboarding.js if (init) { ensureDir(paths.root); if (!fs.existsSync(paths.configPath)) { writeJson(paths.configPath, defaultConfig()); console.log(`Created ${paths.configPath}`); } else { console.log(`Exists ${paths.configPath}`); } ``` ```javascript // scripts/discover-autopilot.js function shouldSendLike(evaluation, options) { if (options.trustMode !== 'send') return false; i ...[truncated 3396 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Change the defaults to `trustMode: "queue"` and set every `allowAuto*` option to `false`. 2. Introduce an explicit read-only default mode rather than defaulting to `full_access`. 3. Require an affirmative, current-session confirmation before enabling likes, skips, replies, comments, or roses. 4. Reject noninteractive autonomous launch unless a short-lived consent token or explicit command-line flag is supplied. 5. Do not infer authorization merely from persisted configuration created by onboarding. 6. Display a clear summary of enabled actions, affected tabs, duration, and per-cycle limits before launch. 7. Add a dry-run mode and require the user to review proposed actions before transitioning to send mode. 8. Record consent time, scope, and expiration separately from ordinary preferences. ]]>

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/hinge-ai.js:332
Finding
Cross-workspace discovery and use of OpenClaw API credentials<![CDATA[ ## Vulnerability Details **File Location**: `scripts/hinge-ai.js:332-372`; `scripts/hinge-agent-daemon.js:211-244`; `scripts/discover-autopilot.js:125-176` **Vulnerability Type**: Unauthorized credential discovery and propagation **Risk Level**: High The same behavior exists under `clawhub-upload/barney/scripts/`. ### Vulnerable Code ```javascript // scripts/hinge-ai.js function readOpenClawOpenAiApiKey() { const candidates = [ path.resolve(__dirname, '..', '..', '..', 'openclaw.json'), path.resolve(process.cwd(), 'openclaw.json') ]; for (const configPath of candidates) { const config = readJsonFileSafe(configPath); const key = config?.models?.providers?.openai?.apiKey; if (typeof key === 'string' && key.startsWith('sk-')) { return key.trim(); } } return ''; } function resolveOpenAiApiKey(preferences) { if (typeof process.env.OPENAI_API_KEY === 'string' && process.env.OPENAI_API_KEY.trim()) { return process.env.OPENAI_API_KEY.trim(); } const keyCandidates = [ preferences?.ai?.openaiApiKey, preferences?.ai?.openAiApiKey, preferences?.ai?.apiKey ]; for (const candidate of keyCandidates) { if (typeof candidate === 'string' && candidate.trim().startsWith('sk-')) { return candidate.trim(); } } return readOpenClawOpenAiApiKey(); } function getOpenAiApiKey(preferences) { const key = resolveOpenAiApiKey(preferences); if (key && !process.env.OPENAI_API_KEY) { process.env.OPENAI_API_KEY = key; } return key; } ``` ```javascript // scripts/hinge-agent-daemon.js function runAutopilotBatch(workspace, options, sessionId, refreshTaste) { // ... const env = options.openAiApiKey ? { OPENAI_API_KEY: options.openAiApiKey } : {}; return runNodeJson(autopilotScript, autopilotArgs, { timeoutMs: 90000, env }); } ``` ### Technical Analysis The Skill searches locations outside its own runtime data directory for `openclaw.json` and extracts `models.providers.openai.a ...[truncated 1573 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove `readOpenClawOpenAiApiKey()` and all parent-directory or current-directory credential discovery. 2. Accept only a credential explicitly supplied for this Skill, preferably through an OS credential store or narrowly scoped environment injection. 3. Do not support plaintext API keys inside `profile-preferences.json`. 4. Use a dedicated OpenAI project key with restricted budget and permissions. 5. Pass the key only to the exact process performing the API request rather than mutating the parent process environment. 6. Scrub inherited environments for unrelated secrets before launching subprocesses. 7. Fail closed with a clear setup message when no explicitly authorized key is available. 8. Document the credential source and obtain user approval before the first billable request. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/hinge-ai.js:1138
Finding
Broad transmission of sensitive dating context and screenshots to OpenAI<![CDATA[ ## Vulnerability Details **File Location**: `scripts/hinge-ai.js:1138-1237, 1260-1310, 1726-1860` **Vulnerability Type**: Excessive sensitive-data disclosure to an external service **Risk Level**: High The affected code is duplicated at `clawhub-upload/barney/scripts/hinge-ai.js`. ### Vulnerable Code ```javascript // scripts/hinge-ai.js const user = JSON.stringify( { mode, preferences: { tone: preferences.user?.tone || 'sharp-flirty', goals: preferences.user?.goals || '', personalitySummary: preferences.user?.personalitySummary || '', observationSummary: preferences.user?.observationSummary || '', dealbreakers: preferences.user?.dealbreakers || [], likesToLeadWith: preferences.user?.likesToLeadWith || [], observedInterestHints: preferences.user?.observedInterestHints || [], profileSummary: preferences.user?.profileSummary || '', profilePrompts: preferences.user?.profilePrompts || [], coreInterests: preferences.user?.coreInterests || [], idealFirstDate: preferences.user?.idealFirstDate || [], attractionPreferences: preferences.user?.attractionPreferences || [], dealmakerTraits: preferences.user?.dealmakerTraits || [], appearanceCompliments: preferences.user?.appearanceCompliments || false }, context: summarizeContext(mode, context), constraints: { maxWords: MAX_WORDS[mode] || 14, anchorTokens: anchorTokensForLikedComponent(context), oneSentenceOnly: true, oneHookOnly: true }, promptChain: { step: 'draft', next: ['rewrite', 'humanize', 'quality-gate'] }, styleGuide: WEB_RIZZ_STYLE_GUIDE, rizzExamples: pickRizzExamples(rizzLines, mode), hardStyleRules: [ 'Direct and playful, never interviewer or reporter tone.', 'Tease lightly when possible; never pander.', 'One sentence only, no paragraph energy.', 'For photo likes, short compliment-first comments are preferred.' ...[truncated 3335 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Require separate, explicit consent for remote text analysis and screenshot upload. 2. Show a preview of the exact fields and image region that will be transmitted. 3. Crop screenshots to the selected profile component and redact names, faces not needed for the task, notifications, and unrelated UI. 4. Pseudonymize match identifiers and omit chat history beyond the minimum conversational window. 5. Do not transmit broad preference fields unless they are directly required for the current request. 6. Provide a local-only drafting mode and make it the default for sensitive contexts. 7. Add destination allowlisting so context can only be sent to the documented API endpoint. 8. Document processor retention and privacy implications before enabling remote analysis. 9. Add automated tests that reject outbound payloads containing unapproved fields. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/discover-autopilot.js:552
Finding
Persistent storage of dating screenshots and behavioral records without retention or access controls<![CDATA[ ## Vulnerability Details **File Location**: `scripts/session-utils.js:40-78, 203-256`; `scripts/discover-autopilot.js:150-166, 552-574, 1666-1708, 1743-1749` **Vulnerability Type**: Unprotected plaintext retention of sensitive personal data **Risk Level**: Medium The same storage behavior exists under `clawhub-upload/barney/scripts/`. ### Vulnerable Code ```javascript // scripts/session-utils.js function ensureDir(dirPath) { fs.mkdirSync(dirPath, { recursive: true }); } function writeJson(filePath, value) { fs.writeFileSync(filePath, JSON.stringify(value, null, 2) + '\n'); } function resolvePaths(dirPath) { const root = path.resolve(dirPath || 'hinge-data'); const activityRoot = path.join(root, 'activity'); const activityDayRoot = path.join(activityRoot, todayStamp()); return { root, configPath: path.join(root, 'profile-preferences.json'), queuePath: path.join(root, 'queue.json'), threadStatePath: path.join(root, 'thread-state.json'), markdownPath: path.join(root, `hinge-queue-${todayStamp()}.md`), stagedMessagePath: path.join(root, 'staged-message.txt'), tasteModelPath: path.join(root, 'taste-model.json'), rizzCachePath: path.join(root, 'rizz-cache.json'), agentStatePath: path.join(root, 'agent-state.json'), agentLogPath: path.join(root, 'agent.log'), appiumLogPath: path.join(root, 'appium.log'), analysisJsonPath: path.join(root, 'analysis-latest.json'), analysisMarkdownPath: path.join(root, 'analysis-latest.md'), activityJsonPath: path.join(root, 'activity-log.json'), activityMarkdownPath: path.join(root, `activity-log-${todayStamp()}.md`), observationPath: path.join(root, 'user-observation.json'), activityRoot, activityDayRoot, activityImagesDir: path.join(activityDayRoot, 'images') }; } ``` ```javascript // scripts/discover-autopilot.js function persistArtifact(paths, sourcePath, prefix, label) { if (!sourcePath || !fs.existsSync(sourcePath)) return '' ...[truncated 2153 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Disable persistent screenshot storage by default. 2. Create sensitive directories with mode `0700` and files with mode `0600`. 3. Add a configurable short retention period and automatic deletion of expired images and records. 4. Provide a user-facing command to securely clear all Hinge runtime data. 5. Store only task-essential fields and pseudonymize profile identifiers. 6. Avoid writing full messages and names to Markdown logs unless explicitly requested. 7. Encrypt retained sensitive data using an OS-backed key when persistence is necessary. 8. Prevent runtime directories from being synchronized or backed up unintentionally. 9. Ensure activity-log pruning also deletes orphaned screenshot files. ]]>

T08 · Insecure Dependencies

Warning
Location
scripts/hinge-agent-daemon.js:504
Finding
Detached daemon invokes unpinned Appium through npx<![CDATA[ ## Vulnerability Details **File Location**: `scripts/hinge-agent-daemon.js:504-519` **Vulnerability Type**: Unpinned runtime dependency execution **Risk Level**: Medium The same command exists at `clawhub-upload/barney/scripts/hinge-agent-daemon.js:504-519`. ### Vulnerable Code ```javascript function startDetachedAppium(paths, options) { rotateLogIfLarge(paths.appiumLogPath); const logFd = fs.openSync(paths.appiumLogPath, 'a'); const child = spawn( '/bin/zsh', [ '-lc', `DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer npx appium --base-path ${options.appiumBasePath} -p ${options.appiumPort} --log-level warn` ], { cwd: options.workspaceDir, detached: true, stdio: ['ignore', logFd, logFd] } ); child.unref(); return child.pid; } ``` ### Technical Analysis The daemon executes `npx appium` without specifying a package version, validating the resolved executable, or demonstrating a lockfile-backed local installation. If Appium is absent locally, npx behavior may resolve or download a mutable package from the configured package registry. Even when a local executable exists, path and workspace manipulation can affect which package is selected. The command runs in a detached process with the user's permissions. Because the daemon and related processes handle an OpenAI credential and have access to Appium-controlled device sessions, unexpected package code would execute in a sensitive environment. The fixed command itself is not directly built from an attacker-controlled package name, so this is an unsafe supply-chain resolution issue rather than confirmed dependency confusion. ### Attack Path 1. The daemon determines that the configured Appium server is unavailable. 2. `startDetachedAppium()` invokes `/bin/zsh -lc`. 3. The shell runs unversioned `npx appium` in the selected workspace. 4. If no trusted local package is pinned, npx resolves Appium according to local configuration and r ...[truncated 635 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Declare Appium as an exact-version local dependency and commit a lockfile. 2. Install dependencies through a controlled setup step rather than dynamically during daemon launch. 3. Invoke the verified local binary directly, such as `node_modules/.bin/appium`, with no registry fallback. 4. Check the resolved path and expected Appium version before starting the process. 5. Use package-integrity verification and a trusted registry configuration. 6. Launch Appium with a minimal environment that excludes API keys and unrelated secrets. 7. Avoid invoking a shell when direct `spawn()` of the verified executable is sufficient. 8. Fail safely and instruct the user to install the approved dependency when verification fails. ]]>
Vulnerability Patterns
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (111)

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding
The skill emphasizes live Hinge session operation, but portions of the described functionality are really local queue/database management and staged-message persistence. While less severe than device-control issues, this still understates the amount of sensitive dating data written to disk and may cause users to underestimate persistence and exposure risk.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The skill emphasizes live Hinge session operation, but portions of the described functionality are really local queue/database management and staged-message persistence. While less severe than device-control issues, this still understates the amount of sensitive dating data written to disk and may cause users to underestimate persistence and exposure risk.

Tp4

High
Category
MCP Tool Poisoning
Confidence
92% confidence
Finding
The skill emphasizes live Hinge session operation, but portions of the described functionality are really local queue/database management and staged-message persistence. While less severe than device-control issues, this still understates the amount of sensitive dating data written to disk and may cause users to underestimate persistence and exposure risk.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The skill emphasizes live Hinge session operation, but portions of the described functionality are really local queue/database management and staged-message persistence. While less severe than device-control issues, this still understates the amount of sensitive dating data written to disk and may cause users to underestimate persistence and exposure risk.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The skill emphasizes live Hinge session operation, but portions of the described functionality are really local queue/database management and staged-message persistence. While less severe than device-control issues, this still understates the amount of sensitive dating data written to disk and may cause users to underestimate persistence and exposure risk.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The skill emphasizes live Hinge session operation, but portions of the described functionality are really local queue/database management and staged-message persistence. While less severe than device-control issues, this still understates the amount of sensitive dating data written to disk and may cause users to underestimate persistence and exposure risk.

Tp4

High
Category
MCP Tool Poisoning
Confidence
90% confidence
Finding
The skill emphasizes live Hinge session operation, but portions of the described functionality are really local queue/database management and staged-message persistence. While less severe than device-control issues, this still understates the amount of sensitive dating data written to disk and may cause users to underestimate persistence and exposure risk.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The skill emphasizes live Hinge session operation, but portions of the described functionality are really local queue/database management and staged-message persistence. While less severe than device-control issues, this still understates the amount of sensitive dating data written to disk and may cause users to underestimate persistence and exposure risk.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The skill emphasizes live Hinge session operation, but portions of the described functionality are really local queue/database management and staged-message persistence. While less severe than device-control issues, this still understates the amount of sensitive dating data written to disk and may cause users to underestimate persistence and exposure risk.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
The skill emphasizes live Hinge session operation, but portions of the described functionality are really local queue/database management and staged-message persistence. While less severe than device-control issues, this still understates the amount of sensitive dating data written to disk and may cause users to underestimate persistence and exposure risk.

Ae1

High
Category
analysis-evasion
Content
- `scripts/onboarding.js`
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
- `scripts/onboarding.js`
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
- `scripts/onboarding.js`
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
- `scripts/onboarding.js`
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
- `scripts/queue.js`
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
- `scripts/queue.js`
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
- `scripts/queue.js`
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
- `scripts/queue.js`
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
- `scripts/appium-ios.js`
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
- `scripts/appium-ios.js`
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
- `scripts/hinge-ios.js`
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
- `scripts/hinge-ios.js`
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
- `scripts/hinge-ios.js`
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
- `scripts/hinge-ai.js`
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
- `scripts/hinge-ai.js`
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Static analysis

Detected: suspicious.dangerous_exec, suspicious.env_credential_access, suspicious.exposed_secret_literal

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
clawhub-upload/barney/scripts/discover-autopilot.js:182

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
clawhub-upload/barney/scripts/hinge-agent-daemon.js:289

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
clawhub-upload/barney/scripts/hinge-ai.js:272

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
scripts/discover-autopilot.js:182

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
scripts/hinge-agent-daemon.js:289

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
scripts/hinge-ai.js:272

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
clawhub-upload/barney/scripts/appium-ios.js:19

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
clawhub-upload/barney/scripts/hinge-agent-daemon.js:187

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
clawhub-upload/barney/scripts/hinge-ai.js:84

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
clawhub-upload/barney/scripts/hinge-ios.js:20

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
scripts/appium-ios.js:19

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
scripts/hinge-agent-daemon.js:187

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
scripts/hinge-ai.js:84

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
scripts/hinge-ios.js:20

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
clawhub-upload/barney/scripts/hinge-agent-daemon.js:869

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
scripts/hinge-agent-daemon.js:869