Skip to content

fix: harden tauri local access and stabilize task lifecycle#50

Merged
ShellMonster merged 3 commits intomainfrom
fix/tauri-safety-timeout-ratio
Mar 5, 2026
Merged

fix: harden tauri local access and stabilize task lifecycle#50
ShellMonster merged 3 commits intomainfrom
fix/tauri-safety-timeout-ratio

Conversation

@ShellMonster
Copy link
Copy Markdown
Owner

@ShellMonster ShellMonster commented Mar 5, 2026

User description

Summary

  • Harden desktop security only in Tauri mode: strict CORS origin allowlist + local refPaths directory validation.
  • Fix stale migration pagination to avoid skipped records.
  • Improve worker pool shutdown order so in-flight tasks are canceled quickly on app exit.
  • Unify generate-area ratio fallback with history formatter to avoid odd ratios like 79:53.

Validation

  • cd backend && go test ./...
  • npm --prefix desktop run type-check

Notes

  • Docker behavior remains unchanged for CORS/refPaths strict checks (strict path validation applies only in Tauri mode).

CodeAnt-AI Description

Harden Tauri desktop access, stabilize task lifecycle, and normalize image aspect labels

What Changed

  • Desktop sidecar now rejects non-allowed web origins when running in Tauri mode; requests from tauri:// and loopback hosts are permitted, others receive a 403 response.
  • Local reference image paths provided from the desktop app are validated and must reside in allowed app directories (config, cache, or temp); invalid paths return a 400 error.
  • Worker shutdown now cancels ongoing provider calls first and prevents new tasks from being accepted during shutdown, so the app exits faster and stops long-running in-flight operations sooner.
  • Migration of old tasks to month folders processes remaining unclassified tasks in ordered batches (avoids skipping records) and reports accurate progress counts.
  • Image aspect ratio labels shown in the desktop UI use a shared normalization routine for consistent, human-friendly labels instead of raw width:height values.

Impact

✅ Block unauthorized local origins in desktop mode
✅ Fewer missed migration records during upgrades
✅ Faster app exit when tasks are running

💡 Usage Guide

Checking Your Pull Request

Every time you make a pull request, our system automatically looks through it. We check for security issues, mistakes in how you're setting up your infrastructure, and common code problems. We do this to make sure your changes are solid and won't cause any trouble later.

Talking to CodeAnt AI

Got a question or need a hand with something in your pull request? You can easily get in touch with CodeAnt AI right here. Just type the following in a comment on your pull request, and replace "Your question here" with whatever you want to ask:

@codeant-ai ask: Your question here

This lets you have a chat with CodeAnt AI about your pull request, making it easier to understand and improve your code.

Example

@codeant-ai ask: Can you suggest a safer alternative to storing this secret?

Preserve Org Learnings with CodeAnt

You can record team preferences so CodeAnt AI applies them in future reviews. Reply directly to the specific CodeAnt AI suggestion (in the same thread) and replace "Your feedback here" with your input:

@codeant-ai: Your feedback here

This helps CodeAnt AI learn and adapt to your team's coding style and standards.

Example

@codeant-ai: Do not flag unused imports.

Retrigger review

Ask CodeAnt AI to review the PR again, by typing:

@codeant-ai: review

Check Your Repository Health

To analyze the health of your code repository, visit our dashboard at https://app.codeant.ai. This tool helps you identify potential issues and areas for improvement in your codebase, ensuring your repository maintains high standards of code health.

@codeant-ai
Copy link
Copy Markdown

codeant-ai bot commented Mar 5, 2026

CodeAnt AI is reviewing your PR.

@gemini-code-assist
Copy link
Copy Markdown

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request focuses on bolstering the application's security posture in its Tauri desktop environment, enhancing the reliability of background data migration, and refining the task management lifecycle. It also brings consistency to how image aspect ratios are presented, ensuring a more uniform user experience.

Highlights

  • Enhanced Tauri Security: Implemented strict CORS origin allowlisting and local reference path directory validation specifically for Tauri desktop mode to prevent unauthorized access.
  • Migration Stability Fix: Corrected a pagination issue in the task migration process to ensure no records are skipped, improving data integrity.
  • Improved Worker Pool Shutdown: Optimized the worker pool shutdown sequence to prioritize context cancellation, ensuring in-flight tasks are terminated more quickly upon application exit.
  • Unified Aspect Ratio Formatting: Standardized the aspect ratio calculation and display logic across the application to avoid inconsistent or 'odd' ratios.
