Back to skill

Security audit

tauri-2-app

Security checks for vulnerabilities and agentic risk

Overview

This Tauri app scaffolding skill is purpose-aligned overall, but some source templates can generate unsafe file access and overly broad desktop permissions.

Review and tighten the generated templates before using this skill for production: remove or constrain any generic write_file command, validate storage filenames against app_data_dir containment, and generate Tauri plugins/capabilities only for features the app actually needs. Treat dependency resolution and updater setup as user-controlled steps, with pinned versions and user-owned signing keys/endpoints.

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

T09 · Insecure Skill Coding Practices

Error
Location
references/good-patterns.md:198
Finding

Unrestricted Frontend-Triggered Arbitrary File Write

Content
View full analysis
.rs use crate::error::ResultExt; #[tauri::command] pub fn write_file(path: String, content: String) -> Result<(), String> { std::fs::write(&path, content).into_string_msg("Failed to write file") } ``` The command is included in the generated IPC handler: ```rust .invoke_handler(tauri::generate_handler![ // System commands commands::write_file, commands::save_file_dialog, commands::open_file_dialog, ``` ### Technical Analysis Both `path` and `content` originate from the frontend IPC caller. The backend passes the path directly to `std::fs::write` without validation, canonicalization, an allowlisted root directory, or proof that the user selected the destination through a trusted native dialog. Tauri capability rules governing `tauri-plugin-fs` do not constrain direct Rust standard-library filesystem calls. Consequently, registering this command exposes the native process's filesystem privileges directly to the WebView. This guidance also contradicts the Skill's prohibition in `SKILL.md:220` against raw filesystem writes using user-supplied paths. ### Attack Path 1. An attacker gains script execution in the WebView through an application vulnerability, compromised frontend dependency, unsafe remote content, or another XSS-equivalent path. 2. The attacker calls the registered `write_file` Tauri command. 3. The attacker supplies an arbitrary user-writable destination and chosen content. 4. The Rust backend writes the content using the application's native privileges. 5. The attacker may overwrite configuration files, shell initialization files, application data, or `~/.ssh/authorized_keys`, depending on operating-system permissions. ...[truncated 754 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
references/templates/storage-mod.md:29
Finding

Path Traversal and Absolute-Path Escape in Storage Helper

