Back to skill

Security audit

ForkZoo

Security checks for vulnerabilities and agentic risk

Overview

This skill is a disclosed GitHub pet-management tool, but it automatically uses a powerful GitHub token to fork repositories, enable unrestricted Actions, run workflows, and publish Pages content without enough scoping or separate confirmation.

Review this before installing. Use only a fine-grained or throwaway GitHub token with the smallest possible repository permissions, ideally from a dedicated account. Do not run adopt.sh unless you are comfortable with it forking an external repo, enabling unrestricted GitHub Actions, dispatching workflows, and publishing GitHub Pages. Audit the upstream ForkZoo repositories and workflows first, and revoke the token after use.

Vulnerability Patterns
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • 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
Findings (3)

T03 · Remote Payload Retrieval and Execution

Error
Location
scripts/adopt.sh:25
Finding

Execution of Mutable Third-Party GitHub Actions Workflows

Content
View full analysis

Vulnerability Details

File Location: scripts/adopt.sh:25-28, 89-106
Vulnerability Type: Remote payload retrieval and execution
Risk Level: High

The adoption process forks a mutable external repository, enables unrestricted GitHub Actions, and immediately dispatches a workflow from that repository.

bash
# Map animal to source repo
case "$ANIMAL" in
  monkey) SOURCE_REPO="forkZoo/forkMonkey" ;;
  cat)    SOURCE_REPO="forkZoo/forkCat" ;;
  dog)    SOURCE_REPO="forkZoo/forkDog" ;;
  lion)   SOURCE_REPO="forkZoo/forkLion" ;;
esac
bash
# Enable GitHub Actions (they're disabled by default on forks)
echo "⚡ Enabling GitHub Actions..."
curl -s -X PUT \
  -H "Authorization: token $GITHUB_TOKEN" \
  -H "Accept: application/vnd.github.v3+json" \
  "https://api.github.com/repos/$GITHUB_USER/$REPO_NAME/actions/permissions" \
  -d '{"enabled": true, "allowed_actions": "all"}' > /dev/null

# Trigger the genesis workflow if it exists
echo "🐣 Initializing your pet..."
curl -s -X POST \
  -H "Authorization: token $GITHUB_TOKEN" \
  -H "Accept: application/vnd.github.v3+json" \
  "https://api.github.com/repos/$GITHUB_USER/$REPO_NAME/actions/workflows/genesis.yml/dispatches" \
  -d '{"ref": "main"}' 2>/dev/null || true

Technical Analysis

The effective workflow payload is not included in the audited project. It is obtained by forking one of four externally maintained repositories at its current, mutable state. No commit SHA, workflow digest, signature, or allowlisted workflow contents are verified before execution.

The setting "allowed_actions": "all" also permits the forked workflows to use arbitrary actions rather than a restricted set of reviewed actions. Consequently, the code that executes in GitHub Actions can change after this Skill has passed review.

This behavior is directly related to pet initialization, but it exceeds minimum privilege because all Actions are enab ...[truncated 1426 chars]

Remediation
View remediation

Remediation Suggestions

  1. Pin each supported source repository to a reviewed commit SHA and verify the forked default branch matches that SHA before enabling Actions.
  2. Retrieve and inspect the exact workflow files and referenced local actions before dispatching them.
  3. Require explicit user confirmation that identifies the upstream repository, commit SHA, workflow, and requested permissions.
  4. Replace "allowed_actions": "all" with selected-action or organization-level allowlists.
  5. Pin third-party actions inside workflows to immutable full commit SHAs rather than tags or branches.
  6. Configure the repository’s default workflow token to read-only and grant write permissions only to specific jobs that require them.
  7. Do not automatically execute the workflow if integrity validation fails or the upstream commit differs from the reviewed version.

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
SKILL.md:24
Finding

Overly Broad GitHub Token Scope Requirement

Content
View full analysis

Vulnerability Details

File Location: SKILL.md:24-26 and scripts/adopt.sh:32-38
Vulnerability Type: Excessive authorization privileges
Risk Level: Medium

The documentation and script instruct users to provide a classic GitHub token with broad repo and workflow scopes.

markdown
## Setup Requirements

Before adopting, the agent needs:
1. **GitHub Token** with `repo` and `workflow` scopes
2. Store as environment variable `GITHUB_TOKEN` or in config
bash
# Check for GitHub token
if [ -z "$GITHUB_TOKEN" ]; then
  echo "❌ GITHUB_TOKEN not set"
  echo "Set it with: export GITHUB_TOKEN=your_token"
  echo "Token needs 'repo' and 'workflow' scopes"
  exit 1
fi

Technical Analysis

For classic personal access tokens, the repo scope grants broad control over repositories accessible to the token, including private repositories unrelated to ForkZoo. The workflow scope further permits workflow-file operations.

