Skip to content

fix(auth): grant asset protocol scope for cached avatars (#365) - #366

Open
ik0zy wants to merge 2 commits into
pacifio:0.4.1from
ik0zy:ik0zy/linux-avatar-asset-scope
Open

ik0zy wants to merge 2 commits into
pacifio:0.4.1from
ik0zy:ik0zy/linux-avatar-asset-scope

Conversation

@ik0zy

@ik0zy ik0zy commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

What?

Cached avatars, your own and org members', load on Linux. Each validated avatar file gets explicit asset-protocol access via app.asset_protocol_scope().allow_file(...), instead of the scope being widened.

Why?

On Linux, cached avatars live in app_config_dir() (~/.config/dev.atlas.ide/avatar-<hash>.<ext>). The configured asset scope is $HOME/**, and Tauri's Unix glob matching uses requireLiteralLeadingDot: true, so it never matches hidden directories such as ~/.config. Every avatar load fails, logging:

ERROR tauri::protocol::asset: asset protocol not configured to allow the path: /home/<user>/.config/dev.atlas.ide/avatar-7e4f2be363746b61.png

Widening the scope to hidden directories, or to the whole config dir, would expose what lives next to the avatars (the session file and credentials) to the webview. Granting one validated file at a time doesn't.

No new dependencies, no telemetry changes.

How?

All in src-tauri/src/commands/auth.rs:

  • Where grants happen: broadcast (launch restore, revalidation, sign-in, org changes), auth_snapshot (initial frontend hydration) and auth_list_members (org roster avatars).

  • What gets granted: resolve_avatar_grant_path only grants a file that:

    • is an absolute path with an avatar- name and an image extension (png, jpg, jpeg, webp, gif), and
    • resolves (symlinks followed, via dunce::canonicalize) to a regular file directly inside the avatar cache dir, still with an avatar- name and an image extension.

    The second rule closes a symlink bypass Copilot flagged on an earlier revision: a link named avatar-x.png pointing at a credential file passed the name checks, and would have had its target granted. AuthState now keeps the config dir it hands AuthCore (where the avatar cache lives), so the check compares against the real cache dir. Both sides are canonicalized, so a symlinked ~/.config doesn't break it.

  • Why this is safe with Tauri (checked against 2.11.1):

    • Scope::is_allowed canonicalizes the requested path before matching, so swapping a granted file for a symlink later doesn't extend access.
    • Allowed patterns are a HashSet, so re-granting on every snapshot or broadcast doesn't pile up duplicates.
  • macOS: unaffected. The avatar cache there is already inside $HOME/**, so the grant is a no-op.

Tests (#[cfg(test)] in auth.rs):

  • resolve_avatar_grant_path_validates_path: valid avatar accepted; relative path, missing file, wrong prefix, non-image extension, directory, and an avatar-named file outside the cache dir all rejected.
  • resolve_avatar_grant_path_rejects_symlink_escape (unix): an avatar-*.png symlink to a file outside the cache dir, and one to a non-avatar file inside it, are both rejected.

Verification: oxlint, oxfmt --check, cargo fmt --check, bun run typecheck, bun run test:contracts (248/248) and bun run test src/features/auth all passed on the first revision. rustfmt passes on the current file. The Rust tests run in CI's macOS app job.

The only failing check, app (src-tauri, Windows), also fails on 0.4.0 itself and is unrelated to this change. #367 fixes it.

Fixes #365

Checklist

  • Targets the current version branch, unless it's a small standalone fix
  • New behaviour has a test; a bug fix has a test that fails without it
  • You've run the app and used the change in a window (Linux 0.4.1 build with this PR: own + member avatars load, no asset-protocol errors)

Copilot AI lite review requested due to automatic review settings October 5, 2026 08:02

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

Reject symlinks or verify canonical paths remain within the avatar cache before granting access.

Review effort: Lite
Findings: 1 High severity

Open (1)
What changed in this PR

Fixes Linux cached-avatar loading by granting explicit Tauri asset-protocol access to validated avatar files.

Changes:

  • Adds avatar path validation and canonicalization tests.
  • Grants avatar access during snapshots, broadcasts, and member listing.
  • Avoids broad hidden-directory scope expansion.
File Description
src-tauri/​src/​commands/​auth.rs Implements avatar scope grants and validation tests.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src-tauri/src/commands/auth.rs

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot review overview

🟢 Approval recommended

No unresolved review issues were identified.

Review effort: Lite
Findings: None

Resolved since last review (1)

@ik0zy
ik0zy force-pushed the ik0zy/linux-avatar-asset-scope branch from 643a279 to 6490ea9 Compare October 7, 2026 03:33
@coderabbitai

coderabbitai Bot commented Oct 7, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration
  • Configuration used: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: c9efef93-eff2-43cf-a0c8-389d338f813e

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot review overview

🟢 Approval recommended

No unresolved blocking issues were identified.

Review effort: Lite
Findings: None

ik0zy added 2 commits October 8, 2026 18:27
On Linux, cached profile avatars are stored in app_config_dir()
(~/.config/dev.atlas.ide/avatar-<hash>.<ext>). Because Tauri's Unix
glob matcher sets requireLiteralLeadingDot: true, the $HOME/** asset
protocol scope skips dot-directories such as ~/.config. This resulted in
Tauri asset protocol errors ("asset protocol not configured to allow the path")
and silently caused avatars to fall back to initials.

Rather than broadly opening hidden directories, this explicitly grants
access to the specific avatar files via allow_file upon auth broadcast,
initial auth_snapshot, and auth_list_members.
dunce::canonicalize resolved a symlink like avatar-evil.png ->
~/.config/dev.atlas.ide/auth-token.json to the secret, and the webview was
then granted asset-protocol read access to it. The prefix/extension checks
only constrained the symlink's name, not its target.

resolve_avatar_grant_path now also canonicalizes the avatar cache dir and
requires the resolved file to be a regular file directly inside it (with an
avatar-shaped name/extension), plus add symlink-guard tests.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants