Curl -fsSL Why requests return 302 after upgrading an old version to Debian 13

root@debian:~# curl -fsSL -v https://my.com/xxx.sh | bash
* Host my.com:443 was resolved.
* IPv6: 2606:4700:3036::ac43:baaa, 2606:4700:3037::6815:409c
* IPv4: 104.21.64.156, 172.67.186.170
*   Trying [2606:4700:3036::ac43:baaa]:443...
* Immediate connect fail for 2606:4700:3036::ac43:baaa: 网络不可达
*   Trying [2606:4700:3037::6815:409c]:443...
* Immediate connect fail for 2606:4700:3037::6815:409c: 网络不可达
*   Trying 104.21.64.156:443...
* ALPN: curl offers h2,http/1.1
} [5 bytes data]
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
} [1567 bytes data]
*  CAfile: /etc/ssl/certs/ca-certificates.crt
*  CApath: /etc/ssl/certs
{ [5 bytes data]
* TLSv1.3 (IN), TLS handshake, Server hello (2):
{ [1210 bytes data]
* TLSv1.3 (IN), TLS change cipher, Change cipher spec (1):
{ [1 bytes data]
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
{ [19 bytes data]
* TLSv1.3 (IN), TLS handshake, Certificate (11):
{ [2475 bytes data]
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
{ [80 bytes data]
* TLSv1.3 (IN), TLS handshake, Finished (20):
{ [36 bytes data]
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
} [1 bytes data]
* TLSv1.3 (OUT), TLS handshake, Finished (20):
} [36 bytes data]
* SSL connection using TLSv1.3 / TLS_AES_128_GCM_SHA256 / X25519MLKEM768 / id-ecPublicKey
* ALPN: server accepted h2
* Server certificate:
*  subject: CN=my.com
*  start date: Jul 14 21:45:13 2026 GMT
*  expire date: Oct 12 22:45:11 2026 GMT
*  subjectAltName: host "my.com" matched cert's "my.com"
*  issuer: C=US; O=Google Trust Services; CN=WE1
*  SSL certificate verify ok.
*   Certificate level 0: Public key type EC/prime256v1 (256/128 Bits/secBits), signed using ecdsa-with-SHA256
*   Certificate level 1: Public key type EC/prime256v1 (256/128 Bits/secBits), signed using ecdsa-with-SHA384
*   Certificate level 2: Public key type EC/secp384r1 (384/192 Bits/secBits), signed using ecdsa-with-SHA384
* Connected to my.com (104.21.64.156) port 443
* using HTTP/2
* [HTTP/2] [1] OPENED stream for https://my.com/xxx.sh
* [HTTP/2] [1] [:method: GET]
* [HTTP/2] [1] [:scheme: https]
* [HTTP/2] [1] [:authority: my.com]
* [HTTP/2] [1] [:path: /xxx.sh]
* [HTTP/2] [1] [user-agent: curl/8.14.1]
* [HTTP/2] [1] [accept: */*]
} [5 bytes data]
> GET /xxx.sh HTTP/2
> Host: my.com
> User-Agent: curl/8.14.1
> Accept: */*
> 
* Request completely sent off
{ [5 bytes data]
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
{ [214 bytes data]
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
{ [214 bytes data]
< HTTP/2 403 
< date: Sun, 30 Aug 2026 11:49:26 GMT
< content-type: text/html; charset=UTF-8
< content-length: 5247
< accept-ch: Sec-CH-UA-Bitness, Sec-CH-UA-Arch, Sec-CH-UA-Full-Version, Sec-CH-UA-Mobile, Sec-CH-UA-Model, Sec-CH-UA-Platform-Version, Sec-CH-UA-Full-Version-List, Sec-CH-UA-Platform, Sec-CH-UA, UA-Bitness, UA-Arch, UA-Full-Version, UA-Mobile, UA-Model, UA-Platform-Version, UA-Platform, UA
< cf-mitigated: challenge
< content-security-policy: default-src 'none'; script-src 'nonce-TXPRUoIFMwZsxoO8q6EhQb' 'unsafe-eval' https://challenges.cloudflare.com; script-src-attr 'none'; style-src 'unsafe-inline'; img-src 'self' https://challenges.cloudflare.com; connect-src 'self' https://challenges.cloudflare.com; frame-src 'self' https://challenges.cloudflare.com blob:; child-src 'self' https://challenges.cloudflare.com blob:; worker-src blob:; form-action http: https:; base-uri 'self'
< server: cloudflare
< critical-ch: Sec-CH-UA-Bitness, Sec-CH-UA-Arch, Sec-CH-UA-Full-Version, Sec-CH-UA-Mobile, Sec-CH-UA-Model, Sec-CH-UA-Platform-Version, Sec-CH-UA-Full-Version-List, Sec-CH-UA-Platform, Sec-CH-UA, UA-Bitness, UA-Arch, UA-Full-Version, UA-Mobile, UA-Model, UA-Platform-Version, UA-Platform, UA
< cross-origin-embedder-policy: require-corp
< cross-origin-opener-policy: same-origin
< cross-origin-resource-policy: same-origin
< origin-agent-cluster: ?1
< permissions-policy: accelerometer=(),camera=(),clipboard-read=(),clipboard-write=(),geolocation=(),gyroscope=(),hid=(),magnetometer=(),microphone=(),payment=(),publickey-credentials-get=(),screen-wake-lock=(),serial=(),sync-xhr=(),usb=(),xr-spatial-tracking=*
< referrer-policy: same-origin
< server-timing: chlray;desc="a3339279fe2cdd9f"
< x-content-type-options: nosniff
< x-frame-options: SAMEORIGIN
{ [5 bytes data]
< report-to: {"group":"cf-nel","max_age":604800,"endpoints":[{"url":"https://a.nel.cloudflare.com/report/v4?s=PD7Gu%2FpUFWg%2FuX2TMOmXfzcJHyTG6pw3K3akFrmuUU1pFt5kMjUelB4STxhkHV2k3rt2Kgw0wRAzBJHI%2B1RZflQTVkBDrSMNXzQmMLSp12iTVxv1f8ageu5pT0zn%2BTQ%3D"}]}
< nel: {"report_to":"cf-nel","success_fraction":0.0,"max_age":604800}
< cf-ray: a3339279fe2cdd9f-HKG
< alt-svc: h3=":443"; ma=86400
* The requested URL returned error: 403
< 
{ [5 bytes data]
* Connection #0 to host my.com left intact
curl: (22) The requested URL returned error: 403
root@debian:~#

The other one returns a normal 200. Do you know where the configuration problem might be?

root@debian:~# curl -fsSL -v https://my.com/xxx.sh | bash
* Host my.com:443 was resolved.
* IPv6: 2606:4700:3036::ac43:baaa, 2606:4700:3037::6815:409c
* IPv4: 172.67.186.170, 104.21.64.156
*   Trying [2606:4700:3036::ac43:baaa]:443...
* Immediate connect fail for 2606:4700:3036::ac43:baaa: 网络不可达
*   Trying [2606:4700:3037::6815:409c]:443...
* Immediate connect fail for 2606:4700:3037::6815:409c: 网络不可达
*   Trying 172.67.186.170:443...
* ALPN: curl offers h2,http/1.1
} [5 bytes data]
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
} [1567 bytes data]
*  CAfile: /etc/ssl/certs/ca-certificates.crt
*  CApath: /etc/ssl/certs
{ [5 bytes data]
* TLSv1.3 (IN), TLS handshake, Server hello (2):
{ [1210 bytes data]
* TLSv1.3 (IN), TLS change cipher, Change cipher spec (1):
{ [1 bytes data]
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
{ [19 bytes data]
* TLSv1.3 (IN), TLS handshake, Certificate (11):
{ [2475 bytes data]
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
{ [79 bytes data]
* TLSv1.3 (IN), TLS handshake, Finished (20):
{ [36 bytes data]
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
} [1 bytes data]
* TLSv1.3 (OUT), TLS handshake, Finished (20):
} [36 bytes data]
* SSL connection using TLSv1.3 / TLS_AES_128_GCM_SHA256 / X25519MLKEM768 / id-ecPublicKey
* ALPN: server accepted h2
* Server certificate:
*  subject: CN=my.com
*  start date: Jul 14 21:45:13 2026 GMT
*  expire date: Oct 12 22:45:11 2026 GMT
*  subjectAltName: host "my.com" matched cert's "my.com"
*  issuer: C=US; O=Google Trust Services; CN=WE1
*  SSL certificate verify ok.
*   Certificate level 0: Public key type EC/prime256v1 (256/128 Bits/secBits), signed using ecdsa-with-SHA256
*   Certificate level 1: Public key type EC/prime256v1 (256/128 Bits/secBits), signed using ecdsa-with-SHA384
*   Certificate level 2: Public key type EC/secp384r1 (384/192 Bits/secBits), signed using ecdsa-with-SHA384
* Connected to my.com (172.67.186.170) port 443
* using HTTP/2
* [HTTP/2] [1] OPENED stream for https://my.com/xxx.sh
* [HTTP/2] [1] [:method: GET]
* [HTTP/2] [1] [:scheme: https]
* [HTTP/2] [1] [:authority: my.com]
* [HTTP/2] [1] [:path: /xxx.sh]
* [HTTP/2] [1] [user-agent: curl/8.14.1]
* [HTTP/2] [1] [accept: */*]
} [5 bytes data]
> GET /xxx.sh HTTP/2
> Host: my.com
> User-Agent: curl/8.14.1
> Accept: */*
> 
* Request completely sent off
{ [5 bytes data]
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
{ [214 bytes data]
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
{ [214 bytes data]
< HTTP/2 200 
< date: Sun, 30 Aug 2026 11:49:35 GMT
< content-type: application/x-sh
< content-length: 1395
< x-content-type-options: nosniff
< report-to: {"group":"cf-nel","max_age":604800,"endpoints":[{"url":"https://a.nel.cloudflare.com/report/v4?s=p%2FQEpJH1Nqbz2t8VkE6VDnU2u8020WBvb9ytOCPyTr9a1MWpl3KUFoSgSMEMFFYX5fQejugfzBi8gp3MoY2YF2xI7pqwaYryn663osbEsyGPk9pNsy6m%2FfgnBV0pw%2B0%3D"}]}
< nel: {"report_to":"cf-nel","success_fraction":0.0,"max_age":604800}
< access-control-allow-origin: *
< cache-control: public, max-age=0, must-revalidate
< etag: "a6a11fe0420619d4afb855df244b6417"
< referrer-policy: strict-origin-when-cross-origin
< server: cloudflare
< cf-cache-status: DYNAMIC
< cf-ray: a33392b099cf1fbb-HKG
< alt-svc: h3=":443"; ma=86400
< 
{ [5 bytes data]
* Connection #0 to host my.com left intact
root@debian:~# 

The problem is Cloudflare asking for a challenge:

HTTP/2 403
cf-mitigated: challenge
server: cloudflare

It has nothing to do with this, it’s not the reason. I’ll figure it out myself slowly, hahaha. Thanks!

I’m sorry, but based on the output you posted, curl can’t retrieve the first file because Cloudflare is requiring a challenge that curl isn’t able to pass. That’s the reason for the 403 error. If there are other variables or factors we’re not aware of, then…