The declared functionality only needs to create or manage a specific pet repository, configure its Actions and Pages settings, dispatch workflows, and read pet status. Requiring account-wide classic scopes gives the script a substantially larger authorization boundary than those repository-specific tasks require.

Attack Path

  1. A user follows the setup instructions and creates a classic token with repo and workflow scopes.
  2. The token is exported into the process environment.
  3. The token is exposed through a compromised local process, shell environment, diagnostic capture, or other credential leak.
  4. An attacker reuses the token through the GitHub API.
  5. Because the token is not restricted to the pet repository, the attacker may access or modify unrelated repositories covered by its scopes.

Impact Assessment

Depending on the token owner’s GitHub access, compromise could expose source code and metadata from unrelated private repositories and perm ...[truncated 363 chars]

Remediation
View remediation

Remediation Suggestions

  1. Replace the classic personal access token requirement with a fine-grained token.
  2. Restrict the token to the intended pet repository or a dedicated account with no unrelated repositories.
  3. Grant only the repository permissions needed for contents, Actions administration or dispatch, repository administration, and Pages configuration.
  4. Separate adoption from routine status checks so read-only commands can use a read-only credential.
  5. Prefer short-lived GitHub App installation tokens when feasible.
  6. Document the exact endpoint-to-permission mapping rather than broadly requesting repo and workflow.
  7. Fail safely when the supplied credential has more access than expected where token introspection allows this to be determined.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/status.sh:15
Finding

GitHub Token Exposed Through Command-Line Arguments

Content
View full analysis

Vulnerability Details

File Location: scripts/status.sh:15-17
Additional Locations: scripts/adopt.sh:40-42, scripts/interact.sh:15-17, and subsequent authenticated curl commands
Vulnerability Type: Sensitive credential exposure
Risk Level: Medium

The scripts interpolate GITHUB_TOKEN directly into curl command-line arguments.