Content
View full analysis
Result { Ok(get_app_data_dir(app)?.join(filename)) } ``` The returned path is subsequently used for direct filesystem writes: ```rust /// Save a slice as pretty-printed JSON to `filename` inside the app data dir. pub fn save_json( app: &AppHandle, filename: &str, entries: &[T], ) -> Result<(), String> { let path = get_storage_path(app, filename)?; let json = serde_json::to_string_pretty(entries) .map_err(|e| format!("Failed to serialize: {}", e))?; fs::write(&path, json).map_err(|e| format!("Failed to write {}: {}", filename, e))?; tracing::info!("Saved {} entries to {}", entries.len(), path.display()); Ok(()) } ``` ### Technical Analysis `PathBuf::join` does not enforce containment beneath the base directory. A filename containing parent-directory components, such as `../../target.json`, can escape the application data directory. On supported platforms, joining an absolute path may also replace or otherwise escape the intended base path. The helper performs no checks for: - Absolute paths. - `ParentDir` components. - Windows drive or UNC prefixes. - Symbolic-link traversal. - Canonicalized containment beneath the application data directory. The helper is publicly re-exported by `references/templates/lib-rs.md`, increasing the chance that generated commands or modules will call it with frontend-controlled or imported values. ### Attack Path 1. A generated command or module accepts a filename from the frontend, imported data, a synchronization record, or another untrusted source. 2. The value is passed to `save_json`, `lo ...[truncated 926 chars]
Remediation
View remediation
Result<&Path, String> { let path = Path::new(filename); if path.is_absolute() || path.components().any(|component| { !matches!(component, Component::Normal(_)) }) { return Err("invalid storage filename".into()); } Ok(path) } ``` Canonical containment and symbolic-link protections should still be applied before accessing the resulting path. ]]>

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
references/templates/capabilities.md:9
Finding

Default Templates Enable Native Plugins and Capabilities Beyond Selected Features

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Memory PoisoningPersistent Context Injection, Context Window Stuffing, Memory Manipulation
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Rogue AgentSelf-Modification, Session Persistence
Findings (72)

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 · SKILL.md (reported line 111)May include surrounding context.

md
vite.config.ts               # port 5173, ignores src-tauri, base: './'
  index.html                   # anti-flash theme script if dark/light theming is in scope
  .gitignore                   # MUST include src-tauri/target/, dist/, .env, *.backup, *.orig, *.temp
  .env.example                 # NEVER .env — only .env.example committed
  src/                         # frontend (TS / React)
    main.tsx                   # entry: createRoot + render
    App.tsx

Credential Access

High
Category
Privilege Escalation
Confidence
90% confidence
Finding

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

Content

Scanner excerpt · references/anti-patterns.md (reported line 99)May include surrounding context.

}

text

**Why it's bad:** Bypasses Tauri's capability system. A misconfigured frontend can ask the command to overwrite `~/.ssh/authorized_keys` or `/etc/hosts`. The whole point of capabilities is to gate dangerous APIs.

**Fix:** Either route through `tauri-plugin-fs` (which respects `fs:scope-*` capability scopes), or restrict raw I/O to paths derived from `app_handle.path().app_data_dir()`.

Memory Manipulation

High
Category
Memory Poisoning
Confidence
80% confidence
Finding

Skill manipulates agent memory, state, or stored context. Memory corruption can alter personality, override safety rules, or cause unpredictable behavior.

Content

Scanner excerpt · references/good-patterns.md (reported line 105)May include surrounding context.

Why: Users perceive a Tauri app as broken if the window doesn't appear within ~500ms. Synchronous setup work (model loading, device enumeration, network calls) blocks the window from drawing.

Reset state on startup

rust
// In .setup(), before any "ready" event:

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 · references/good-patterns.md (reported line 471)May include surrounding context.

md
- name: Install Ubuntu system deps
        if: matrix.platform == 'ubuntu-latest'
        run: |
          sudo apt-get update
          sudo apt-get install -y \
            libgtk-3-dev \

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 · references/templates/ci-workflow.md (reported line 46)May include surrounding context.

md
- name: Install Ubuntu system deps
        if: matrix.platform == 'ubuntu-latest'
        run: |
          sudo apt-get update
          sudo apt-get install -y \
            libgtk-3-dev \

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

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

Content

Scanner excerpt · references/templates/encryption-mod.md (reported line 13)May include surrounding context.

md
//! Threat model: protects against casual disk reads (backup syncs, malware
//! grepping files, accidental leaks via shared screenshots). Does NOT protect
//! against a privileged process on the same machine. For higher assurance,
//! integrate the OS-native keychain.

use aes_gcm::{
    aead::{Aead, AeadCore, KeyInit, OsRng},

Hidden Instructions

High
Category
Prompt Injection
Confidence
70% confidence
Finding

Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Content

Scanner excerpt · references/templates/macos-plist.md (reported line 15)May include surrounding context.

md
<key>CFBundleIdentifier</key>
    <string>{{bundle.identifier}}</string>

    <!-- Usage descriptions: REQUIRED for every OS permission the app requests. -->
    <!-- Without these, the permission prompt never shows and the call returns "denied". -->

    <!-- Microphone — required if the app uses cpal / AVFoundation audio input. -->

Hidden Instructions

High
Category
Prompt Injection
Confidence
70% confidence
Finding

Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Content

Scanner excerpt · references/templates/macos-plist.md (reported line 23)May include surrounding context.

md
<string>{{ProductName}} needs the microphone to record voice input.</string> -->

    <!-- Accessibility — required if the app sends synthetic keystrokes / reads UI. -->
    <!-- <key>NSAccessibilityUsageDescription</key>
    <string>{{ProductName}} needs Accessibility access to insert text into other apps.</string> -->

    <!-- AppleEvents — required if the app sends AppleScript to other apps. -->

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The manifest description says to use the skill when the user says phrases including "my Tauri conventions," even if they don't name the skill. That phrase is broad and could easily arise in ordinary discussion about a project without clearly indicating the user wants this scaffolding skill invoked.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The skill triggers when a user pastes a feature spec for a desktop feature and asks to wire it through the backend and frontend, but this does not clearly distinguish between wanting advice, review, or actual use of this skill. Without tighter constraints, ordinary implementation discussions could unintentionally activate the skill.

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.

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.

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

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

md
- **`tauri.conf.json` `windows[].devtools: false`** (or omitted — Tauri defaults to off in release). DevTools should be opened from a build-time feature flag, not the production config.
- **Reset-state-on-startup pattern** — in `pub fn run()`'s `.setup(|app| { ... })`, clear any in-progress / stuck state from a previous run before showing the window. Crashes leave globals in odd places; treat each startup as recovering from "the app was force-quit".
- **Show window FIRST in `.setup()`** before any blocking initialization. Heavy work (ML model loading, large config parses) goes on a background thread that emits events back to the frontend.
- **Minimal comments in generated code (Rust and TS).** Default to no comments. Only add one when the *why* is non-obvious — `// SAFETY:` on an `unsafe` block, a workaround for a specific upstream bug (with a link), a non-trivial invariant the code depends on, a platform quirk that isn't visible from the names. Never write Rust doc-comment blocks (`///`) on internal items; reserve them for genuinely public API surface (`pub` types crossing crate boundaries). Never restate *what* the next line does, never leave `// TODO` without an issue link. One short line max — no multi-line comment blocks. `// SAFETY:` on `unsafe` is the one place verbose justification is *required*; everywhere else, well-named identifiers carry the *what* and comments earn their place only when they carry *why*.

