Repository navigation
fix(github): don't abort when a forge token has an invalid header character - #13488
Conversation
…racter A GitHub, GitLab or Forgejo token containing a character that is illegal in an HTTP header — a newline, say — reached `HeaderValue::from_str(..).unwrap()` and aborted the process with SIGABRT instead of reporting a credential problem. Route all four call sites through a shared `tokens::bearer_header`, which maps the failure to a redacted error and marks the header value sensitive so reqwest keeps it out of debug output. `gitlab::get_headers` and `forgejo::get_headers` now return `Result<HeaderMap>` to carry it; both already carried an "Avoid panicking here" comment directly above the unwrap. Also trim tokens read from `github_tokens.toml`, `gitlab_tokens.toml` and `forgejo_tokens.toml`, matching what `env::scoped_var` already does for the environment-variable sources, and stop `packslip::repo_file_request` from swallowing the error as "this forge is unsupported". Reported in #13471 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Navigate logical layers of code changes, visualize relationships, and explore their blast radius. No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository YAML (base), Central YAML (inherited), Organization UI (inherited) Review profile: CHILL Plan: Advanced Run ID: 📒 Files selected for processing (7)
Included review availability: Your plan provides up to 10 included reviews per hour; 8 remain after this review. 📝 WalkthroughWalkthroughChangesAuthentication header error propagation
Priority: ➖ Normal Estimated code review effort: 3 (Moderate) | ~20 minutes Change: Bug fix Suggested reviewers: Merge Risk: ⚪ Minimal · up to The authentication changes are mergeable with no identified current-head regression. 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
<!-- entire-trail-link-start --> https://entire.io/gh/jdx/mise/trails/68 <!-- entire-trail-link-end --> ### 🚀 Features - **(bootstrap)** remove module resources with unapply by @jdx in [#13441](#13441) - **(bootstrap)** support PartOf, BindsTo, Before, Conflicts and ExecStartPre/Post in systemd units by @jdx in [#13526](#13526) - **(bootstrap)** remove a templated file when it renders empty by @jdx in [#13510](#13510) - **(bootstrap)** manage a file's permissions without its contents by @jdx in [#13511](#13511) - **(cli)** colour the help page mise prints, and give it a logo by @jdx in [#13449](#13449) - **(config)** add .miserc.local.toml overrides by @jdx in [#13440](#13440) - **(config)** complete keys for `mise config get` and `mise config set` by @jdx in [#13551](#13551) - **(daemons)** add user-owned shared server providers by @jdx in [#13534](#13534) - **(daemons)** share SQL servers with isolated checkout databases by @jdx in [#13536](#13536) - **(daemons)** isolate shared NATS consumers with accounts by @jdx in [#13537](#13537) - **(dotfiles)** preview file counts and size before tracking by @jdx in [#13417](#13417) - **(dotfiles)** support exclusions on tracked directories by @jdx in [#13418](#13418) - **(dotfiles)** select tracked files with include lists by @jdx in [#13432](#13432) - **(dotfiles)** deliver warnings from background captures by @jdx in [#13483](#13483) - **(dotfiles)** set target file permissions with a permissions key by @jdx in [#13514](#13514) - **(dotfiles)** remove targets with mode = "absent" by @jdx in [#13513](#13513) - **(dotfiles)** remove a template's target when it renders empty by @jdx in [#13515](#13515) - **(dotfiles)** remove directories mise created once they are empty by @jdx in [#13518](#13518) - **(hooks)** expose installed tool backend and path by @garysassano in [#13421](#13421) - **(install)** explain checksum mismatches caused by re-uploaded GitHub assets by @jdx in [#13512](#13512) - **(lock)** keep locked backends when the registry moves a tool, and add `mise backends switch` by @jdx in [#13543](#13543) - **(ls)** filter and group tools by backend by @jdx in [#13530](#13530) - **(registry)** add a url field for a tool's project homepage by @jdx in [#13533](#13533) - **(search)** search package registries by backend prefix or with --all by @jdx in [#13550](#13550) - **(tool-stub)** lock stubs in their project's mise.lock by @jdx in [#13502](#13502) - **(vfox)** add BackendUninstall hook for backend plugins by @jdx in [#13522](#13522) - override node bundled pnpm by specified version of pnpm by @EMcCormack in [#13498](#13498) ### 🐛 Bug Fixes - **(activate)** make bash `mise` function work without $__MISE_EXE by @jdx in [#13491](#13491) - **(aqua)** create .mise-bins for registry files listed by name only by @jdx in [#13525](#13525) - **(aqua)** report only the provenance and signature checks mise performs by @jdx in [#13549](#13549) - **(backend)** keep .exe when bin renames a raw Windows download by @jdx in [#13529](#13529) - **(bootstrap)** stop running Windows user services through cmd.exe by @jdx in [#13429](#13429) - **(bootstrap)** run history reload commands for dotfiles bootstrap writes by @jdx in [#13509](#13509) - **(brew-cask)** percent-decode artifact filenames from cask URLs by @jdx in [#13431](#13431) - **(cache)** stop prune from destroying installed tool files by @jdx in [#13424](#13424) - **(completion)** exit quietly when the completion reader closes stdout by @jdx in [#13527](#13527) - **(daemons)** fail early when a postgres daemon would start as root by @jdx in [#13567](#13567) - **(github)** don't abort when a forge token has an invalid header character by @jdx in [#13488](#13488) - **(history)** run the Windows watcher without a console window by @jdx in [#13428](#13428) - **(history)** report files omitted by credential filtering by @jdx in [#13415](#13415) - **(history)** skip nested repositories unless tracked directly by @jdx in [#13416](#13416) - **(history)** apply global exclusions consistently to tracked paths by @jdx in [#13427](#13427) - **(install)** align per-tool progress bars in interactive installs by @jdx in [#13494](#13494) - **(install)** extract .tar.zst archives compressed with a long window by @jdx in [#13566](#13566) - **(lock)** lock the npm version, not the aube install directory name by @jdx in [#13542](#13542) - **(lock)** lock global requests shadowed by the project config by @jdx in [#13547](#13547) - **(lock)** make --bump check remote versions and fail when it can't by @jdx in [#13544](#13544) - **(lock)** refuse to lock a version that a failed listing never confirmed by @jdx in [#13552](#13552) - **(npm)** run npm_execpath scripts through aube, not the task runner by @jdx in [#13484](#13484) - **(release)** build Windows with panic=unwind so vfox Lua errors don't abort by @jdx in [#13503](#13503) - **(self-update)** fail before downloading when the install dir is not writable by @jdx in [#13453](#13453) - **(shim)** install a wrapper command's missing provider before dispatching by @jdx in [#13532](#13532) - **(task)** preserve script execution and dependencies in metadata overlays by @jdx in [#13448](#13448) - **(task)** allow TOML commands to replace file tasks by @jdx in [#13458](#13458) - **(task)** only report the task that failed as an error by @jdx in [#13556](#13556) - **(upgrade)** persist explicit selectors when bumping versions by @zeitlinger in [#13179](#13179) ### 🚜 Refactor - move platform and version primitives out of cli::version by @jdx in [#13457](#13457) - move shared history helpers out of the CLI layer by @jdx in [#13480](#13480) - move global-config editing helpers into config::edit by @jdx in [#13481](#13481) ### 📚 Documentation - **(agents)** move task procedures into skills and fix stale guidance by @jdx in [#13528](#13528) - **(bootstrap)** explain optional setup modules with config environments by @jdx in [#13439](#13439) - **(bootstrap)** remove files in the home directory with state = "absent" by @jdx in [#13507](#13507) - **(registry)** show verification badges and link each tool to mise-versions by @jdx in [#13548](#13548) - fix zsh completion steps rendering as duplicate "sh" tabs by @jdx in [#13423](#13423) - accept bug reports in GitHub Issues by @jdx in [#13524](#13524) - describe development tools and project configuration plainly by @jdx in [#13517](#13517) ### 🧪 Testing - **(bootstrap)** cover the bootstrap task on adoption and later updates by @jdx in [#13508](#13508) - **(daemons)** make the port-slot test deterministic by @jdx in [#13447](#13447) - **(e2e)** share one HTTP test server via start_http_server by @jdx in [#13553](#13553) - **(e2e)** serve npm metadata from a local fake registry by @jdx in [#13554](#13554) - **(e2e)** skip the postgres daemon provider test as root by @jdx in [#13565](#13565) - **(lockfile)** make the python provenance-skip test use its locked tarball by @jdx in [#13545](#13545) - don't reset the shared fixture tree in --list invocations by @betaboon in [#13455](#13455) ### 📦️ Dependency Updates - update rust crate usage-cli to v6.11.0 by @renovate[bot] in [#13450](#13450) - update rust crate console to v0.16.6 by @renovate[bot] in [#13468](#13468) - update ghcr.io/jdx/mise:alpine docker digest to f443aaf by @renovate[bot] in [#13462](#13462) - update ghcr.io/jdx/mise:rpm docker digest to 6277132 by @renovate[bot] in [#13464](#13464) - update docker/build-push-action digest to c3c9e26 by @renovate[bot] in [#13474](#13474) - update rust crate cc to v1.4.6 by @renovate[bot] in [#13467](#13467) - update rust crate jiff to v0.2.37 by @renovate[bot] in [#13469](#13469) - update rust crate aws-sdk-s3 to v1.146.1 by @renovate[bot] in [#13466](#13466) - bump locked dev tools and fix communique 1.4.1 lock entry by @jdx in [#13490](#13490) - update rattler to rattler_conda_types 0.53 by @jdx in [#13489](#13489) - update ubuntu docker tag to resolute-20260901 by @renovate[bot] in [#13476](#13476) - update zizmorcore/zizmor-action action to v0.6.4 by @renovate[bot] in [#13486](#13486) - update jdx/packslip action to v1.2.0 by @renovate[bot] in [#13492](#13492) - refresh Cargo.lock and handle build metadata from versions 8.0.1 by @jdx in [#13506](#13506) - update ghcr.io/jdx/mise:deb and nscloud-cache-action digests by @jdx in [#13504](#13504) - group all usage crates in one Renovate update by @jdx in [#13519](#13519) - update rust crate usage-lib to v6.11.1 by @renovate[bot] in [#13516](#13516) - update communique to 1.4.2 in mise.lock by @jdx in [680c305](680c305) - upgrade locked mise tools by @jdx in [dadb677](dadb677) ### 📦 Registry - add mole by @casparbreloh in [#13363](#13363) - point aube at aubepkg/aube by @jdx in [#13541](#13541) - add reviewdog by @takumin in [#13562](#13562) - add nim by @elijahr in [#13461](#13461) ### Chore - **(backend)** **breaking** remove the experimental pkgx backend by @jdx in [#13555](#13555) - **(ci)** comment on a discussion when the PR implementing it merges by @jdx in [#13452](#13452) - **(ci)** skip debuginfo in release-plz builds by @jdx in [a486c41](a486c41) - remove Entire trail runners by @jdx in [#13535](#13535) - float jdx tools and aube on latest without a release-age delay by @jdx in [#13540](#13540) ### Security - **(bootstrap)** refuse untrusted parent symlinks when writing or removing files as root by @jdx in [#13539](#13539) - **(bootstrap)** don't follow untrusted parent symlinks when changing directories as root by @jdx in [#13546](#13546) ### New Contributors - @elijahr made their first contribution in [#13461](#13461) - @takumin made their first contribution in [#13562](#13562) - @EMcCormack made their first contribution in [#13498](#13498) ## 📦 Aqua Registry Updates ### New Packages (3) - [`UsefulSoftwareCo/executor`](https://github.com/UsefulSoftwareCo/executor) - [`aquaproj/ar2`](https://github.com/aquaproj/ar2) - [`revive-lint/revive`](https://github.com/revive-lint/revive) ### Updated Packages (124) - [`TomWright/dasel`](https://github.com/TomWright/dasel) - [`UpCloudLtd/upcloud-cli`](https://github.com/UpCloudLtd/upcloud-cli) - [`XcodesOrg/xcodes`](https://github.com/XcodesOrg/xcodes) - [`YS-L/csvlens`](https://github.com/YS-L/csvlens) - [`abemedia/stagelint`](https://github.com/abemedia/stagelint) - [`abhimanyu003/sttr`](https://github.com/abhimanyu003/sttr) - [`abhinav/git-spice`](https://github.com/abhinav/git-spice) - [`anchore/grype`](https://github.com/anchore/grype) - [`anchore/syft`](https://github.com/anchore/syft) - [`aquaproj/aqua-registry-updater`](https://github.com/aquaproj/aqua-registry-updater) - [`aquaproj/example-go-slsa-provenance`](https://github.com/aquaproj/example-go-slsa-provenance) - [`aquaproj/registry-tool`](https://github.com/aquaproj/registry-tool) - [`aquasecurity/trivy`](https://github.com/aquasecurity/trivy) - [`arch-go/arch-go`](https://github.com/arch-go/arch-go) - [`betterleaks/betterleaks`](https://github.com/betterleaks/betterleaks) - [`bomctl/bomctl`](https://github.com/bomctl/bomctl) - [`boostsecurityio/bagel`](https://github.com/boostsecurityio/bagel) - [`caarlos0/fork-cleaner`](https://github.com/caarlos0/fork-cleaner) - [`caarlos0/svu`](https://github.com/caarlos0/svu) - [`caddyserver/caddy`](https://github.com/caddyserver/caddy) - [`carvel-dev/imgpkg`](https://github.com/carvel-dev/imgpkg) - [`carvel-dev/kapp`](https://github.com/carvel-dev/kapp) - [`carvel-dev/kbld`](https://github.com/carvel-dev/kbld) - [`carvel-dev/vendir`](https://github.com/carvel-dev/vendir) - [`carvel-dev/ytt`](https://github.com/carvel-dev/ytt) - [`cert-manager/cmctl`](https://github.com/cert-manager/cmctl) - [`chainguard-dev/apko`](https://github.com/chainguard-dev/apko) - [`chainguard-dev/melange`](https://github.com/chainguard-dev/melange) - [`charmbracelet/crush`](https://github.com/charmbracelet/crush) - [`charmbracelet/freeze`](https://github.com/charmbracelet/freeze) - [`charmbracelet/glow`](https://github.com/charmbracelet/glow) - [`charmbracelet/gum`](https://github.com/charmbracelet/gum) - [`charmbracelet/vhs`](https://github.com/charmbracelet/vhs) - [`daveshanley/vacuum`](https://github.com/daveshanley/vacuum) - [`docker/buildx`](https://github.com/docker/buildx) - [`docker/compose`](https://github.com/docker/compose) - [`ekristen/aws-nuke`](https://github.com/ekristen/aws-nuke) - [`fission/fission`](https://github.com/fission/fission) - [`fluxcd/flux2`](https://github.com/fluxcd/flux2) - [`foundry-rs/foundry`](https://github.com/foundry-rs/foundry) - [`getsops/sops`](https://github.com/getsops/sops) - [`gittuf/gittuf`](https://github.com/gittuf/gittuf) - [`gleam-lang/gleam`](https://github.com/gleam-lang/gleam) - [`go-delve/delve`](https://github.com/go-delve/delve) - [`google/yamlfmt`](https://github.com/google/yamlfmt) - [`gopasspw/gopass`](https://github.com/gopasspw/gopass) - [`goreleaser/nfpm`](https://github.com/goreleaser/nfpm) - [`helm/chart-releaser`](https://github.com/helm/chart-releaser) - [`helm/chart-testing`](https://github.com/helm/chart-testing) - [`interlynk-io/sbomqs`](https://github.com/interlynk-io/sbomqs) - [`jenkins-x/jx`](https://github.com/jenkins-x/jx) - [`kubepug/kubepug`](https://github.com/kubepug/kubepug) - [`kubermatic/kubeone`](https://github.com/kubermatic/kubeone) - [`kubernetes-sigs/zeitgeist`](https://github.com/kubernetes-sigs/zeitgeist) - [`kyverno/chainsaw`](https://github.com/kyverno/chainsaw) - [`kyverno/kyverno`](https://github.com/kyverno/kyverno) - [`lintnet/lintnet`](https://github.com/lintnet/lintnet) - [`loft-sh/vcluster`](https://github.com/loft-sh/vcluster) - [`masasuzu/clrnd`](https://github.com/masasuzu/clrnd) - [`mikefarah/yq`](https://github.com/mikefarah/yq) - [`moby/buildkit`](https://github.com/moby/buildkit) - [`nao1215/atago`](https://github.com/nao1215/atago) - [`nao1215/gup`](https://github.com/nao1215/gup) - [`nao1215/sqly`](https://github.com/nao1215/sqly) - [`nodejs/node`](https://github.com/nodejs/node) - [`open-policy-agent/conftest`](https://github.com/open-policy-agent/conftest) - [`openbao/openbao/bao`](https://github.com/openbao/openbao) - [`openfga/cli`](https://github.com/openfga/cli) - [`opengrep/opengrep`](https://github.com/opengrep/opengrep) - [`openvex/vexctl`](https://github.com/openvex/vexctl) - [`orlangure/gocovsh`](https://github.com/orlangure/gocovsh) - [`purpleclay/dns53`](https://github.com/purpleclay/dns53) - [`rafaelespinoza/godfish`](https://github.com/rafaelespinoza/godfish) - [`rs/curlie`](https://github.com/rs/curlie) - [`santosr2/TerraTidy`](https://github.com/santosr2/TerraTidy) - [`sholdee/crd-schema-publisher`](https://github.com/sholdee/crd-schema-publisher) - [`siderolabs/talos`](https://github.com/siderolabs/talos) - [`sigstore/gitsign`](https://github.com/sigstore/gitsign) - [`smallstep/certificates`](https://github.com/smallstep/certificates) - [`smallstep/cli`](https://github.com/smallstep/cli) - [`stacklok/frizbee`](https://github.com/stacklok/frizbee) - [`suzuki-shunsuke/ci-info`](https://github.com/suzuki-shunsuke/ci-info) - [`suzuki-shunsuke/circleci-config-merge`](https://github.com/suzuki-shunsuke/circleci-config-merge) - [`suzuki-shunsuke/cmdx`](https://github.com/suzuki-shunsuke/cmdx) - [`suzuki-shunsuke/deny-self-approve`](https://github.com/suzuki-shunsuke/deny-self-approve) - [`suzuki-shunsuke/disable-checkout-persist-credentials`](https://github.com/suzuki-shunsuke/disable-checkout-persist-credentials) - [`suzuki-shunsuke/docfresh`](https://github.com/suzuki-shunsuke/docfresh) - [`suzuki-shunsuke/ghalint`](https://github.com/suzuki-shunsuke/ghalint) - [`suzuki-shunsuke/ghaperf`](https://github.com/suzuki-shunsuke/ghaperf) - [`suzuki-shunsuke/ghatm`](https://github.com/suzuki-shunsuke/ghatm) - [`suzuki-shunsuke/ghcp`](https://github.com/suzuki-shunsuke/ghcp) - [`suzuki-shunsuke/ghd2i`](https://github.com/suzuki-shunsuke/ghd2i) - [`suzuki-shunsuke/ghir`](https://github.com/suzuki-shunsuke/ghir) - [`suzuki-shunsuke/ghomfc`](https://github.com/suzuki-shunsuke/ghomfc) - [`suzuki-shunsuke/ghproj`](https://github.com/suzuki-shunsuke/ghproj) - [`suzuki-shunsuke/ghtkn`](https://github.com/suzuki-shunsuke/ghtkn) - [`suzuki-shunsuke/github-comment`](https://github.com/suzuki-shunsuke/github-comment) - [`suzuki-shunsuke/langcheck`](https://github.com/suzuki-shunsuke/langcheck) - [`suzuki-shunsuke/migrate-urfave-cli-v3`](https://github.com/suzuki-shunsuke/migrate-urfave-cli-v3) - [`suzuki-shunsuke/mkghtag`](https://github.com/suzuki-shunsuke/mkghtag) - [`suzuki-shunsuke/nllint`](https://github.com/suzuki-shunsuke/nllint) - [`suzuki-shunsuke/pinact`](https://github.com/suzuki-shunsuke/pinact) - [`suzuki-shunsuke/renovate-issue-action`](https://github.com/suzuki-shunsuke/renovate-issue-action) - [`suzuki-shunsuke/rgo`](https://github.com/suzuki-shunsuke/rgo) - [`suzuki-shunsuke/sort-issue-template`](https://github.com/suzuki-shunsuke/sort-issue-template) - [`suzuki-shunsuke/tfaction-go`](https://github.com/suzuki-shunsuke/tfaction-go) - [`suzuki-shunsuke/tfcmt`](https://github.com/suzuki-shunsuke/tfcmt) - [`suzuki-shunsuke/tfmv`](https://github.com/suzuki-shunsuke/tfmv) - [`suzuki-shunsuke/tfprovidercheck`](https://github.com/suzuki-shunsuke/tfprovidercheck) - [`suzuki-shunsuke/tfrstate`](https://github.com/suzuki-shunsuke/tfrstate) - [`suzuki-shunsuke/yodoc`](https://github.com/suzuki-shunsuke/yodoc) - [`takumin/zizmor-bin`](https://github.com/takumin/zizmor-bin) - [`technicalpickles/envsense`](https://github.com/technicalpickles/envsense) - [`terraform-linters/tflint`](https://github.com/terraform-linters/tflint) - [`terraprovider/statebridge`](https://github.com/terraprovider/statebridge) - [`tfmigrator/cli`](https://github.com/tfmigrator/cli) - [`tmknom/actdocs`](https://github.com/tmknom/actdocs) - [`tofuutils/tenv`](https://github.com/tofuutils/tenv) - [`trufflesecurity/trufflehog`](https://github.com/trufflesecurity/trufflehog) - [`txn2/kubefwd`](https://github.com/txn2/kubefwd) - [`ubugeeei-prod/vize`](https://github.com/ubugeeei-prod/vize) - [`updatecli/updatecli`](https://github.com/updatecli/updatecli) - [`version-fox/vfox`](https://github.com/version-fox/vfox) - [`yuyaban/gitlab-comment`](https://github.com/yuyaban/gitlab-comment)
https://entire.io/gh/jdx/mise/trails/109
Problem
If a resolved GitHub token contains a character that is illegal in an HTTP header — a newline is the easy way to get one — mise aborts the whole process instead of reporting a bad credential:
src/github.rsbuilt theAuthorizationheader withHeaderValue::from_str(..).unwrap(), so a malformed token became a SIGABRT with a coredump rather than an error message.After
Exit code 1, no panic, no coredump, and the token is not echoed back.
What changed
src/github.rs, one each insrc/gitlab.rsandsrc/forgejo.rs— now go through a sharedtokens::bearer_header, which mapsInvalidHeaderValueto the redacted error above. The GitLab and Forgejo sites carried an// Avoid panicking here. See #3547.comment directly above theunwrap();get_headersin those two modules now returnsResult<HeaderMap>so the error has somewhere to go.bearer_headeralso callsHeaderValue::set_sensitive(true), so reqwest redacts the credential from its own debug output.github_tokens.toml,gitlab_tokens.tomlandforgejo_tokens.tomlare now trimmed and dropped when blank. The environment-variable sources already did this inenv::scoped_var, so a token with a trailing newline worked fromGITHUB_TOKENbut panicked from the config file.packslip::repo_file_requestusedgithub::get_headers(..).ok()?, which would have turned this error into the misleading warning "comes from the source repository, which mise cannot read files from". It returnsResult<Option<..>>now, so a real failure propagates andNonestill means only "unsupported forge".No behavior change for well-formed tokens: header contents and token-source reporting are unchanged.
Validation
github::get_headersreturns an error rather than panicking.cargo clippy --workspace --all-features --all-targets -- -D warningsclean;mise run lintclean.mainin my local sandbox (pacman,system::remote*,terapath tests) — pre-existing and unrelated.mise latest github:jdx/mise@lateststill resolves.Reported in #13471
AI-assisted — Tool: Claude Code; model: anthropic/claude-opus-5; version: 2.1.236.
🤖 Generated with Claude Code
Note
Medium Risk
Touches authentication header construction across GitHub, GitLab, and Forgejo download/API paths; behavior change is limited to malformed tokens (error vs panic) but the surface area is security-sensitive.
Overview
Fixes process aborts when a GitHub/GitLab/Forgejo token contains characters illegal in HTTP headers (e.g. a trailing newline in a tokens file).
Authorization headers — Replaces
HeaderValue::from_str(..).unwrap()with sharedtokens::bearer_header, which returns a redacted error instead of panicking and marks the value sensitive for reqwest debug output. GitLab and Forgejoget_headersnow returnResult<HeaderMap>; download and API paths inbackend/github.rs,spm.rs, and related callers propagate with?.Token loading — Tokens from
*_tokens.tomlare trimmed and whitespace-only entries are dropped, aligning with env-var handling.Packslip —
repo_file_requestreturnsResult<Option<..>>so a malformed token surfaces as a real error instead of the misleading “unsupported forge” warning from.ok()?.Well-formed tokens behave unchanged. New unit tests cover invalid tokens, TOML trim, and GitHub
get_headerserror paths.Reviewed by Cursor Bugbot for commit 45902ec. Bugbot is set up for automated code reviews on this repo. Configure here.
Summary by CodeRabbit
Bug Fixes
Tests