Back to skill

Security audit

Auto Pr Merger

Security checks for vulnerabilities and agentic risk

Overview

This PR automation skill performs powerful repository actions and sends code to Gemini, but its controls and disclosure are not strong enough for safe default use.

Only use this in an isolated disposable checkout with least-privilege GitHub credentials, on trusted repositories and PRs, and with full awareness that source code and logs may be sent to Google Gemini. It should not be installed for sensitive private repositories unless command execution is hardened, external AI use is opt-in and redacted, tests run in a sandbox, and commits/merges require human review.

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

T09 · Insecure Skill Coding Practices

Error
Location
index.js:125
Finding

Shell Command Injection Through Unvalidated PR and Branch Values

Content
View full analysis
${command}`); try { const output = execSync(command, { encoding: 'utf8', stdio: 'pipe' }); return { success: true, output }; } catch (error) { ``` ### Technical Analysis The `--pr` value is parsed directly from command-line input and embedded in shell command strings without validation or shell-safe argument separation. The target branch is similarly embedded into `git fetch` and `git merge` commands. Because `execSync()` receives a string, Node.js invokes shell parsing, and shell metacharacters contained in these values can introduce additional commands. The PR value is directly attacker- or caller-controlled. The branch value is obtained from GitHub PR metadata, which must also be considered untrusted. Quoting only selected file paths elsewhere does not protect these command constructions. ### Attack Path 1. An attacker convinces a privileged user or automation process ...[truncated 914 chars]
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Error
Location
index.js:228
Finding

Execution of Untrusted Pull Request Code in a Privileged Environment

Content
View full analysis
Remediation
View remediation

other

Error
Location
index.js:70
Finding

Undisclosed Transmission of Repository Source and Test Output to an External AI Service

Content
View full analysis
>>>>>>). Please resolve the conflicts intelligently. Preserve the logic that makes the most sense. Ensure the code is syntactically correct and functional. Return ONLY the resolved code for the entire file. File content: ${content}`; ``` Test output and an entire failing source file are also included: ```javascript const prompt = `You are an expert developer. The tests failed with this error:\n${outputTail}\n\nHere is the content of ${failingFile}:\n${fileContent}\n\nReturn the fixed code for the entire file. Do not wrap in markdown code blocks, just raw code.`; console.log("Calling LLM for fix..."); const fixedCode = await callLLM(prompt); ``` ### Technical Analysis The skill sends full source files and test diagnostics to the Google Gemini API. Source files may contain proprietary algorithms, internal endpoints, personal data, or embedded credentials. Test logs can contain tokens, connection strings, filesystem paths, request data, or other sensitive diagnostic material. No secret redaction, content classification, file allowlist, size restriction, or user confirmation is performed. `SKILL.md` describes the repair behavior as placeholder or ...[truncated 1326 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
index.js:278
Finding

Unvalidated AI-Generated Code Is Written, Broadly Staged, Committed, and Pushed

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
index.js:204
Finding

Failed Auto-Merge Falls Back to an Immediate Merge

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • 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
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (12)

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · index.js (reported line 39)May include surrounding context.

js
let apiKey = process.env.GEMINI_API_KEY;

    if (!apiKey) {
        // Try to load from .env in workspace root
        const possiblePaths = [
            path.resolve(process.cwd(), '.env'),
            path.resolve(process.cwd(), '..', '.env'),

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · index.js (reported line 68)May include surrounding context.

js
let apiKey = process.env.GEMINI_API_KEY;

    if (!apiKey) {
        // Try to load from .env in workspace root
        const possiblePaths = [
            path.resolve(process.cwd(), '.env'),
            path.resolve(process.cwd(), '..', '.env'),

Credential Access

High
Category
Privilege Escalation
Confidence
91% confidence
Finding

Including process.cwd()/.env in a filesystem search causes the script to harvest credentials from local project files rather than relying on explicitly provisioned runtime secrets. In this script, that behavior directly supports outbound LLM requests, increasing the chance of unreviewed secret use and data exfiltration.

Content

Scanner excerpt · index.js (reported line 41)May include surrounding context.

js
if (!apiKey) {
        // Try to load from .env in workspace root
        const possiblePaths = [
            path.resolve(process.cwd(), '.env'),
            path.resolve(process.cwd(), '..', '.env'),
            path.resolve(__dirname, '../../..', '.env')
        ];

Credential Access

High
Category
Privilege Escalation
Confidence
96% confidence
Finding

Searching the parent directory for a .env file expands credential access beyond the active repository and may capture unrelated secrets from a broader workspace. That unnecessary privilege expansion is dangerous in a tool that automatically sends data to an external service.

Content

Scanner excerpt · index.js (reported line 42)May include surrounding context.

js
// Try to load from .env in workspace root
        const possiblePaths = [
            path.resolve(process.cwd(), '.env'),
            path.resolve(process.cwd(), '..', '.env'),
            path.resolve(__dirname, '../../..', '.env')
        ];

Credential Access

High
Category
Privilege Escalation
Confidence
97% confidence
Finding

Searching an ancestor path relative to __dirname for .env files further broadens secret discovery and can reach credentials outside the intended project boundary. This is disproportionate to the script's purpose and materially increases the risk of unauthorized secret use.

Content

Scanner excerpt · index.js (reported line 43)May include surrounding context.

js
const possiblePaths = [
            path.resolve(process.cwd(), '.env'),
            path.resolve(process.cwd(), '..', '.env'),
            path.resolve(__dirname, '../../..', '.env')
        ];
        
        for (const p of possiblePaths) {

Missing User Warnings

High
Category
Not specified by scanner
Confidence
96% confidence
Finding

The script sends prompts containing repository content, merge-conflict content, and test output to an external LLM service, but provides no explicit disclosure, approval step, or data minimization. This can leak proprietary source code, secrets embedded in files or logs, and sensitive internal context to a third party.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The script writes LLM-generated code into repository files, stages all changes, commits them, and pushes to the branch without human review or confirmation. This creates a direct path for unsafe, malicious, or simply incorrect code changes to be introduced into a PR and potentially merged.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill automates high-impact repository actions: checking out a PR, committing and pushing code changes, and enabling auto-merge if tests pass, but the description does not prominently warn users that it can modify repository history and merge changes. This omission increases the risk of accidental use in sensitive repositories, especially because the workflow includes autonomous fix attempts and merge operations that could apply unintended or unsafe changes.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The script searches for and reads GEMINI_API_KEY from .env files in the current directory, parent directory, and an ancestor path, expanding its access to local secrets beyond explicit user input. In combination with the external Gemini API call, this enables silent credential discovery and immediate use for data exfiltration to a third-party service.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

Reading API credentials from .env files in parent directories without clear notice broadens the script's access to secrets that may belong to other projects or the wider workspace. This is especially risky because the credential is then used to enable external transmission of code and logs.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The code path labeled as a conflict check actually performs a real git merge of the target branch into the PR branch, then may modify files, commit, and push AI-generated resolutions. This mismatch between stated behavior and actual side effects is dangerous because operators may expect a read-only check but instead get repository state changes and remote updates.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
90% confidence
Finding

The dependency is specified with a caret range (^1.2.8), which allows automatic installation of newer compatible versions rather than a single fixed version. This weakens build reproducibility and can expose consumers to unexpected or compromised upstream releases, though the impact here is limited because the file only shows a common CLI parsing library and no additional suspicious context.

Content

Scanner excerpt · package.json (reported line 10)May include surrounding context.

json
"test": "echo \"Error: no test specified\" && exit 1"
  },
  "dependencies": {
    "minimist": "^1.2.8"
  }
}