Skip to content

Add assistant files and links view#690

Merged
yewreeka merged 13 commits intodevfrom
jarod/assistant-files-links
Apr 14, 2026
Merged

Add assistant files and links view#690
yewreeka merged 13 commits intodevfrom
jarod/assistant-files-links

Conversation

@yewreeka
Copy link
Copy Markdown
Contributor

@yewreeka yewreeka commented Apr 11, 2026

Summary

  • add a Files & Links row to Conversation Info when a verified assistant is present
  • add a Files & Links screen with tabs for assistant-shared files and links plus search
  • reuse shared UIKit Quick Look presentation for file previews from both the messages list and the new assistant file list

Details

  • queries assistant-sent attachments and link previews from the conversation database
  • parses both inline file:// attachment keys and remote attachment JSON for filenames and mime types
  • file rows now open Quick Look instead of showing a download affordance
  • link rows use the Safari icon

Testing

  • xcodebuild build -project Convos.xcodeproj -scheme "Convos (Dev)" -destination "platform=iOS Simulator,name=convos-jarod-assistant-files-links" -derivedDataPath .derivedData
  • swiftlint on changed files

Note

Add assistant files and links view to conversation info screen

  • Adds AssistantFilesLinksView, a new screen where users can browse, search, and open assistant-managed files (via Quick Look) and links (via system browser), accessible from the Conversation Info screen when the conversation has ever had a verified assistant.
  • Introduces AssistantFilesLinksRepository to fetch assistant files and links from the database by querying stored messages for a given conversation.
  • Tracks whether a conversation has ever had a verified assistant via a new hasHadVerifiedAssistant boolean column on the conversation table, set to true by ConversationWriter, StreamProcessor, InviteJoinRequestsManager, and the NSE messaging service when a verified Convos Assistant is detected.
  • Refactors file attachment preview in MessagesViewController to use a new FileAttachmentPreviewLoader + QuickLookSheetPresenter, replacing the previous in-controller QLPreviewController data source/delegate approach.
  • Risk: adds a new database migration (addHasHadVerifiedAssistantToConversation); existing conversations default to false and are only upgraded when agent verification runs.

Macroscope summarized a9636f3.

@claude
Copy link
Copy Markdown

claude bot commented Apr 11, 2026

Claude finished @yewreeka's task —— View job


Code Review Complete ✅

I've completed a thorough review of PR #690. Overall, this is a well-structured feature addition with clean separation of concerns. Below are my findings:


Code Quality & Best Practices ✅

Strengths:

  • Clean architecture: Proper separation between View (SwiftUI), ViewModel (@Observable), and Repository (database layer)
  • SwiftUI best practices: Correct use of @State, @Observable, button action extraction pattern followed
  • Dependency injection: Repository is injected via makeAssistantFilesLinksRepository()
  • Error handling: Proper async/await with try/catch, user-facing error messages
  • Naming conventions: Follows project patterns (AssistantFilesLinksView, AssistantFilesLinksRepository)
  • Code style: No force unwraps, no assertions, proper optional handling with guard let

