Harden GUI storage and browser inputs
Some checks are pending
Security Scan / security (push) Waiting to run
Test / test (push) Waiting to run

This commit is contained in:
Snider 2026-04-15 22:51:07 +01:00
parent c73b9c10e3
commit 7aaabf4b77
6 changed files with 43 additions and 3 deletions

View file

@ -64,6 +64,9 @@ func validatedOpenURL(raw string) (string, error) {
if parsed.Host == "" {
return "", coreerr.E("browser.openURL", "url host is required", nil)
}
if parsed.User != nil {
return "", coreerr.E("browser.openURL", "url must not include credentials", nil)
}
return parsed.String(), nil
}

View file

@ -67,6 +67,17 @@ func TestTaskOpenURL_Bad_Scheme(t *testing.T) {
assert.Empty(t, mp.lastURL)
}
func TestTaskOpenURL_Bad_Credentials(t *testing.T) {
mp := &mockPlatform{}
_, c := newTestBrowserService(t, mp)
r := c.Action("browser.openURL").Run(context.Background(), core.NewOptions(
core.Option{Key: "url", Value: "https://user:pass@example.com"},
))
assert.False(t, r.OK)
assert.Empty(t, mp.lastURL)
}
func TestTaskOpenURL_Bad_PlatformError(t *testing.T) {
mp := &mockPlatform{urlErr: core.NewError("browser not found")}
_, c := newTestBrowserService(t, mp)

View file

@ -590,6 +590,9 @@ func (s *Service) renderStoreSearchPage(query string, results []StorageEntry) st
}
func (s *Service) searchAllStorage(query string) []StorageEntry {
if strings.TrimSpace(query) == "" {
return nil
}
results := s.storage.Search(query)
if conversations := s.Core().QUERY(chat.QueryConversationSearch{Query: query}); conversations.OK {
switch list := conversations.Value.(type) {

View file

@ -172,6 +172,17 @@ func TestScheme_ResolveScheme_Ugly(t *testing.T) {
assert.Contains(t, searchPayload["body"].(string), "No matches found in Core storage.")
}
func TestScheme_HandleStoreSearch_BlankQueryReturnsNoResults(t *testing.T) {
svc, _ := newTestDisplayService(t)
svc.storage.Set("origin-a", "local", "theme", "dark")
result := svc.handleStoreSearch(context.Background(), url.Values{})
require.True(t, result.OK)
payload := result.Value.(map[string]any)
assert.Empty(t, payload["results"])
assert.Contains(t, payload["body"].(string), "Enter a search term")
}
func TestScheme_ResolveScheme_ServiceBackedRoute_Good(t *testing.T) {
c := core.New(
core.WithService(Register(nil)),

View file

@ -115,7 +115,7 @@ func storageOriginForPageURL(pageURL string) string {
}
func makeStorageEntryKey(origin, bucket, key string) string {
return strings.Join([]string{origin, bucket, key}, "\x00")
return storageCompositeKey(origin, bucket, key)
}
func storageCompositeKey(origin, bucket, key string) string {
@ -278,6 +278,9 @@ func (r *StorageRegistry) Snapshot(pageURL string) map[string]map[string]string
defer r.mu.RUnlock()
origin := storageOriginForPageURL(pageURL)
if strings.TrimSpace(origin) == "" {
return map[string]map[string]string{}
}
snapshot := make(map[string]map[string]string)
for _, entry := range r.entries {
if origin != "" && !strings.EqualFold(entry.Origin, origin) {

View file

@ -11,7 +11,7 @@ import (
)
func storageEntryKey(origin, bucket, key string) string {
return strings.Join([]string{origin, bucket, key}, "\x00")
return makeStorageEntryKey(origin, bucket, key)
}
func setStorageEntryTime(r *StorageRegistry, origin, bucket, key string, ts time.Time) {
@ -149,6 +149,15 @@ func TestStorage_StorageOriginForPageURL_Ugly(t *testing.T) {
assert.Equal(t, "", storageOriginForPageURL(" "))
}
func TestStorage_Snapshot_BlankOriginReturnsEmpty(t *testing.T) {
r := NewStorageRegistry()
r.Set("core://settings", "localStorage", "theme", "dark")
snapshot := r.Snapshot("")
assert.Empty(t, snapshot)
}
func TestStorage_CompositeKey_Good(t *testing.T) {
key := storageCompositeKey("origin", "bucket", "item")
@ -157,7 +166,7 @@ func TestStorage_CompositeKey_Good(t *testing.T) {
assert.Equal(t, "origin", origin)
assert.Equal(t, "bucket", bucket)
assert.Equal(t, "item", item)
assert.Equal(t, "origin\x00bucket\x00item", makeStorageEntryKey("origin", "bucket", "item"))
assert.Equal(t, key, makeStorageEntryKey("origin", "bucket", "item"))
}
func TestStorage_CompositeKey_Bad(t *testing.T) {