{"record":{"id":"41dda8ad1b1e5cc2","repo":"gastownhall/beads","slug":"remote-url-q-does-not-match-any-allowed-pattern","errorCode":null,"errorMessage":"remote URL %q does not match any allowed pattern","messagePattern":"remote URL %q does not match any allowed pattern","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/remotecache/url.go","lineNumber":233,"sourceCode":"\treturn matched\n}\n\n// ValidateRemoteURLWithPatterns validates a URL and optionally checks it\n// against an allowlist of glob patterns. If patterns is empty, only\n// structural validation is performed.\nfunc ValidateRemoteURLWithPatterns(rawURL string, patterns []string) error {\n\tif err := ValidateRemoteURL(rawURL); err != nil {\n\t\treturn err\n\t}\n\tif len(patterns) == 0 {\n\t\treturn nil\n\t}\n\tfor _, p := range patterns {\n\t\tif MatchesRemotePattern(rawURL, p) {\n\t\t\treturn nil\n\t\t}\n\t}\n\treturn fmt.Errorf(\"remote URL %q does not match any allowed pattern\", rawURL)\n}\n\nfunc sortedSchemes() []string {\n\t// Return in a consistent display order\n\treturn []string{\"dolthub\", \"https\", \"http\", \"ssh\", \"git\", \"git+ssh\", \"git+https\", \"git+http\", \"git+file\", \"s3\", \"aws\", \"gs\", \"az\", \"oci\", \"file\"}\n}\n\n// CacheKey returns a filesystem-safe identifier for a remote URL.\n// It uses the first 16 hex characters (64 bits) of the SHA-256 hash.\n// Birthday-bound collision risk is negligible for a local cache: 50% at\n// ~4.3 billion entries, well beyond any realistic number of remotes.\nfunc CacheKey(remoteURL string) string {\n\th := sha256.Sum256([]byte(remoteURL))\n\treturn fmt.Sprintf(\"%x\", h[:8])\n}\n","sourceCodeStart":215,"sourceCodeEnd":249,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/remotecache/url.go#L215-L249","documentation":"ValidateRemoteURLWithPatterns enforces an allowlist: the URL must match at least one configured glob-style pattern (path.Match semantics, e.g. \"dolthub://myorg/*\"). If no pattern matches, the remote is outside policy and the call fails with the offending URL quoted.","triggerScenarios":"Adding a remote whose URL scheme or host is not covered by any allowed pattern — e.g. allowlist is [\"dolthub://myorg/*\"] but the URL is https://github.com/other/repo, or a typo like dolthub://myorgX/repo.","commonSituations":"Organization policy configs that restrict remotes to trusted hosts; users pointing at a personal fork or a different registry; scheme typos (http vs https) not covered by patterns.","solutions":["Check the configured allowed patterns and use a URL that matches one of them exactly.","Fix the URL typo or wrong scheme/host (e.g. dolthub://myorg/repo instead of dolthub://myorgx/repo).","If the remote is legitimately needed, have an admin add a pattern covering it (e.g. \"dolthub://myorg/forks/*\")."],"exampleFix":"// before\npatterns := []string{\"dolthub://myorg/*\"}\nValidateRemoteURLWithPatterns(\"https://github.com/other/repo\", patterns) // fails\n// after\nValidateRemoteURLWithPatterns(\"dolthub://myorg/repo\", patterns) // ok","handlingStrategy":"validation","validationCode":"func urlAllowed(rawURL string, patterns []string) bool {\n    for _, p := range patterns {\n        if matched, _ := path.Match(p, rawURL); matched {\n            return true\n        }\n    }\n    return false\n}","typeGuard":null,"tryCatchPattern":"if err := remotecache.ValidateRemoteURLWithPatterns(rawURL, patterns); err != nil {\n    return fmt.Errorf(\"remote not permitted by policy: %w\", err)\n}","preventionTips":["Keep the allowlist in config and document covered hosts/schemes for users.","Validate scheme and host before constructing the full URL.","Log the offending URL on failure so typos are easy to spot."],"tags":["validation","remote","allowlist","security"],"backgroundTag":"remote-url-not-allowed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}