home / skills / dchuk / claude-code-tauri-skills / tauri-http-headers

tauri-http-headers skill

/tauri/tauri-http-headers

This skill helps you secure Tauri v2 apps by configuring HTTP security headers, CORS, and related policies in tauri.conf.json.

npx playbooks add skill dchuk/claude-code-tauri-skills --skill tauri-http-headers

Review the files below or copy the command above to add this skill to your agents.

Files (1)
SKILL.md
8.3 KB
---
name: configuring-tauri-http-headers
description: Guides developers through configuring HTTP headers security in Tauri v2 applications, covering security headers, custom headers, and CORS configuration for secure cross-origin resource handling.
---

# Tauri HTTP Headers Security Configuration

This skill covers HTTP headers configuration in Tauri v2.1.0+, enabling developers to set security headers in webview responses.

## Overview

Tauri allows configuring HTTP headers that are included in responses to the webview. These headers apply to production builds and do not affect IPC messages or error responses.

## Supported Headers (Allowlist)

Tauri restricts header configuration to a specific allowlist for security:

### CORS Headers
- `Access-Control-Allow-Credentials`
- `Access-Control-Allow-Headers`
- `Access-Control-Allow-Methods`
- `Access-Control-Expose-Headers`
- `Access-Control-Max-Age`

### Cross-Origin Policies
- `Cross-Origin-Embedder-Policy`
- `Cross-Origin-Opener-Policy`
- `Cross-Origin-Resource-Policy`

### Security Headers
- `X-Content-Type-Options`
- `Permissions-Policy`
- `Timing-Allow-Origin`
- `Service-Worker-Allowed`

### Testing Only
- `Tauri-Custom-Header` (not for production use)

## Configuration in tauri.conf.json

Headers are configured under `app.security.headers` in `src-tauri/tauri.conf.json`.

### Value Formats

1. **String**: Direct assignment
2. **Array**: Items joined by commas
3. **Object**: Key-value pairs formatted as "key value", joined by semicolons
4. **Null**: Header is ignored

### Basic Configuration Example

```json
{
  "app": {
    "security": {
      "headers": {
        "Cross-Origin-Opener-Policy": "same-origin",
        "Cross-Origin-Embedder-Policy": "require-corp",
        "X-Content-Type-Options": "nosniff"
      }
    }
  }
}
```

### Comprehensive Configuration Example

```json
{
  "app": {
    "security": {
      "headers": {
        "Cross-Origin-Opener-Policy": "same-origin",
        "Cross-Origin-Embedder-Policy": "require-corp",
        "Cross-Origin-Resource-Policy": "same-origin",
        "Timing-Allow-Origin": [
          "https://example.com",
          "https://api.example.com"
        ],
        "X-Content-Type-Options": "nosniff",
        "Permissions-Policy": {
          "camera": "()",
          "microphone": "()",
          "geolocation": "(self)"
        },
        "Access-Control-Allow-Methods": ["GET", "POST", "PUT", "DELETE"],
        "Access-Control-Allow-Headers": ["Content-Type", "Authorization"],
        "Access-Control-Max-Age": "86400"
      },
      "csp": "default-src 'self'; connect-src ipc: http://ipc.localhost"
    }
  }
}
```

## Enabling SharedArrayBuffer

`SharedArrayBuffer` requires specific cross-origin policies. Configure both headers together:

```json
{
  "app": {
    "security": {
      "headers": {
        "Cross-Origin-Opener-Policy": "same-origin",
        "Cross-Origin-Embedder-Policy": "require-corp"
      }
    }
  }
}
```

## CORS Configuration Examples

### Restrictive CORS (Recommended for Production)

```json
{
  "app": {
    "security": {
      "headers": {
        "Cross-Origin-Resource-Policy": "same-origin",
        "Access-Control-Allow-Credentials": "false",
        "Access-Control-Allow-Methods": ["GET"],
        "Access-Control-Max-Age": "3600"
      }
    }
  }
}
```

### Permissive CORS (Development/API Scenarios)

```json
{
  "app": {
    "security": {
      "headers": {
        "Cross-Origin-Resource-Policy": "cross-origin",
        "Access-Control-Allow-Methods": ["GET", "POST", "PUT", "DELETE", "OPTIONS"],
        "Access-Control-Allow-Headers": ["Content-Type", "Authorization", "X-Requested-With"],
        "Access-Control-Expose-Headers": ["Content-Length", "X-Request-Id"],
        "Access-Control-Max-Age": "86400"
      }
    }
  }
}
```

## Development Server Configuration

Development frameworks require separate header configuration for their dev servers. Tauri header injection only applies to production builds.

### Vite (React, Vue, Svelte, Solid, Qwik)

```typescript
// vite.config.ts
import { defineConfig } from 'vite';

export default defineConfig({
  server: {
    headers: {
      'Cross-Origin-Opener-Policy': 'same-origin',
      'Cross-Origin-Embedder-Policy': 'require-corp',
      'X-Content-Type-Options': 'nosniff'
    }
  }
});
```

### Angular

```json
// angular.json
{
  "projects": {
    "your-app": {
      "architect": {
        "serve": {
          "options": {
            "headers": {
              "Cross-Origin-Opener-Policy": "same-origin",
              "Cross-Origin-Embedder-Policy": "require-corp"
            }
          }
        }
      }
    }
  }
}
```

### Nuxt

```typescript
// nuxt.config.ts
export default defineNuxtConfig({
  vite: {
    server: {
      headers: {
        'Cross-Origin-Opener-Policy': 'same-origin',
        'Cross-Origin-Embedder-Policy': 'require-corp'
      }
    }
  }
});
```

### Next.js

