Back to skill

Security audit

tauri2-best-practice

Security checks for vulnerabilities and agentic risk

Overview

The skill is a documentation-only Tauri v2 guide, but it includes runnable examples that could lead agents to generate unsafe file-write and weak CI release workflows.

Review the examples before using this skill as an implementation source. In particular, avoid copying the IPC `save_file` command as written; require writes to stay under an app-owned directory and validate filenames. Pin CI actions, Node/Rust versions, npm dependencies, and test runners before using the release or E2E workflow examples, especially where signing secrets are available.

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

T09 · Insecure Skill Coding Practices

Error
Location
references/ipc-commands.md:28
Finding

Webview-Controlled Arbitrary File Write Through IPC Command

Content
View full analysis

Vulnerability Details

File Location: references/ipc-commands.md, lines 28-31
Vulnerability Type: Unrestricted file write
Risk Level: High

Vulnerable Code:

rust
#[tauri::command]
async fn save_file(path: String, contents: String) -> Result<(), String> {
    std::fs::write(&path, contents).map_err(|e| e.to_string())
}

The corresponding frontend example at line 43 demonstrates that the path is supplied directly by the webview:

ts
await invoke("save_file", { path: "/tmp/out.txt", contents: "hi" });

Technical Analysis

The IPC command accepts an arbitrary path and file contents from the frontend and passes them directly to std::fs::write. It does not:

  • Restrict writes to a dedicated application directory.
  • Reject absolute paths or .. traversal components.
  • Canonicalize and validate the destination or its parent directory.
  • protect against symbolic-link redirection.
  • Enforce an allowlist of permitted filenames or extensions.
  • Prevent overwriting an existing sensitive file.

Tauri capability controls can determine whether a webview may invoke this custom command, but they do not automatically restrict filesystem paths accessed internally by the Rust implementation. Once the command is callable, it writes with all filesystem privileges of the application process.

This exceeds the minimum privilege required for a typical “save file” example because the frontend receives authority to select any destination writable by the current user.

Attack Path

  1. An attacker compromises frontend execution through an XSS flaw, malicious bundled dependency, or other webview code-injection weakness.
  2. The compromised frontend invokes save_file.
  3. The attacker supplies an absolute path or traversal-based destination and attacker-controlled contents.
  4. The Rust backend writes to that destination with native application privileges.
  5. Depending on writable ...[truncated 661 chars]
Remediation
View remediation

Remediation Suggestions

  • Do not accept an unrestricted filesystem path from the webview. Accept a logical filename or application-specific resource identifier instead.
  • Resolve destinations beneath a dedicated directory such as the application data directory.
  • Reject absolute paths, parent-directory components, platform-specific path prefixes, and embedded separators where filenames alone are expected.
  • Canonicalize the approved parent directory and destination parent, then verify that the resolved destination remains beneath the approved root.
  • Defend against symbolic-link and time-of-check/time-of-use attacks by using platform-appropriate no-follow and exclusive-create operations when relevant.
  • Decide explicitly whether overwriting is permitted; otherwise use create-new semantics.
  • Apply filename, extension, and size limits.
  • Consider using Tauri’s scoped filesystem APIs so filesystem access is represented explicitly in capabilities.
  • Add tests for absolute paths, ../ traversal, symlink redirection, Windows path prefixes, and overwrite attempts.

T08 · Insecure Dependencies

Warning
Location
references/bundling-updater-cicd.md:100
Finding

Mutable and Non-Reproducible Dependencies in Secret-Bearing Release Workflow

Content
View full analysis

Vulnerability Details

File Location: references/bundling-updater-cicd.md, lines 100-112
Vulnerability Type: CI/CD supply-chain exposure
Risk Level: Medium

Vulnerable Code:

yaml
steps:
  - uses: actions/checkout@v4
  - uses: dtolnay/rust-toolchain@stable
  - uses: actions/setup-node@v4
    with: { node-version: 'lts/*' }
  - run: npm install
  - uses: tauri-apps/tauri-action@v0
    env:
      GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
      TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
      # + platform-specific signing secrets (Apple ID/cert, Azure Key Vault, etc.)

Technical Analysis