bash
# Get current user
GITHUB_USER=$(curl -s -H "Authorization: token $GITHUB_TOKEN" \
  https://api.github.com/user | jq -r '.login')

Equivalent authenticated command patterns are used throughout adopt.sh, status.sh, and interact.sh.

Technical Analysis

Shell expansion places the complete authorization header in the curl process argument vector. Depending on operating-system process visibility and the execution environment, command arguments may be available to another local process, privileged monitoring software, CI diagnostics, process accounting, or debugging wrappers.

This finding also explains the static pre-scan alert for scripts/status.sh. The token is transmitted over HTTPS only to api.github.com, which is necessary for authenticated status retrieval and is not evidence of intentional third-party exfiltration. The avoidable issue is exposing the credential as an argument and using a broadly scoped credential for a read operation.

Attack Path

  1. A user runs one of the scripts with GITHUB_TOKEN set.
  2. The shell expands the token into the -H argument passed to curl.
  3. A local attacker or monitoring component with sufficient process-inspection access observes the curl argument vector while the request is running or captures it through diagnostics.
  4. The observer extracts the bearer credential from the authorization header.
  5. The token is replayed against GitHub within its validity period and granted scopes.

Impact Assessment

Successful exploitation grants the attacker the GitHub privileges assigned to the exp ...[truncated 385 chars]

Remediation
View remediation

Remediation Suggestions

  1. Avoid passing authentication secrets directly in process arguments.
  2. Supply the sensitive header through a protected temporary curl configuration or standard input, ensuring the secret does not appear in the process argument vector.
  3. If a temporary configuration is required, create it with restrictive permissions, use mktemp, install an exit trap, and delete it immediately after use.
  4. Prefer short-lived, fine-grained credentials with only the permissions needed by each operation.
  5. Use a read-only token for status.sh and gallery.sh-style retrieval operations.
  6. Disable shell tracing around credential handling and ensure errors or debug output never print headers.
  7. Apply the corrected credential-handling pattern consistently to every authenticated curl invocation in all scripts.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (25)

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The script enables GitHub Actions with allowed_actions: all on a freshly forked repository using a token that the user is told must have repo and workflow scopes. If the upstream pet repository or a later pull/sync contains malicious workflows or actions, this setting permits unrestricted workflow execution in the user's fork, which can exfiltrate secrets, modify repository contents, or abuse CI resources.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding

The skill instructs the agent to run local shell scripts (./scripts/adopt.sh, status.sh, interact.sh, history.sh) but does not declare any tool scope or permissions boundaries. That mismatch is dangerous because an orchestrator or reviewer cannot accurately understand or constrain the skill's execution surface, increasing the risk of unintended command execution or privilege misuse.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The description includes broad triggers such as pet-related requests, tamagotchi mentions, and especially "my pet" queries, which can match ordinary conversation unrelated to this skill. Over-broad routing can cause the agent to invoke this skill in the wrong context, leading to unnecessary shell usage, token requests, or GitHub-side actions the user did not intend.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The skill directs users to provide a GitHub token with repo and workflow scopes and store it in an environment variable, but it does not warn that these are powerful permissions that can modify repositories and trigger workflows. In this skill's context, those scopes are especially sensitive because the documented shell scripts perform repository forking and GitHub Actions enablement, so misuse could create, alter, or automate activity across the user's GitHub account.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
70% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/adopt.sh (reported line 57)May include surrounding context.

sh
fi

# Check if repo already exists
EXISTING=$(curl -s -o /dev/null -w "%{http_code}" \
  -H "Authorization: token $GITHUB_TOKEN" \
  "https://api.github.com/repos/$GITHUB_USER/$REPO_NAME")

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The script does more than adopt a pet repository: it changes repository security and publishing settings by enabling Actions, dispatching a workflow, and turning on Pages. Those side effects materially increase the attack surface of the newly forked repository and are not narrowly constrained to the minimum needed for pet adoption.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
98% confidence
Finding

This API call changes repository Actions permissions to enable workflows and allow all actions. In context, the danger is not the network transmission itself but the privileged remote state change it performs, which can allow untrusted workflows in the fork to execute with repository privileges.

Content

Scanner excerpt · scripts/adopt.sh (reported line 92)May include surrounding context.

sh
# Enable GitHub Actions (they're disabled by default on forks)
echo "⚡ Enabling GitHub Actions..."
curl -s -X PUT \
  -H "Authorization: token $GITHUB_TOKEN" \
  -H "Accept: application/vnd.github.v3+json" \
  "https://api.github.com/repos/$GITHUB_USER/$REPO_NAME/actions/permissions" \

External Transmission

Medium
Category
Data Exfiltration
Confidence
98% confidence
Finding

This endpoint reference is part of the call that enables repository Actions with unrestricted allowed actions. In context, that remote configuration change materially lowers repository safety controls and can enable execution of untrusted CI automation from the forked content.

Content

Scanner excerpt · scripts/adopt.sh (reported line 95)May include surrounding context.

sh
curl -s -X PUT \
  -H "Authorization: token $GITHUB_TOKEN" \
  -H "Accept: application/vnd.github.v3+json" \
  "https://api.github.com/repos/$GITHUB_USER/$REPO_NAME/actions/permissions" \
  -d '{"enabled": true, "allowed_actions": "all"}' > /dev/null

# Trigger the genesis workflow if it exists

External Transmission

Medium
Category
Data Exfiltration
Confidence
86% confidence
Finding

Dispatching genesis.yml triggers a workflow in the newly forked repository without any review of the workflow file or referenced actions. In the context of an upstream-controlled repo, automatically executing its workflow can run attacker-controlled CI logic with repository privileges and any secrets later added to the repo.

Content

Scanner excerpt · scripts/adopt.sh (reported line 103)May include surrounding context.

sh
curl -s -X POST \
  -H "Authorization: token $GITHUB_TOKEN" \
  -H "Accept: application/vnd.github.v3+json" \
  "https://api.github.com/repos/$GITHUB_USER/$REPO_NAME/actions/workflows/genesis.yml/dispatches" \
  -d '{"ref": "main"}' 2>/dev/null || true

# Enable GitHub Pages

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

Publishing the repository through GitHub Pages exposes repository content as a public website, which is unrelated to the minimal act of adoption and may unintentionally host unsafe or misleading content from the fork. In the context of an unreviewed upstream repo, this increases exposure and can aid phishing, reputation abuse, or accidental data disclosure if sensitive files are present in the published branch.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
90% confidence
Finding

This call enables GitHub Pages on the forked repository, causing repository content to be published publicly. While it targets GitHub's API, the security concern is the automatic publication of potentially unreviewed content rather than the mere existence of external communication.

Content

Scanner excerpt · scripts/adopt.sh (reported line 108)May include surrounding context.

sh
# Enable GitHub Pages
echo "🌐 Setting up GitHub Pages..."
curl -s -X POST \
  -H "Authorization: token $GITHUB_TOKEN" \
  -H "Accept: application/vnd.github.v3+json" \
  "https://api.github.com/repos/$GITHUB_USER/$REPO_NAME/pages" \

External Transmission

Medium
Category
Data Exfiltration
Confidence
90% confidence
Finding

This endpoint reference is part of the Pages creation call that publishes repository content. The risk comes from exposing unreviewed fork content as a public site, which expands the attack surface and can facilitate hosting of unwanted or deceptive material.

Content

Scanner excerpt · scripts/adopt.sh (reported line 111)May include surrounding context.

sh
curl -s -X POST \
  -H "Authorization: token $GITHUB_TOKEN" \
  -H "Accept: application/vnd.github.v3+json" \
  "https://api.github.com/repos/$GITHUB_USER/$REPO_NAME/pages" \
  -d '{"source": {"branch": "main", "path": "/"}}' 2>/dev/null || true

PAGES_URL="https://$GITHUB_USER.github.io/$REPO_NAME/"

External Transmission

Medium
Category
Data Exfiltration
Confidence
70% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/interact.sh (reported line 41)May include surrounding context.

sh
# Try different workflow names
for WORKFLOW in "daily-evolution.yml" "evolve.yml" "daily.yml"; do
  RESPONSE=$(curl -s -o /dev/null -w "%{http_code}" -X POST \
    -H "Authorization: token $GITHUB_TOKEN" \
    -H "Accept: application/vnd.github.v3+json" \
    "https://api.github.com/repos/$GITHUB_USER/$REPO_NAME/actions/workflows/$WORKFLOW/dispatches" \

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The script uses GITHUB_TOKEN in authenticated curl requests to the GitHub API, which is a sensitive credential access and network transmission path. While it checks whether the token is set, it does not disclose to the user that the token will be used for authenticated API calls or that account/repository metadata will be sent to GitHub.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/adopt.sh (reported line 40)May include surrounding context.

sh
# Get current user
GITHUB_USER=$(curl -s -H "Authorization: token $GITHUB_TOKEN" \
  https://api.github.com/user | jq -r '.login')

# If no repo specified, try to find one
if [ -z "$REPO_NAME" ]; then

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/adopt.sh (reported line 59)May include surrounding context.

sh
# Get current user
GITHUB_USER=$(curl -s -H "Authorization: token $GITHUB_TOKEN" \
  https://api.github.com/user | jq -r '.login')

# If no repo specified, try to find one
if [ -z "$REPO_NAME" ]; then

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/adopt.sh (reported line 73)May include surrounding context.

sh
# Get current user
GITHUB_USER=$(curl -s -H "Authorization: token $GITHUB_TOKEN" \
  https://api.github.com/user | jq -r '.login')

# If no repo specified, try to find one
if [ -z "$REPO_NAME" ]; then

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/gallery.sh (reported line 17)May include surrounding context.

sh
# Get current user
GITHUB_USER=$(curl -s -H "Authorization: token $GITHUB_TOKEN" \
  https://api.github.com/user | jq -r '.login')

# If no repo specified, try to find one
if [ -z "$REPO_NAME" ]; then

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/interact.sh (reported line 17)May include surrounding context.

sh
# Get current user
GITHUB_USER=$(curl -s -H "Authorization: token $GITHUB_TOKEN" \
  https://api.github.com/user | jq -r '.login')

# If no repo specified, try to find one
if [ -z "$REPO_NAME" ]; then

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/interact.sh (reported line 22)May include surrounding context.

sh
# Get current user
GITHUB_USER=$(curl -s -H "Authorization: token $GITHUB_TOKEN" \
  https://api.github.com/user | jq -r '.login')

# If no repo specified, try to find one
if [ -z "$REPO_NAME" ]; then

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/interact.sh (reported line 44)May include surrounding context.

sh
# Get current user
GITHUB_USER=$(curl -s -H "Authorization: token $GITHUB_TOKEN" \
  https://api.github.com/user | jq -r '.login')

# If no repo specified, try to find one
if [ -z "$REPO_NAME" ]; then

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/status.sh (reported line 17)May include surrounding context.

sh
# Get current user
GITHUB_USER=$(curl -s -H "Authorization: token $GITHUB_TOKEN" \
  https://api.github.com/user | jq -r '.login')

# If no repo specified, try to find one
if [ -z "$REPO_NAME" ]; then

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/status.sh (reported line 25)May include surrounding context.

sh
# Get current user
GITHUB_USER=$(curl -s -H "Authorization: token $GITHUB_TOKEN" \
  https://api.github.com/user | jq -r '.login')

# If no repo specified, try to find one
if [ -z "$REPO_NAME" ]; then

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/status.sh (reported line 45)May include surrounding context.

sh
# Get current user
GITHUB_USER=$(curl -s -H "Authorization: token $GITHUB_TOKEN" \
  https://api.github.com/user | jq -r '.login')

# If no repo specified, try to find one
if [ -z "$REPO_NAME" ]; then

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/status.sh (reported line 51)May include surrounding context.

sh
# Get current user
GITHUB_USER=$(curl -s -H "Authorization: token $GITHUB_TOKEN" \
  https://api.github.com/user | jq -r '.login')

# If no repo specified, try to find one
if [ -z "$REPO_NAME" ]; then

Static analysis

No suspicious patterns detected.