```javascript
// next.config.js
module.exports = {
  async headers() {
    return [
      {
        source: '/(.*)',
        headers: [
          {
            key: 'Cross-Origin-Opener-Policy',
            value: 'same-origin'
          },
          {
            key: 'Cross-Origin-Embedder-Policy',
            value: 'require-corp'
          }
        ]
      }
    ];
  }
};
```

### Trunk (Yew, Leptos)

```toml
# Trunk.toml
[serve]
headers = { "Cross-Origin-Opener-Policy" = "same-origin", "Cross-Origin-Embedder-Policy" = "require-corp" }
```

## Security Headers Reference

### Cross-Origin-Opener-Policy (COOP)

Controls window opener relationships:

| Value | Description |
|-------|-------------|
| `unsafe-none` | Default, allows opener access |
| `same-origin` | Isolates browsing context to same-origin |
| `same-origin-allow-popups` | Same-origin but allows popups |

### Cross-Origin-Embedder-Policy (COEP)

Controls resource embedding:

| Value | Description |
|-------|-------------|
| `unsafe-none` | Default, no restrictions |
| `require-corp` | Requires CORP or CORS for cross-origin resources |
| `credentialless` | Cross-origin requests without credentials |

### Cross-Origin-Resource-Policy (CORP)

Controls who can load your resources:

| Value | Description |
|-------|-------------|
| `same-site` | Only same-site requests |
| `same-origin` | Only same-origin requests |
| `cross-origin` | Allows cross-origin requests |

### X-Content-Type-Options

Prevents MIME type sniffing:

```json
{
  "X-Content-Type-Options": "nosniff"
}
```

### Permissions-Policy

Controls browser feature access:

```json
{
  "Permissions-Policy": {
    "camera": "()",
    "microphone": "()",
    "geolocation": "(self)",
    "fullscreen": "(self)"
  }
}
```

## Best Practices

1. **Configure Both Dev and Prod**: Set headers in both your framework's dev server config and `tauri.conf.json` for consistent behavior.

2. **Use Restrictive Defaults**: Start with restrictive policies and loosen only as needed.

3. **Enable COOP/COEP Together**: For `SharedArrayBuffer` support, both headers must be configured.

4. **Separate CSP Configuration**: Content-Security-Policy is configured under `app.security.csp`, not in the headers section.

5. **Avoid Tauri-Custom-Header in Production**: This header is for testing purposes only.

6. **Test Cross-Origin Scenarios**: Verify that CORS headers work correctly with your API endpoints.

## Troubleshooting

### SharedArrayBuffer Not Available

Ensure both headers are set:
```json
{
  "Cross-Origin-Opener-Policy": "same-origin",
  "Cross-Origin-Embedder-Policy": "require-corp"
}
```

### Headers Not Applied in Development

Headers in `tauri.conf.json` only apply to production builds. Configure your dev server separately.

### CORS Errors with External APIs

Add required headers for cross-origin requests:
```json
{
  "Access-Control-Allow-Methods": ["GET", "POST", "OPTIONS"],
  "Access-Control-Allow-Headers": ["Content-Type", "Authorization"]
}
```

### Custom Headers Not Visible

Expose custom headers via:
```json
{
  "Access-Control-Expose-Headers": ["X-Custom-Header", "X-Request-Id"]
}
```

## Version Requirements

- Tauri v2.1.0 or later required for HTTP headers configuration
- Headers feature is not available in earlier versions

## Related Configuration

- **CSP**: Configure under `app.security.csp` for Content Security Policy
- **Capabilities**: Use Tauri's capability system for fine-grained permissions
- **IPC Security**: Headers do not affect IPC message handling

Overview

This skill guides developers through configuring HTTP header security for Tauri v2 applications, focusing on security headers, custom headers, and CORS for webview responses. It explains allowed headers, value formats, production vs. dev behavior, and practical examples to harden cross-origin handling.

How this skill works

It describes how Tauri injects configured headers into webview HTTP responses in production builds and which headers are allowlisted. The skill explains accepted value formats (string, array, object, null), where to place settings in src-tauri/tauri.conf.json, and how to mirror those headers in development servers like Vite, Next.js, or Angular.

When to use it

  • When hardening a Tauri v2 production build with security and cross-origin policies
  • When enabling SharedArrayBuffer or other features that require COOP and COEP
  • When exposing or restricting APIs accessed by the webview (CORS configuration)
  • When ensuring consistent header behavior across dev server and production builds
  • When adding or testing custom response headers for the webview

Best practices

  • Configure headers in both your framework's dev server and tauri.conf.json to avoid environment drift
  • Start with restrictive defaults (same-origin, nosniff) and relax only as required by use cases
  • Enable Cross-Origin-Opener-Policy and Cross-Origin-Embedder-Policy together if you need SharedArrayBuffer
  • Keep Content-Security-Policy under app.security.csp, not inside the headers map
  • Avoid using the Tauri-Custom-Header in production; reserve it for testing

Example use cases

  • Lock down a desktop app to same-origin resources with COOP, COEP, and nosniff for production
  • Allow specific cross-origin API calls by configuring Access-Control-Allow-Methods and Access-Control-Allow-Headers
  • Expose custom response headers to the webview with Access-Control-Expose-Headers
  • Enable SharedArrayBuffer for WebAssembly code by setting COOP and COEP together
  • Mirror production headers during development by adding equivalent server headers in Vite or Next.js

FAQ

Do these headers apply during development?

No. Headers configured in tauri.conf.json are injected only in production builds; configure your dev server separately.

Which headers can I set?

Tauri restricts header configuration to an allowlist (CORS, COOP/COEP/CORP, X-Content-Type-Options, Permissions-Policy, Timing-Allow-Origin, Service-Worker-Allowed); Tauri-Custom-Header is for testing only.