Minor Issues:

  1. AssistantFilesLinksRepository.swift:154 - Empty filename handling: When lastPathComponent ends with underscore (e.g., file:///path/prefix_), filename becomes empty string. While displayName falls back to "Untitled" for nil, it doesn't handle empty strings.

    // Current:
    filename = candidate.isEmpty ? name : candidate
    // Better:
    filename = !candidate.isEmpty ? candidate : name
  2. FileAttachmentQuickLook.swift:68 - File cleanup happens on dismiss, but if the user never dismisses (app termination), temp files persist in /tmp/preview_*. Consider using defer or cleanup on next app launch.

  3. AssistantFilesLinksView.swift:223 - Using UIImage(data:) directly in SwiftUI could cause issues on macOS if ConvosCore needs cross-platform support. However, this is in the main app target, so it's acceptable.


Potential Bugs 🐛

Medium Priority:

  1. AssistantFilesLinksView.swift:159-174 - FileAttachmentPreviewLoader.loadPreviewURL can throw, but the error is caught and shown as generic "file unavailable". Loss of file-specific error context could make debugging harder.

    • Recommendation: Log the specific error type/message for better diagnostics
  2. FileAttachmentQuickLook.swift:68 - Deleting entire temporary directory fileURL.deletingLastPathComponent() is risky if multiple previews share the same parent directory. Race condition if two files from different messages are opened simultaneously.

    • Recommendation: Only delete the specific file, not the parent directory

Low Priority:
3. AssistantFilesLinksRepository.swift:79 - JSON decoding failure in compactMap silently discards invalid attachment data. This might hide data corruption issues.

  • Recommendation: Log failed decode attempts at debug level
  1. ConversationInfoView.swift:98 - hasEverHadVerifiedAssistant check gates the entire assistant section. If the flag is incorrectly set to false, users lose access even if assistant is currently present.
    • Mitigation: The flag is set in multiple places (StreamProcessor, MessagingService, AgentVerificationWriter), providing redundancy

Performance Considerations ⚡

Good:

  • ✅ Uses LazyVStack for lists (efficient memory usage)
  • ✅ Database queries use indexed columns (conversationId, senderId, contentType)
  • AsyncImage handles image loading automatically
  • ✅ Repository uses DatabaseReader (read-only access, allows concurrent reads)

Potential Optimizations:

  1. AssistantFilesLinksRepository.swift:58-94 - fetchFiles() and fetchLinks() run two separate SQL queries. Could be combined into a single query with UNION for better performance if the list grows large.

    • Current: 2 round trips to database
    • Not urgent: Current approach is more maintainable and readable
  2. AssistantFilesLinksView.swift:26-39 - Filtering happens in-memory on every searchText change. For large datasets (1000+ items), consider debouncing or database-level filtering.

    • Current: Simple .contains() is fine for typical usage

Security Considerations 🔒

Good:

  • ✅ No SQL injection risk (uses GRDB parameterized queries)
  • ✅ File access is scoped to attachment keys (no arbitrary path injection)
  • ✅ Proper validation of assistant sender (memberKind IN ('agent:convos', 'agent:user-oauth'))
  • ✅ Temp file creation uses UUID for uniqueness

Potential Issues:

  1. FileAttachmentPreviewLoader.swift:80-94 - file:// URLs are constructed from attachment keys. If attachment keys can be manipulated (e.g., via malicious messages), this could potentially access arbitrary files.

    • Mitigation: Keys are stored from XMTP messages, which are cryptographically signed. Risk is low.
  2. AssistantFilesLinksView.swift:239 - UIApplication.shared.open(url) opens URLs without validation. Malicious link previews could open file://, javascript:, or other dangerous schemes.

    • Recommendation: Validate URL scheme before opening (whitelist http, https)
    if let url = link.resolvedURL, ["http", "https"].contains(url.scheme?.lowercased()) {
        UIApplication.shared.open(url)
    }

Test Coverage 📊

Coverage Analysis:

  • AssistantFilesLinksRepository has database integration (covered by SharedDatabaseMigrator migration test)
  • hasHadVerifiedAssistant flag is tested in multiple integration tests (AgentVerificationWriter, StreamProcessor)
  • No unit tests for AssistantFilesLinksRepository (file/link fetching logic)
  • No UI tests for AssistantFilesLinksView (search, tab switching, file preview)

Recommendations:

  1. Add unit tests for parseAttachmentKey() edge cases:
    • Empty strings, malformed JSON, missing fields
    • file:// URLs with/without underscores
    • RemoteAttachment JSON parsing
  2. Add integration test for fetchFiles()/fetchLinks():
    • Verify only assistant-sent messages are included
    • Test ordering (DESC by date)
    • Test with empty results
  3. Consider UI test for end-to-end flow:
    • Navigate from ConversationInfoView → AssistantFilesLinksView
    • Verify search filtering works
    • Test file preview opens correctly

Test Infrastructure:

  • Migration addHasHadVerifiedAssistantToConversation is in place (line 354-358 of SharedDatabaseMigrator.swift)
  • No breaking schema changes detected

Database Migration ✅

Migration Review:

migrator.registerMigration("addHasHadVerifiedAssistantToConversation") { db in
    try db.alter(table: "conversation") { t in
        t.add(column: "hasHadVerifiedAssistant", .boolean).notNull().defaults(to: false)
    }
}
  • ✅ Safe migration (adds non-null column with default value)
  • ✅ No data loss
  • ✅ Backward compatible (defaults to false)
  • ✅ Flag is set progressively via StreamProcessor, push notification handling, and agent verification

Adherence to Project Conventions ✅

CLAUDE.md Compliance:

  • ✅ Uses @Observable instead of ObservableObject
  • ✅ Button actions extracted to avoid closure compilation errors
  • ✅ No force unwrapping (!)
  • ✅ No implicitly unwrapped optionals
  • ✅ No assertions in non-test code
  • ✅ Prefers guard over if for early returns
  • first(where:) used over .filter().first
  • ✅ No trailing whitespace
  • ✅ No step-count comments
  • ✅ Uses descriptive names (AssistantFilesLinksViewModel, AssistantFile)
  • ✅ Follows SwiftLint modifier order

File Organization:

  • ✅ Views in main app target (Convos/Conversation Detail/)
  • ✅ Repository and models in ConvosCore
  • ✅ Proper dependency injection

Summary & Recommendations

Overall Assessment: This is a high-quality PR with clean separation of concerns and good error handling. The implementation follows project conventions and introduces no breaking changes.

Required Changes (Security):

  1. Validate URL schemes in AssistantFilesLinksView.swift:239 before opening links

Recommended Improvements:

  1. Handle empty filename edge case in parseAttachmentKey()
  2. Delete only the specific temp file, not parent directory, in QuickLook cleanup
  3. Add unit tests for AssistantFilesLinksRepository
  4. Log specific error types in file preview failures for better debugging

Nice-to-Have:

  1. Debounce search input for large datasets
  2. Consider UNION query to reduce database round trips
  3. Add integration tests for assistant file/link filtering logic

Comment thread ConvosCore/Sources/ConvosCore/Inboxes/MockInboxesService.swift Outdated
@macroscopeapp
Copy link
Copy Markdown
Contributor

macroscopeapp bot commented Apr 11, 2026

Approvability

Verdict: Needs human review

2 blocking correctness issues found. This PR introduces a new feature with substantial scope: new UI views, a database schema migration adding hasHadVerifiedAssistant, and changes propagating through multiple data layer files. Additionally, unresolved review comments include a high-severity timing issue and a medium-severity bash compatibility problem that could block commits.

You can customize Macroscope's approvability policy. Learn more.

@yewreeka yewreeka force-pushed the jarod/assistant-files-links branch from 1db6284 to ec11803 Compare April 13, 2026 17:00
yewreeka and others added 13 commits April 14, 2026 13:15
Shows a 'Files & Links' row in Conversation Info when a verified
assistant is present. Tapping navigates to a new view with:
- Segmented picker to switch between Files and Links tabs
- Search to filter by filename or URL
- File rows with thumbnail, name, and date
- Link rows with OG image, title, and domain

New files:
- AssistantFilesLinksRepository: queries messages by agent senders
  filtered to attachments and linkPreview content types
- AssistantFilesLinksView: SwiftUI view with tabs, search, and lists
Attachment keys in the database can be either StoredRemoteAttachment
JSON blobs (for remote uploads) or file:// URLs (for inline
attachments sent via CLI). The previous code only tried JSON parsing,
which failed silently for file:// URLs, causing all inline attachments
to show as 'Untitled' with no type icon.