### Eliminate (anti-patterns)

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · references/good-patterns.md (reported line 472)May include surrounding context.

  • name: Install Ubuntu deps if: matrix.platform == 'ubuntu-latest' run: | sudo apt-get update sudo apt-get install -y libgtk-3-dev libayatana-appindicator3-dev pkg-config - run: cd src-tauri && cargo test
text

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · references/good-patterns.md (reported line 473)May include surrounding context.

  • name: Install Ubuntu deps if: matrix.platform == 'ubuntu-latest' run: | sudo apt-get update sudo apt-get install -y libgtk-3-dev libayatana-appindicator3-dev pkg-config - run: cd src-tauri && cargo test
text

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · references/templates/ci-workflow.md (reported line 47)May include surrounding context.

md
- name: Install Ubuntu system deps
        if: matrix.platform == 'ubuntu-latest'
        run: |
          sudo apt-get update
          sudo apt-get install -y \
            libgtk-3-dev \
            libayatana-appindicator3-dev \

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · references/templates/ci-workflow.md (reported line 48)May include surrounding context.

md
- name: Install Ubuntu system deps
        if: matrix.platform == 'ubuntu-latest'
        run: |
          sudo apt-get update
          sudo apt-get install -y \
            libgtk-3-dev \
            libayatana-appindicator3-dev \

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
94% confidence
Finding

The skill manifest describes scaffolding a Tauri app with a self-hosted updater, which implies the generated app should include updater integration. In this template, the updater plugin is explicitly commented out with a note to enable it later, so the shipped scaffold does not match that advertised capability.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

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

md
# macOS `Info.plist` and `entitlements.plist`

Both files live at `src-tauri/Info.plist` and `src-tauri/entitlements.plist` and are referenced from `tauri.conf.json` `bundle.macOS`.

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

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

md
# macOS `Info.plist` and `entitlements.plist`

Both files live at `src-tauri/Info.plist` and `src-tauri/entitlements.plist` and are referenced from `tauri.conf.json` `bundle.macOS`.