The release workflow executes several dependencies through mutable references:

  • GitHub Actions use major-version tags rather than immutable commit SHAs.
  • dtolnay/rust-toolchain@stable selects a moving toolchain.
  • Node uses the moving lts/* version selector.
  • npm install may resolve dependency versions differently over time and executes package lifecycle scripts by default.
  • tauri-apps/tauri-action@v0 is a mutable action tag.

The workflow later provides repository and updater-signing credentials to the release action. Although GitHub masks secret values in logs, masking does not stop malicious code running in the job from using or transmitting them. Earlier compromised steps can also modify the workspace or generated files consumed by the signing and publishing step.

No dependency is shown to be intentionally malicious. The vulnerability is the unsafe trust and pinning model presented as a release best practice.

Attack Path

  1. An upstream action tag is moved or an npm dependency or lifecycle script is compromised.
  2. The release runner executes the changed third-party code.
  3. Malicious code modifies source files, build outputs, updater metadata, or rele ...[truncated 842 chars]
Remediation
View remediation

Remediation Suggestions

  • Pin every third-party GitHub Action to a reviewed full commit SHA; retain the release tag in a comment for maintainability.
  • Pin an exact Rust toolchain and Node.js version rather than stable and lts/*.
  • Commit the npm lockfile and use npm ci instead of npm install.
  • Use npm ci --ignore-scripts where lifecycle scripts are unnecessary. Where scripts are required, document and audit each required script.
  • Enable dependency update automation so pinned SHAs and versions are updated through reviewed pull requests.
  • Separate compilation from signing and publishing into different jobs.
  • Pass immutable build artifacts between jobs and verify hashes or attestations before signing.
  • Grant the GitHub token only the minimum required permissions and use protected release environments with approval gates.
  • Avoid exposing signing secrets to pull-request workflows or untrusted code paths.
  • Prefer short-lived or hardware-backed signing credentials where supported.

T08 · Insecure Dependencies

Warning
Location
references/testing.md:132
Finding

Unpinned Package Execution in End-to-End Test Workflow

Content
View full analysis

Vulnerability Details

File Location: references/testing.md, lines 132-139
Vulnerability Type: CI dependency and tool execution risk
Risk Level: Medium

Vulnerable Code:

yaml
jobs:
  e2e:
    strategy:
      matrix: { platform: [ubuntu-latest, windows-latest] }
    runs-on: ${{ matrix.platform }}
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@stable
      - uses: actions/setup-node@v4
      - run: npm install
      - run: npm run tauri build -- --debug   # or the appropriate dev/test build
      - run: npx wdio run wdio.conf.ts

Technical Analysis

This CI example uses mutable runner and dependency inputs, including ubuntu-latest, windows-latest, major-version action tags, and the moving Rust stable channel. It installs JavaScript dependencies with npm install, which may update resolution and execute lifecycle scripts.

The final command uses npx wdio. If the expected executable is absent from local dependencies, npx can download and execute a package from the configured registry. This makes the executed test tool dependent on registry state and package-manager behavior rather than exclusively on reviewed, lockfile-pinned project dependencies.

The test job does not show signing secrets, so its direct credential risk is lower than the release workflow. Nevertheless, it executes third-party code on CI runners and can undermine test integrity or abuse any credentials and permissions available to the job.

Attack Path

  1. An upstream action, npm dependency, lifecycle script, or package selected by npx is compromised or resolves unexpectedly.
  2. The CI runner downloads and executes the changed code.
  3. The code tampers with test configuration, suppresses failures, alters build outputs, reads job-accessible data, or uses available repository credentials.
  4. The workflow reports misleading test results or performs unauthorized acti ...[truncated 408 chars]
Remediation
View remediation

Remediation Suggestions

  • Pin GitHub Actions to immutable commit SHAs.
  • Pin exact runner images where operationally practical, or explicitly account for runner-image changes.
  • Pin the Rust and Node.js versions.
  • Commit and enforce a package lockfile with npm ci.
  • Add WebdriverIO and its Tauri service as explicit development dependencies.
  • Invoke the locally installed executable through an npm script, such as npm run e2e, rather than allowing npx to fetch a missing package.
  • If npx must be used, apply an option that prevents installation and fails when the executable is not locally available.
  • Disable npm lifecycle scripts when they are unnecessary and audit exceptions.
  • Set explicit least-privilege workflow permissions, especially for workflows triggered by pull requests.
  • Do not expose repository secrets to workflows running untrusted fork code.
Vulnerability Patterns
  • 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
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
Findings (2)

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.

Static analysis

No suspicious patterns detected.