-
-
Notifications
You must be signed in to change notification settings - Fork 615
[FEATURE] Support more url schemes and remove insecure ftp scheme #4537
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: dev
Are you sure you want to change the base?
Changes from all commits
fd90e73
4ef930b
bde1d46
8b1d0d4
19c600c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -12,7 +12,21 @@ public class Main : IPlugin, IPluginI18n, ISettingProvider | |||||||||||||||||||||||||||||||||||||||||||||||||||||
| internal static PluginInitContext Context { get; private set; } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| internal static Settings Settings { get; private set; } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private static readonly string[] UrlSchemes = ["http", "https", "ftp"]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Schemes requiring full host validation: domain with TLD, IP address, or localhost | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private static readonly string[] HostValidatedSchemes = ["http", "https"]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Chromium browser schemes accepting both :// and : forms (e.g. chrome://settings, chrome:settings) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private static readonly string[] ChromiumSchemes = ["chrome-extension", "chrome", "brave", "edge", "opera", "vivaldi"]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Schemes using :// that are validated by scheme recognition alone — any valid URI structure is accepted | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private static readonly string[] NonHostValidatedDoubleSlashSchemes = [.. ChromiumSchemes, "file", "moz-extension"]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Schemes using colon-only syntax (e.g. about:blank, chrome:settings) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Chromium schemes also accept the colon form | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private static readonly string[] ColonOnlySchemes = [.. ChromiumSchemes, "about", "data"]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // All :// schemes | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private static readonly string[] AllDoubleSlashSchemes = [.. HostValidatedSchemes, .. NonHostValidatedDoubleSlashSchemes]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public List<Result> Query(Query query) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -44,7 +58,12 @@ public List<Result> Query(Query query) | |||||||||||||||||||||||||||||||||||||||||||||||||||||
| // if url was accepted without having any of the recognized scheme, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // then that means no scheme was specified (e.g. www.google.com) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // so we add the preferred http/https scheme | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!UrlSchemes.Any(scheme => raw.StartsWith(scheme + "://", StringComparison.OrdinalIgnoreCase))) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| var hasScheme = ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| AllDoubleSlashSchemes.Any(scheme => raw.StartsWith(scheme + "://", StringComparison.OrdinalIgnoreCase)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| || | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ColonOnlySchemes.Any(scheme => raw.StartsWith(scheme + ":", StringComparison.OrdinalIgnoreCase)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!hasScheme) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| raw = GetHttpPreference() + "://" + raw; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -116,21 +135,37 @@ public bool IsURL(string raw) | |||||||||||||||||||||||||||||||||||||||||||||||||||||
| return true; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Check colon-only schemes (e.g. about:blank, chrome:settings) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| var colonIndex = input.IndexOf(':'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (colonIndex > 0) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| var scheme = input[..colonIndex]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (ColonOnlySchemes.Any(s => scheme.Equals(s, StringComparison.OrdinalIgnoreCase))) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| var content = input[(colonIndex + 1)..]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return content.Length > 0 && !content.Any(char.IsWhiteSpace); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P1: Colon-scheme validation incorrectly treats Prompt for AI agents
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+138
to
+148
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Bug: For Chromium schemes that support both forms ( When content starts with 🐛 Proposed fix // Check colon-only schemes (e.g. about:blank, chrome:settings)
var colonIndex = input.IndexOf(':');
if (colonIndex > 0)
{
var scheme = input[..colonIndex];
if (ColonOnlySchemes.Any(s => scheme.Equals(s, StringComparison.OrdinalIgnoreCase)))
{
var content = input[(colonIndex + 1)..];
+ // Defer double-slash forms to URI-based validation below
+ if (!content.StartsWith("//"))
+ {
return content.Length > 0 && !content.Any(char.IsWhiteSpace);
+ }
}
}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Add protocol if missing for Uri validation | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| var urlToValidate = UrlSchemes.Any(s => input.StartsWith(s + "://", StringComparison.OrdinalIgnoreCase)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| var urlToValidate = AllDoubleSlashSchemes.Any(s => input.StartsWith(s + "://", StringComparison.OrdinalIgnoreCase)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ? input | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| : GetHttpPreference() + "://" + input; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!Uri.TryCreate(urlToValidate, UriKind.Absolute, out var uri)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return false; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Validate protocol against known schemes | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!UrlSchemes.Any(scheme => uri.Scheme == scheme)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Validate protocol against known :// schemes | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!AllDoubleSlashSchemes.Any(scheme => uri.Scheme == scheme)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return false; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| var host = uri.Host; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Scheme-only validation: any valid URI structure is accepted, no host checks | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (NonHostValidatedDoubleSlashSchemes.Any(scheme => uri.Scheme == scheme)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return true; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // localhost is valid | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (host.Equals("localhost", StringComparison.OrdinalIgnoreCase)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return true; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
P2: Bookmark actions now bypass Flow's configured browser launch settings and always force tab opening.
Prompt for AI agents