fix(remote): refuse a redirect that drops TLS

The scheme was only checked on the URL the user wrote. A server answering
an https URL with a redirect to http was followed by the client without
any further check, so both the HEAD probe and the download travelled in
the clear, and a network attacker could substitute the Taskfile that is
about to be executed.

CheckRedirect now refuses an https to http hop. --insecure does not
loosen it: requesting an http entrypoint is the user's decision, being
sent to one is the server's. Setting CheckRedirect also replaces Go's
default cap, so the ten-hop limit is kept explicitly.

The three call sites turned almost every client error into a generic
download failure, which would have hidden the reason; TaskfileNotSecureError
is now passed through, with wording of its own for the redirect case since
--insecure is not a way out of it.
This commit is contained in:
Valentin Maerten
2026-08-23 13:06:37 +02:00
parent b250872d9a
commit 25fc28927d
6 changed files with 138 additions and 4 deletions

View File

@@ -102,9 +102,18 @@ func (err *TaskfileNotTrustedError) Code() int {
// remote Taskfile over an insecure connection.
type TaskfileNotSecureError struct {
URI string
// Redirect reports that the insecure URI was reached through a redirect
// rather than requested, in which case --insecure does not allow it.
Redirect bool
}
func (err *TaskfileNotSecureError) Error() string {
if err.Redirect {
return fmt.Sprintf(
`task: Taskfile %q was redirected to over an insecure connection. Point the URL at the final location instead`,
filepath.ToSlash(err.URI),
)
}
return fmt.Sprintf(
`task: Taskfile %q cannot be downloaded over an insecure connection. You can override this by using the --insecure flag`,
filepath.ToSlash(err.URI),