Now uses the same parsing logic as MessagesRepository.hydrateAttachment:
parses filename from the file:// path (splitting on underscore) and
derives mimeType from the file extension via UTType.
Replace the download affordance in Files & Links with the same file
preview flow used when tapping a file attachment in the message list.
Rows now open QuickLook after loading inline or remote attachment data,
show a chevron instead of the iCloud download icon, and display file
extension + date in the subtitle.
Stop presenting file previews via a SwiftUI sheet and instead reuse a
shared UIKit QuickLook presenter that presents from the top-most view
controller. This matches the message-list attachment preview host more
closely and removes the modal sheet wrapper from the Files & Links
screen.
Wrap QLPreviewController in a shared SwiftUI representable and present it
through a hosting controller from both the messages list and the assistant
Files & Links view. This unifies the preview implementation while still
loading inline and remote files through the same helper.
Drop the shared SwiftUI sheet host and move both the messages-list and
assistant Files & Links entry points to a shared UIKit presenter that
creates and presents QLPreviewController directly. This restores
consistent Quick Look toolbar behavior across both flows while keeping
file loading shared.
… filters

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Add markdown attachment preview sheet with WKWebView rendering

When tapping a markdown file attachment (.md, .markdown), show a
native sheet with rendered markdown instead of the QuickLook file
preview. Uses marked.js (bundled) to convert markdown to HTML and
renders in a WKWebView with system-matching styles.