Changelog
  • backend/cmd/server/main.go
    • Imported 'net/url' for URL parsing.
    • Added 'isTauriSidecar', 'isLoopbackOrigin', and 'isAllowedTauriOrigin' functions to detect Tauri mode and validate allowed origins.
    • Modified CORS middleware to apply strict origin validation only when running as a Tauri sidecar.
  • backend/internal/api/handlers.go
    • Introduced 'isTauriSidecarMode' to check for Tauri environment.
    • Added path validation utilities: 'normalizePathForCheck', 'pathWithinRoot', 'allowedRefPathRoots', and 'validateRefPathForTauri'.
    • Integrated 'validateRefPathForTauri' into 'GenerateWithImagesHandler' to ensure local reference image paths are within allowed directories in Tauri mode.
  • backend/internal/model/db.go
    • Replaced 'offset' with 'processed' variable for tracking migration progress.
    • Added 'Order("id ASC")' to the database query for task migration to ensure consistent ordering and prevent skipped records when items are updated during pagination.
  • backend/internal/worker/pool.go
    • Imported 'sync/atomic' for atomic operations.
    • Added an 'atomic.Int32' field 'stopping' to 'WorkerPool' to signal shutdown state.
    • Refactored 'Stop' method to first cancel the context, then close the task queue, and finally wait for workers, ensuring faster termination of in-flight tasks.
    • Modified 'Submit' method to prevent new tasks from being submitted if the worker pool is in the process of stopping.
  • desktop/src/components/GenerateArea/ImageCard.tsx
    • Imported 'formatAspectRatioLabel' from '../../utils/aspectRatio'.
    • Replaced the custom aspect ratio calculation logic with the 'formatAspectRatioLabel' utility function for consistency.
Activity
  • No specific activity (comments, reviews, progress updates) has been recorded for this pull request yet.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@codeant-ai codeant-ai bot added the size:L This PR changes 100-499 lines, ignoring generated files label Mar 5, 2026
@codeant-ai
Copy link
Copy Markdown

codeant-ai bot commented Mar 5, 2026

Nitpicks 🔍

🔒 No security issues identified
⚡ Recommended areas for review

  • CORS Allowlist
    isAllowedTauriOrigin treats an empty Origin as allowed (returns true). In Tauri middleware the code accepts empty origin as allowed and does not set Access-Control-Allow-Origin — this combination may unintentionally relax origin checks or create inconsistent CORS behavior. Validate intent for empty Origin and consider stricter handling (e.g., disallow empty origin or treat "null" specially).

  • Middleware Logic
    Middleware branch for Tauri vs non-Tauri sets different Access-Control-Allow-Origin behavior. Confirm that returning 403 for disallowed origins and not setting wildcard header in Tauri mode matches expected desktop vs Docker behavior. Ensure no case where origin is "null" or malformed bypasses checks.

  • Stop Ordering / Task Loss Risk
    Stop() now cancels wp.ctx before closing the task queue; worker loop exits on ctx.Done, so queued tasks may be abandoned (not drained). This may result in dropped tasks and inconsistent "all tasks processed" log. Consider reordering or changing worker loop to drain queue even when ctx is canceled.

  • Local Path Validation
    validateRefPathForTauri allows paths under allowed roots (user config, cache, temp). Confirm these roots are exhaustive and safe on all platforms. Path normalization and symlink resolution are used; double-check Windows drive-letter and case-sensitivity interactions and whether additional roots (workDir) are needed for some deployments.

  • RefPath Read Behavior
    When Tauri path validation fails the handler returns 400; when ReadFile fails it only logs and continues. Confirm that skipping unreadable local refpaths is intended and doesn't silently hide user errors. Also consider whether permission errors should return a visible error instead of continuing.

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces important security hardening for the Tauri desktop application by implementing a strict CORS policy and validating local file paths to prevent directory traversal attacks. It also includes a critical fix for a pagination issue in the database migration logic and improves the worker pool shutdown sequence for faster and more reliable application exit, along with refactoring to unify aspect ratio formatting. However, it's crucial to note that the introduced security protections are explicitly bypassed when the application is not running in Tauri mode, leaving it vulnerable to authenticated CORS attacks and arbitrary file reads via path traversal in non-Tauri environments. Additionally, there are suggestions to improve code maintainability by reducing duplication and simplifying logic.

