fix(tool): port upstream webfetch redirect rule checks (anomalyco/opencode#59748)
DE
1d ago+167+167+012345678901234567890123456789-7-7-0123456789
Issue for this PR
Closes #1658
Type of change
- Bug fix
- New feature
- Refactor / code improvement
- Documentation
What does this PR do?
Ports the upstream webfetch permission fixes to the fork's packages/opencode/src/tool/webfetch.ts:
- anomalyco/opencode#59748:
webfetchusedfetch's defaultredirect: "follow", so only the URL the model passed was checked against thewebfetchrules. An allowed page that redirects to a denied URL (for examplehttp://169.254.169.254/...under{"*": "allow", "http://169.254.169.254/*": "deny"}) was fetched and returned to the model. Redirects are now followed by hand (redirect: "manual", max 10 hops). Each target is evaluated against the effective ruleset (ctx.permissions) before it is requested. A denied target throwsPermissionDeniedError; as upstream does, the user is not asked again for redirect targets. Redirects to non-HTTP schemes fail. - anomalyco/opencode#61701: URLs with credentials are rejected, both the requested URL and redirect targets. Without this, a rule for
https://docs.example.com*also matchedhttps://docs.example.com@evil.example/. Fragments are dropped before rules are matched. - anomalyco/opencode#60505: the permission prompt matches the normalized
URL.href, not the raw string the model typed.
Upstream made these changes in the v2 packages/core/src/tool/plugin/webfetch.ts. This PR adapts them to the fork's legacy tool and wraps the changes in altimate_change ... upstream_fix: markers. The failure cache, UA fallback and error messages are unchanged.
How did you verify your code works?
- Added four tests to
packages/opencode/test/tool/webfetch.test.ts: an allowed redirect is followed, a denied redirect target stops before it is requested, non-HTTP and endless redirects fail, and credentials are rejected. Onmain, the denied-redirect, scheme and credential tests fail. With this change, all 37 tests inwebfetch.test.tsandwebfetch-cache.test.tspass. bun run typecheck(tsgo) inpackages/opencodepasses, and so does the pre-pushbun typecheck.bun run script/upstream/analyze.ts --markers --base origin/main --strict: ok.
Cost side effects
None. A redirect issues the same number of HTTP requests as before. Rule checks are local.
Screenshots / recordings
Not a UI change.
Checklist
- I have tested my changes locally
- I have not included unrelated changes in this PR
- I checked for cost side effects (model calls, queries or cloud resources that grow with user data) and described them, or wrote "none"
Tracked in #1478.
Summary by cubic
Fixes the webfetch tool's permission checks so allowed pages can no longer redirect to denied URLs, and incoming URLs are normalized before being matched against rules.
- Follows redirects manually (max 10 hops) and checks each target against the effective ruleset before requesting it; denied targets throw without prompting the user again.
- Rejects URLs with embedded credentials and drops URL fragments before matching rules, so a rule like
https://docs.example.com*no longer matcheshttps://docs.example.com@evil.example/. - Permission prompts now use the normalized
URL.hrefinstead of the raw input string. - Adds four tests covering allowed redirects, denied redirect targets, non-HTTP and endless redirects, and credential rejection.