Features:
- Headings, lists, code blocks, blockquotes, tables
- Remote images load inline
- Links rendered as tappable blue text
- Dark mode support via CSS color-scheme
- Share button to copy file or open in Files app
- Sheet with medium/large detents and grabber
- Falls back to QuickLook for non-markdown files

* Fix lint violations and security issues in markdown preview

- Remove unused markdownPreviewController property (UIKit retains
  presented controllers)
- Fix XSS vulnerability: use base64-encoded markdown passed to JS
  instead of template literal string escaping
- Add Content-Security-Policy header restricting scripts and images
- Handle missing marked.js bundle with user-visible error instead
  of silent failure
- Fix SwiftLint implicit_optional_initialization violations

* Fix XSS vulnerability and add unit tests for isMarkdownFile

Security:
- Move base64-encoded markdown to a data-markdown attribute on the
  body element instead of interpolating inside a script tag. This
  prevents script context injection (e.g. </script> payloads) by
  keeping user content entirely out of JavaScript source.

Tests:
- Add 10 unit tests for HydratedAttachment.isMarkdownFile covering
  .md/.markdown extensions, case insensitivity, text/markdown and
  text/x-markdown MIME types, non-markdown files, nil values, and
  extension-over-MIME priority.

* Add file attachment cache for instant repeat previews

Introduce FileAttachmentCache (actor, in ConvosCore) that persists
downloaded file attachment data in Caches/FileAttachments/ keyed by
a SHA-256 hash of the attachment key. This mirrors how ImageCache
handles image attachments.

Before: every tap on a file attachment re-fetched data from the
network or inline recovery, wrote to a random temp path, and
deleted it on sheet dismiss.

After: first tap fetches and caches; subsequent taps return the
cached file URL instantly. Files are stored in Caches/ so iOS can
evict under storage pressure.

Also adds 5 unit tests for FileAttachmentCache.

* Use X close button and hide drag indicator on markdown sheet

* Harden markdown preview against XSS and injection attacks

- Strip raw HTML blocks from markdown via custom marked renderer
  that returns empty string for html tokens
- Sanitize rendered DOM: remove script, iframe, object, embed,
  form, and input elements after parsing
- Strip inline event handlers (onload, onerror, onclick, etc.)
- Remove javascript: URLs from anchor hrefs
- Restrict CSP img-src to data: only (block remote image loading
  which enables tracking pixels and information disclosure)
- Add WKNavigationDelegate to intercept link taps and open them
  in Safari instead of navigating inside the WKWebView

* Fix path traversal vulnerability in FileAttachmentCache

Sanitize filenames in all public entry points by extracting
lastPathComponent and replacing '..' sequences. A malicious
filename like '../../../etc/passwd' is now resolved to 'passwd'
within the cache subdirectory.

All file operations now go through resolvedFileURL() which
applies sanitization before constructing the path.

Adds test covering path traversal, dot-dot prefix, and empty
filename cases.

* Use @Environment dismiss and standard Done button for markdown sheet

* Fix review issues: wildcard sanitization, async I/O, reload guard, button extraction

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Wrap QLPreviewController in a shared SwiftUI representable and present it
through a hosting controller from both the messages list and the assistant
Files & Links view. This unifies the preview implementation while still
loading inline and remote files through the same helper.
@yewreeka yewreeka force-pushed the jarod/assistant-files-links branch from 95c70ab to a9636f3 Compare April 14, 2026 20:17
@yewreeka yewreeka merged commit 9bba7af into dev Apr 14, 2026
6 of 7 checks passed
@yewreeka yewreeka deleted the jarod/assistant-files-links branch April 14, 2026 20:17
}