Comment on lines +488 to +498
targetPath := path
if isTauriSidecarMode() {
validatedPath, validateErr := validateRefPathForTauri(path)
if validateErr != nil {
log.Printf("[API] 非法本地参考图路径: %s, err: %v\n", path, validateErr)
Error(c, http.StatusBadRequest, 400, "参考图路径不在允许目录内")
return
}
targetPath = validatedPath
}
content, err := os.ReadFile(targetPath)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-critical critical

The GenerateWithImagesHandler function allows reading arbitrary files from the server's file system when not running in Tauri mode. The path parameter from the request is used directly in os.ReadFile without any validation or sanitization. An attacker can exploit this to read sensitive files such as configuration files, credentials, or system files. While validation was added for Tauri mode, other modes (like Docker) remain unprotected. Strict path validation should be implemented for all environments.

Comment on lines +180 to +181
if origin != "" {
c.Writer.Header().Set("Access-Control-Allow-Origin", origin)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-high high

The application reflects the Origin header directly into the Access-Control-Allow-Origin response header when not running in Tauri mode. Combined with Access-Control-Allow-Credentials: true (line 187), this configuration allows any malicious website to make authenticated cross-origin requests to the backend API, leading to unauthorized data access or actions. It is recommended to use a strict allowlist of origins instead of reflecting the Origin header. Additionally, the logic in this else block for handling non-Tauri environments can be simplified to improve readability and reduce nesting.

Comment on lines +127 to +129
func isTauriSidecarMode() bool {
return os.Getenv("TAURI_PLATFORM") != "" || os.Getenv("TAURI_FAMILY") != ""
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The function isTauriSidecarMode is a duplicate of the isTauriSidecar function in backend/cmd/server/main.go. This introduces code duplication, which can make future maintenance more difficult.

To avoid duplication, this function should be moved to a shared utility package (e.g., internal/util or internal/platform) and be called from both main.go and handlers.go.

References
  1. Avoid duplicated code in the codebase; it should be abstracted into reusable functions or components. (link)

@codeant-ai
Copy link
Copy Markdown

codeant-ai bot commented Mar 5, 2026

CodeAnt AI finished reviewing your PR.

@ShellMonster
Copy link
Copy Markdown
Owner Author

已根据本轮 CodeReview 补充修复并推送 f150c91,处理点如下:

  1. 安全:refPaths 现在仅允许 Tauri 模式使用;非 Tauri 请求会直接返回 400,避免任意文件读取。
  2. 安全:非 Tauri CORS 不再使用 "Origin 反射 + Credentials=true" 组合。
    • 默认(未配置 allowlist):Access-Control-Allow-Origin: * 且不允许 credentials。
    • 如需凭证跨域:可通过 CORS_ALLOW_ORIGINS 显式白名单。
  3. 安全:Tauri 模式下对空 Origin / null Origin 直接拒绝。
  4. 稳定性:Worker 收到停止信号后会额外 drain 队列并把遗留任务标记失败,避免“任务丢失但状态不一致”。
  5. 维护性:抽出 internal/platform.IsTauriSidecar(),去掉重复实现。

本地验证:

  • cd backend && go test ./...
  • npm --prefix desktop run type-check
    均通过。

@ShellMonster
Copy link
Copy Markdown
Owner Author

/gemini review

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This PR significantly strengthens security for Tauri desktop applications, particularly in CORS handling and local file access validation, and also optimizes worker pool shutdown logic and fixes a database migration bug. However, the CORS implementation contains two significant issues: a loose prefix check for Tauri origins and an insecure handling of wildcard allowlists that allows reflected origins with credentials. These issues could allow unauthorized cross-origin or cross-app access to the backend API. Additionally, while overall code quality is high, there are areas for improvement in code clarity and security.

Comment on lines +223 to +225
} else if originInAllowlist(trimmedOrigin, corsAllowlist) {
c.Writer.Header().Set("Access-Control-Allow-Origin", trimmedOrigin)
c.Writer.Header().Set("Access-Control-Allow-Credentials", "true")
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-high high

The CORS implementation incorrectly handles the wildcard (*) in the CORS_ALLOW_ORIGINS allowlist. If the allowlist contains *, the originInAllowlist function returns true for any origin, which is then reflected in the Access-Control-Allow-Origin header with Access-Control-Allow-Credentials set to true. This effectively bypasses browser security, allowing malicious websites to make authenticated requests if the allowlist is misconfigured with a wildcard. The logic should be updated to ensure that if a wildcard is used, credentials are not permitted, or the origin is not reflected unless it matches a specific trusted domain. Furthermore, the non-Tauri mode logic in this CORS middleware is complex and repetitive, especially where if trimmedOrigin == "" and else if len(corsAllowlist) == 0 branches perform the same c.Writer.Header().Set("Access-Control-Allow-Origin", "*") operation. Reorganizing this logic to prioritize invalid origins and then handle corsAllowlist presence separately would improve clarity and maintainability.

Comment on lines +184 to +187
real := abs
if resolved, err := filepath.EvalSymlinks(abs); err == nil && strings.TrimSpace(resolved) != "" {
real = filepath.Clean(resolved)
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

validateRefPathForTauri 函数中,静默忽略 filepath.EvalSymlinks 的错误存在安全隐患。

当前逻辑是:如果 EvalSymlinks 执行失败,代码会回退到检查未经符号链接解析的原始路径 (abs)。如果这个原始路径本身是一个指向允许目录之外的符号链接,os.ReadFile 在后续操作中仍然会跟随这个链接,从而绕过了路径限制,导致潜在的目录遍历漏洞。

例如,攻击者可以创建一个符号链接 /app/tmp/malicious_link 指向 /etc/passwd。如果由于某些原因(如权限问题)EvalSymlinks 失败,验证逻辑会检查 /app/tmp/malicious_link 本身,发现它在允许的 /app/tmp 目录内,从而错误地通过验证。但随后的 os.ReadFile 会读取到 /etc/passwd 的内容。

为了修复此漏洞,当 filepath.EvalSymlinks 返回错误时,应该直接拒绝该路径。

	real, err := filepath.EvalSymlinks(abs)
	if err != nil {
		// 如果符号链接解析失败,出于安全考虑应直接拒绝。
		// 失败可能意味着链接损坏,或存在权限问题,这可能掩盖恶意路径。
		return "", fmt.Errorf("ref path could not be resolved: %w", err)
	}
	real = filepath.Clean(real)
References
  1. 规范 feat: integrate folder features into HistoryPanel (Phase 4) #29 “本地路径读取需防止路径遍历攻击 (验证路径合法性)”。当前实现虽然尝试进行验证,但存在漏洞,未能完全防止路径遍历攻击。 (link)

Comment on lines +61 to +63
if strings.HasPrefix(strings.ToLower(origin), "tauri://") {
return true
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-medium medium

The isAllowedTauriOrigin function uses a loose prefix check (strings.HasPrefix(strings.ToLower(origin), "tauri://")) to validate the Origin header in Tauri mode. This allows any origin starting with tauri:// to pass validation. When validation passes, the server reflects the origin in the Access-Control-Allow-Origin header and sets Access-Control-Allow-Credentials to true. This allows any application on the system that can use the tauri:// scheme (such as another malicious Tauri app) to make authenticated requests to the backend API. It is recommended to strictly validate the origin against a known, trusted value (e.g., tauri://localhost).

@ShellMonster
Copy link
Copy Markdown
Owner Author

已继续处理 Gemini 最新一轮 review,并推送 4901ed6

  1. Tauri Origin 校验收紧:

    • 不再使用 HasPrefix("tauri://"),改为 URL 解析后严格校验 scheme=taurihost=localhost
    • 空 origin / null origin 均拒绝。
  2. 非 Tauri 的 CORS * 处理修正:

    • CORS_ALLOW_ORIGINS* 时,统一返回 Access-Control-Allow-Origin: *,不再反射 origin,也不设置 credentials。
    • 仅在明确匹配具体白名单 origin 时才返回该 origin 并允许 credentials。
  3. 本地路径解析加强:

    • validateRefPathForTauriEvalSymlinks 失败改为直接拒绝,避免符号链接绕过校验。

本地验证已通过:

  • cd backend && go test ./...
  • npm --prefix desktop run type-check

@ShellMonster ShellMonster merged commit cdd9c18 into main Mar 5, 2026
5 checks passed
@ShellMonster ShellMonster deleted the fix/tauri-safety-timeout-ratio branch March 5, 2026 08:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L This PR changes 100-499 lines, ignoring generated files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant