Back to skill

Security audit

Turborepo Monorepo Patterns

Security checks for vulnerabilities and agentic risk

Overview

This Turborepo guide is mostly coherent, but its CI template exposes build and deployment secrets too broadly and runs an unpinned deployment CLI with those credentials.

Review the CI template before using it. Scope TURBO_TOKEN and TURBO_TEAM only to Turbo steps, pin or lock the Vercel CLI before giving it a deployment token, restrict secrets to trusted workflows, and confirm that remote cache outputs do not contain sensitive artifacts.

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

T09 · Insecure Skill Coding Practices

Error
Location
references/ci-github-actions.yml:10
Finding

Workflow-level remote-cache credentials are exposed to unrelated CI steps

Content
View full analysis

Vulnerability Details

File Location: references/ci-github-actions.yml, lines 10-12
Vulnerability Type: Excessive secret scope and potential credential exfiltration
Risk Level: High

Vulnerable code:

yaml
env:
  TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
  TURBO_TEAM: ${{ secrets.TURBO_TEAM }}

Technical Analysis

TURBO_TOKEN and TURBO_TEAM are declared in the workflow-level env block. Consequently, GitHub Actions injects them into every process launched by every step in every job, rather than only into the Turbo build commands that require remote caching.

The credentials are therefore available to:

  • Package lifecycle scripts executed by pnpm install --frozen-lockfile.
  • Repository-controlled lint, test, type-check, and build scripts.
  • All third-party actions and subprocesses used by the workflow.
  • The preview deployment job, even though its Vercel deployment operation does not inherently require the Turbo remote-cache credentials.

This exceeds minimum privilege. The declared functionality only requires the credentials while Turbo communicates with the configured remote-cache service. Supplying them to dependency installation and unrelated commands creates an unnecessary exfiltration path. A malicious dependency lifecycle script or malicious same-repository pull request could read the environment variables and transmit them over the network.

GitHub normally withholds repository secrets from pull requests originating from forks, which limits one common attack path. It does not protect against compromised dependencies, malicious changes from branches within the repository, compromised maintainer accounts, or untrusted commands running during push-triggered workflows.

Attack Path

  1. An attacker compromises a dependency, contributes a malicious package lifecycle script, or modifies a repository script that executes in CI.
  2. A workflow runs on push or on an eligible pull req ...[truncated 1141 chars]
Remediation
View remediation

Remediation Suggestions

  • Remove the workflow-level env declaration.
  • Inject the remote-cache credentials only into individual Turbo steps that need remote caching:
    yaml
    - name: Build
      run: pnpm turbo build
      env:
        TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
        TURBO_TEAM: ${{ secrets.TURBO_TEAM }}
    
  • Do not expose these variables to pnpm install, linting, or other commands unless remote-cache access is demonstrably required.
  • Consider disabling remote cache for untrusted pull-request validation and enabling it only for trusted branches or post-merge workflows.
  • Use separate credentials for read-only and cache-write operations where the remote-cache provider supports that distinction.
  • Restrict the token to the specific team and repository and configure the shortest practical lifetime.
  • Review package lifecycle scripts and consider pnpm install --ignore-scripts where compatible, followed by explicit execution of only required installation scripts.
  • Add egress controls or monitoring to CI runners where practical, and rotate TURBO_TOKEN immediately if exposure is suspected.

T08 · Insecure Dependencies

Error
Location
references/ci-github-actions.yml:100
Finding

Unpinned Vercel CLI is remotely resolved and receives a deployment token

Content
View full analysis

Vulnerability Details

File Location: references/ci-github-actions.yml, lines 100-103
Vulnerability Type: Unpinned third-party executable with access to deployment credentials
Risk Level: High

Vulnerable code:

yaml
- name: Deploy web to Vercel (preview)
  run: |
    pnpm turbo build --filter=web
    npx vercel --token=${{ secrets.VERCEL_TOKEN }} \
      --scope=${{ secrets.VERCEL_ORG_ID }} \
      --project=${{ secrets.VERCEL_PROJECT_ID }}

Technical Analysis

The workflow invokes npx vercel without a version pin and without demonstrating that the CLI is locked in the repository's dependency lockfile. If the package is not already installed locally, npx can retrieve executable package content from the configured npm registry at workflow runtime.

This makes the effective executable mutable after the Skill and workflow have been reviewed. A compromised upstream release, registry account, registry configuration, or dependency chain could cause different code to execute under the same workflow definition.

The risk is amplified because the remotely resolved executable is passed VERCEL_TOKEN, VERCEL_ORG_ID, and VERCEL_PROJECT_ID. A malicious CLI package can read command-line arguments and process environment data before performing, altering, or skipping the expected deployment.

Passing the token directly as a command-line argument also makes it available through process-argument inspection while the process is running. GitHub log masking reduces accidental log disclosure but does not protect the value from code running on the same runner.

This network retrieval is related to the Skill's deployment functionality, but dynamically selecting the latest available executable is not necessary. A reviewed, integrity-locked version is sufficient and follows least privilege and supply-chain hardening principles.

Attack Path

  1. An attacker compromises the vercel npm package, one of its ...[truncated 1312 chars]
Remediation
View remediation

Remediation Suggestions

  • Add the Vercel CLI as an exact-version development dependency, commit the lockfile, and invoke the locked binary:
    bash
    pnpm add --save-dev --save-exact vercel@REVIEWED_VERSION
    pnpm exec vercel --token="$VERCEL_TOKEN" \
      --scope="$VERCEL_ORG_ID" \
      --project="$VERCEL_PROJECT_ID"
    
  • Continue using pnpm install --frozen-lockfile so CI fails if dependency resolution differs from the reviewed lockfile.
  • If runtime retrieval is unavoidable, specify an exact package version and enforce the trusted npm registry; a lockfile-backed local installation remains preferable.
  • Pass secrets through step-scoped environment variables rather than embedding GitHub expressions directly in the shell command:
    yaml
    env:
      VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }}
      VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
      VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}
    
  • Use a dedicated Vercel token restricted to the required project and preview-deployment operations.
  • Do not expose deployment credentials to workflows running untrusted pull-request code. Require approval or run deployment from a trusted post-validation workflow.
  • Pin GitHub Actions dependencies to audited commit SHAs for additional supply-chain protection.
  • Enable dependency update review and integrity monitoring, and rotate the Vercel token after any suspected package or runner compromise.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (13)

Chaining Abuse

High
Category
Tool Misuse
Confidence
75% confidence
Finding

Tool calls are chained to bypass individual safety checks or escalate capabilities beyond what any single tool call would allow.

Content

Scanner excerpt · SKILL.md (reported line 81)May include surrounding context.

md
"lint": "turbo lint",
    "test": "turbo test",
    "type-check": "turbo type-check",
    "clean": "turbo clean && rm -rf node_modules"
  },
  "devDependencies": {
    "turbo": "latest"

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding

npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
86% confidence
Finding

The skill instructs users to enable remote caching and pass an authentication token to a remote endpoint without any warning that build artifacts, logs, environment-derived outputs, or metadata may be uploaded off-host. In a monorepo context, cached outputs can include sensitive internal code or generated artifacts, so omission of privacy and credential-handling guidance creates real data exposure risk.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding

npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding

npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The manifest describes a skill for setting up and managing a Turborepo monorepo, including CI/CD integration, which reasonably covers build/test workflows. However, this file also performs an actual preview deployment to an external hosting platform (Vercel), which goes beyond repository/CI orchestration and into application deployment behavior not stated in the description.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

Running npx vercel with organization, project, and token secrets grants the workflow an external service deployment capability. For a skill framed around workspace configuration, task pipelines, caching, shared packages, and CI/CD integration for Turborepo, this hosting-provider-specific deployment action is broader than the clearly stated core purpose.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
94% confidence
Finding

The workflow executes npx vercel without pinning an exact package version, which causes the runner to fetch and execute the latest CLI at build time. In CI, this creates a supply-chain risk: a compromised upstream release or unexpected breaking behavior could result in unreviewed code execution with access to repository contents and deployment secrets such as VERCEL_TOKEN.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

This markdown file includes code examples that hard-code zh-CN and CNY as defaults in natural-language-adjacent sample code. That can violate language/locale policy because it implicitly forces a specific locale for formatting behavior without user opt-in or any documented regional justification.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding

npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding

npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding

npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding

npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Content

No source excerpt is available for this finding.