if key.hasPrefix("file://") {
let url = URL(string: key) ?? URL(fileURLWithPath: String(key.dropFirst(7)))
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟢 Low Repositories/AssistantFilesLinksRepository.swift:150

In parseAttachmentKey, when a file:// URL has two slashes instead of three (e.g., file://path/to/file vs file:///path/to/file), URL(string: key) succeeds but parses path as the host, leaving lastPathComponent empty or /. The filename is then extracted incorrectly or becomes empty. Consider validating the URL structure or using fileURL(withPath:) as the primary parser for file:// schemes.

-        if key.hasPrefix("file://") {
-            let url = URL(string: key) ?? URL(fileURLWithPath: String(key.dropFirst(7)))
+        if key.hasPrefix("file://") {
+            let url = URL(fileURLWithPath: String(key.dropFirst(7)))
🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file ConvosCore/Sources/ConvosCore/Storage/Repositories/AssistantFilesLinksRepository.swift around line 150:

In `parseAttachmentKey`, when a `file://` URL has two slashes instead of three (e.g., `file://path/to/file` vs `file:///path/to/file`), `URL(string: key)` succeeds but parses `path` as the host, leaving `lastPathComponent` empty or `/`. The filename is then extracted incorrectly or becomes empty. Consider validating the URL structure or using `fileURL(withPath:)` as the primary parser for `file://` schemes.

Evidence trail:
ConvosCore/Sources/ConvosCore/Storage/Repositories/AssistantFilesLinksRepository.swift lines 149-165 (parseAttachmentKey function at REVIEWED_COMMIT), ConvosCore/Tests/ConvosCoreTests/VideoMessageTests.swift line 231 (test using two-slash file URL), Swift URL documentation showing that `URL(string: "file://host/path")` parses 'host' as the host component rather than part of the path.

}
}

public func fetchLinks() async throws -> [AssistantLink] {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟢 Low Repositories/AssistantFilesLinksRepository.swift:96

Only the first attachment from each message is processed. The code decodes attachmentUrls as [String] but then only uses keys.first, so messages with multiple attachments silently drop all but the first. Additionally, using the message id as AssistantFile.id means multiple attachments from the same message would collide if you later fix this.

🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file ConvosCore/Sources/ConvosCore/Storage/Repositories/AssistantFilesLinksRepository.swift around line 96:

Only the first attachment from each message is processed. The code decodes `attachmentUrls` as `[String]` but then only uses `keys.first`, so messages with multiple attachments silently drop all but the first. Additionally, using the message `id` as `AssistantFile.id` means multiple attachments from the same message would collide if you later fix this.

Evidence trail:
ConvosCore/Sources/ConvosCore/Storage/Repositories/AssistantFilesLinksRepository.swift lines 76-84 at REVIEWED_COMMIT:
- Line 76: `let attachmentUrlsJson: String = row["attachmentUrls"]`
- Line 77: `let keys = try? JSONDecoder().decode([String].self, from: Data(attachmentUrlsJson.utf8))`
- Line 78: `let firstKey = keys.first`
- Line 84: `return AssistantFile(id: id, ...)`

Verified that `attachmentUrls` is decoded as `[String]` but only `keys.first` is used, dropping all subsequent attachments. Message `id` is used as `AssistantFile.id`.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟠 High

https://github.com/xmtplabs/convos-ios/blob/95c70ab6bca267d9d1716c08d7f017b14ac6098c/Convos/Conversation Detail/ConversationViewModel.swift#L625

When the conversation ID changes, sendReadReceiptIfNeeded() is called at line 660 before loadPhotoPreferences() completes at line 657. This causes sendReadReceipts to still hold the stale preference value from the previous conversation. If switching from a conversation with sendReadReceipts=false to one with sendReadReceipts=true, the read receipt is incorrectly blocked; switching from true to false incorrectly sends a read receipt. Consider moving sendReadReceiptIfNeeded() after loadPhotoPreferences() completes, or skip the immediate call and rely on the normal message flow.

🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file Convos/Conversation Detail/ConversationViewModel.swift around line 625:

When the conversation ID changes, `sendReadReceiptIfNeeded()` is called at line 660 before `loadPhotoPreferences()` completes at line 657. This causes `sendReadReceipts` to still hold the stale preference value from the previous conversation. If switching from a conversation with `sendReadReceipts=false` to one with `sendReadReceipts=true`, the read receipt is incorrectly blocked; switching from `true` to `false` incorrectly sends a read receipt. Consider moving `sendReadReceiptIfNeeded()` after `loadPhotoPreferences()` completes, or skip the immediate call and rely on the normal message flow.

Evidence trail:
ConversationViewModel.swift lines 609-622 (loadPhotoPreferences uses Task { @MainActor }), lines 653-661 (observe() calls loadPhotoPreferences() then sendReadReceiptIfNeeded() synchronously), line 331 (sendReadReceipts property), line 617 (sendReadReceipts updated in async task). ConversationViewModel+ReadReceipts.swift line 17 (guard sendReadReceipts else { return }).

Comment thread Scripts/hooks/pre-commit
# Get staged Swift files (excluding deleted files and build directories)
STAGED_SWIFT_FILES=$(git diff --cached --name-only --diff-filter=d | grep '\.swift$' || true)
STAGED_SWIFT_FILES=$(echo "$STAGED_SWIFT_FILES" | grep -v -E '^\.derivedData/|^\.build/|/\.build/' || true)
mapfile -t STAGED_SWIFT_FILES < <(
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Medium hooks/pre-commit:23

The mapfile command at line 23 requires Bash 4.0+, but macOS ships with Bash 3.2.57 by default, causing mapfile: command not found and blocking all commits for affected developers. With set -e at line 4, the hook aborts on this error. The previous while IFS= read -r loop was compatible with Bash 3.2.

🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file Scripts/hooks/pre-commit around line 23:

The `mapfile` command at line 23 requires Bash 4.0+, but macOS ships with Bash 3.2.57 by default, causing `mapfile: command not found` and blocking all commits for affected developers. With `set -e` at line 4, the hook aborts on this error. The previous `while IFS= read -r` loop was compatible with Bash 3.2.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟢 Low

https://github.com/xmtplabs/convos-ios/blob/a9636f3bdc22d6c4dad0cb08a5d94ccf69f77a9a/Convos/Conversation Detail/Messages/Messages View Controller/View Controller/MessagesViewController.swift#L1268

The JavaScript URL filter a[href^="javascript:"] on line 1084 is case-sensitive, so mixed-case schemes like JAVASCRIPT: or JaVaScRiPt: bypass the filter and execute arbitrary JavaScript in the WebView. Consider using the same URL-parsing approach as MarkdownAttachmentPreviewSheet (lines 1268-1282) to normalize and validate the scheme with case-insensitive comparison.

🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file Convos/Conversation Detail/Messages/Messages View Controller/View Controller/MessagesViewController.swift around line 1268:

The JavaScript URL filter `a[href^="javascript:"]` on line 1084 is case-sensitive, so mixed-case schemes like `JAVASCRIPT:` or `JaVaScRiPt:` bypass the filter and execute arbitrary JavaScript in the WebView. Consider using the same URL-parsing approach as `MarkdownAttachmentPreviewSheet` (lines 1268-1282) to normalize and validate the scheme with case-insensitive comparison.

Evidence trail:
MessagesViewController.swift:1084 - `div.querySelectorAll('a[href^="javascript:"]').forEach(function(el) { el.removeAttribute('href'); });` (case-sensitive CSS selector)
MessagesViewController.swift:1015 - CSP with `script-src 'unsafe-inline'` allows inline scripts including javascript: URLs
MessagesViewController.swift:1268-1282 - URL parsing approach with `.toLowerCase()` for case-insensitive scheme comparison
git grep result confirms exact line 1084 for the vulnerable pattern

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟢 Low

In processProfileSnapshotInSE, profiles with existing name or avatar are skipped entirely via continue on line 771, so the agent verification logic (lines 795-798) and markConversationHasVerifiedAssistantIfNeeded call never execute for those profiles. Pre-existing agent profiles that already have a name/avatar will never be verified through snapshot processing, leaving hasHadVerifiedAssistant unset on conversations that should have it. Consider removing the continue and merging the snapshot data with the existing profile instead.

🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file ConvosCore/Sources/ConvosCore/Inboxes/MessagingService+PushNotifications.swift around line 771:

In `processProfileSnapshotInSE`, profiles with existing `name` or `avatar` are skipped entirely via `continue` on line 771, so the agent verification logic (lines 795-798) and `markConversationHasVerifiedAssistantIfNeeded` call never execute for those profiles. Pre-existing agent profiles that already have a name/avatar will never be verified through snapshot processing, leaving `hasHadVerifiedAssistant` unset on conversations that should have it. Consider removing the `continue` and merging the snapshot data with the existing profile instead.

Evidence trail:
ConvosCore/Sources/ConvosCore/Inboxes/MessagingService+PushNotifications.swift lines 771-773 (continue statement for existing name/avatar), lines 795-798 (agent verification logic after continue), line 800 (markConversationHasVerifiedAssistantIfNeeded call after continue) at REVIEWED_COMMIT

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.

1 participant