Validate URL schemes and double extensions on file import#5226
Open
pballart wants to merge 3 commits into
Open
Validate URL schemes and double extensions on file import#5226pballart wants to merge 3 commits into
pballart wants to merge 3 commits into
Conversation
Adds two security validations to the third-party file/zip import path, agreed in the kick-off: - Drop bookmarks whose URL uses a javascript:/data: scheme (which would execute content rather than navigate if the bookmark were activated). - Reject zip entries with a disguising double extension (e.g. foo.swift.html). Both rules live once in BrowserServicesKit as the single source of truth (String.hasUnsafeBookmarkImportScheme / String.hasMultipleFileExtensions) and are invoked from each platform's existing skip-invalid path: iOS via BookmarkOrFolder.isInvalidBookmark and the Core ImportArchiveReader, macOS via the LocalBookmarkStore import loop and the DataImport ImportArchiveReader. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…imits Addresses PR review: - Apply the double-extension guard to directly-selected (non-archive) files, not just zip entries: iOS DataImportManager.importFile and macOS SafariArchiveImporter.readContentsForSelectedFile now reject a file whose name has a disguising double extension (e.g. foo.swift.html). Archives stay exempt — their entries are still validated individually inside ImportArchiveReader. - Add .timeLimit(.minutes(1)) (with @available) to all Swift Testing @test declarations, per the codebase convention, to avoid the 60-minute default. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
8e304ad to
4125bf5
Compare
Contributor
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 4125bf5. Configure here.
Addresses PR review: the macOS guard applied to all BookmarkOrFolder types, so a folder carrying a stray javascript:/data: URL string would be skipped along with all its children. Exempt folders (matching iOS BookmarkOrFolder.isInvalidBookmark) so nested bookmarks aren't silently lost, keeping both platforms consistent. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Task/Issue URL: https://app.asana.com/0/0/1210890453697052/f/
Description
Hardens the third-party file/zip import path (security-audit follow-up):
javascript:/data:scheme — activating such a bookmark would execute embedded content instead of navigating.foo.swift.html).Both rules live once in BrowserServicesKit (
String.hasUnsafeBookmarkImportScheme()/String.hasMultipleFileExtensions) and are invoked from each platform's import paths — the scheme check at the shared bookmark-save chokepoint (iOSBookmarkOrFolder.isInvalidBookmark, macOSLocalBookmarkStore), and the double-extension check at both the archive readers (ImportArchiveReader) and the direct-file entry points (iOSDataImportManager.importFile, macOSSafariArchiveImporter.readContentsForSelectedFile). Archives themselves are exempt — their entries are validated individually.Testing Steps
https:bookmark plusjavascript:/data:bookmarks (iOS + macOS) → thehttps:one imports; the unsafe ones are dropped (counted as failed, not saved).bookmarks.html+passwords.csvplus a decoy likeevil.swift.html→ normal files import; the double-extension entry is skipped.bookmarks.evil.html) directly → it's rejected (nothing imported).Impact and Risks
Low–Medium — changes which imported bookmarks are persisted (privacy/security hardening; no change to existing stored data).
What could go wrong?
A legitimate item could be dropped. Mitigations: the scheme check is limited to
javascript:/data:and is bookmarks-only (passwords/cards unaffected). The double-extension rule is intentionally strict (any filename with >1 dot) — an accepted trade-off agreed in the kick-off — so a legitimately double-dotted archive entry is skipped, and a directly-selected file with that shape is rejected outright (the import fails). The strictness was a deliberate decision over false-positive risk.Quality Considerations
StringFileExtensionsTests,BookmarkImportSchemeValidationTests), iOS (ImportArchiveReaderTests,DataImportManagerTests), and macOS (LocalBookmarkStoreTests,SafariArchiveImporterTests). iOS tests verified passing locally; macOS + BSK suites run on CI.Internal references:
Definition of Done | Engineering Expectations | Tech Design Template
Note
Medium Risk
Import behavior changes which bookmarks and files are accepted; scheme filtering is narrow but the double-extension rule may skip legitimate multi-dot filenames (e.g.
report.tar.gz).Overview
Hardens third-party data import (security-audit follow-up) by blocking two abuse paths: executable bookmark targets and disguised filenames.
Unsafe bookmark URLs: Shared helpers in BrowserServicesKit (
hasUnsafeBookmarkImportScheme()forjavascript:/data:) extendBookmarkOrFolder.isInvalidBookmark, so iOS import viaBookmarkCoreDataImporterdrops those entries. macOS adds the same filter inLocalBookmarkStorewhen persisting imports (folders with stray unsafe URLs are kept so children still import).Double extensions:
hasMultipleFileExtensionsflags last path components with more than one dot (e.g.foo.swift.html). Direct file picks are rejected on iOS (DataImportManager.importFilereturns nil) and macOS standalone Safari imports (SafariArchiveImporteryields empty contents / import failure). Zip entries with that pattern are skipped in both platforms’ImportArchiveReaderwhile normal.html/.csv/.jsonentries still load.Unit tests cover BSK helpers and platform import/archive paths.
Reviewed by Cursor Bugbot for commit d6b7f2a. Bugbot is set up for automated code reviews on this repo. Configure here.