Files

7.7 KiB
Raw Permalink Blame History

Security

goget implements multiple security features to protect both the client and server during file transfers. This document covers TLS configuration, certificate handling, checksum verification, PGP support, HSTS, and SSRF protection.

TLS / HTTPS

Default Security

  • TLS 1.2 minimum — TLS 1.0 and 1.1 are disabled
  • Certificate verification — Enabled by default against system CA bundle
  • HTTP/2 support — Automatic ALPN negotiation

Certificate Pinning

Pin a specific certificate by its SHA-256 hash. This works across every TLS-bearing protocol goget supports: HTTPS, FTPS, Gemini, and WebDAVS.

goget --pinned-cert "a1b2c3d4e5f6..." --url https://example.com
goget --pinned-cert "a1b2c3d4e5f6..." --url ftps://ftp.example.com/file
goget --pinned-cert "a1b2c3d4e5f6..." --url gemini://geminiprotocol.net
goget --pinned-cert "a1b2c3d4e5f6..." --url webdavs://dav.example.com/file

If the leaf certificate's SHA-256 doesn't match, the connection is aborted.

SSH Host-Key Pinning (SFTP)

Pin the SSH host key for SFTP by its OpenSSH fingerprint (the same value printed by ssh-keygen -lf ~/.ssh/known_hosts). Pinning takes precedence over --ssh-insecure and the known_hosts file.

goget --pinned-host-key "SHA256:AAAAC3NzaC1lZDI1NTE5AAAAIE+HHi0MtRj4VPl8mdP8gniGZDRb0SZTdI2TPxRyCm1H" \
      --url sftp://example.com/file

The raw lowercase-hex SHA-256 of the key wire format is also accepted.

Client Certificates (mTLS)

Authenticate the client to the server with mutual TLS:

goget --cert client.pem --key client.key --url https://mtls.example.com

Custom CA Bundle

goget --cacert custom-ca.pem --url https://internal.example.com

Insecure Mode

Disable all TLS verification (⚠ for testing only):

goget --insecure --url https://self-signed.local

SSLKEYLOGFILE

Log TLS session keys for Wireshark debugging:

goget --ssl-key-log tls.keys --url https://example.com
# Then: Wireshark → Preferences → TLS → (Pre-)Master-Secret log filename → tls.keys

HSTS (HTTP Strict Transport Security)

Per RFC 6797, goget maintains an HSTS cache that automatically upgrades HTTP connections to HTTPS for known hosts.

How It Works

sequenceDiagram
    participant Client as goget
    participant Server as Server

    Client->>Server: GET http://example.com
    Server-->>Client: 200 OK + Strict-Transport-Security: max-age=31536000
    Client->>Client: Store: example.com → 365 days
    Client->>Server: GET http://example.com/page (later)
    Client->>Client: HSTS cache hit → upgrade to HTTPS
    Client->>Server: GET https://example.com/page

Cache Location

~/.config/goget/hsts

Can be overridden with GOGET_HSTS environment variable or --hsts-file.

Cache Format

[
  {
    "host": "example.com",
    "include_subdomains": true,
    "expires": "2027-06-01T00:00:00Z"
  }
]

Expired entries are automatically pruned on load.

Checksum Verification

Verify file integrity after download:

Direct Hash

goget --checksum "a1b2c3d4e5f6..." --checksum-algo sha256 --url https://example.com/file.zip

Supported algorithms:

Algorithm Flag Value Hash Length
SHA-256 sha256 64 hex chars
SHA-512 sha512 128 hex chars
SHA3-256 sha3-256 64 hex chars
SHA3-512 sha3-512 128 hex chars
BLAKE2b blake2b 128 hex chars
MD5 md5 32 hex chars

Checksum File

Supports standard SHA256SUMS format:

# SHA256SUMS file:
# a1b2c3d4...  file.zip
# e5f6a7b8...  *file.tar.gz

goget --checksum-file SHA256SUMS --url https://example.com/file.zip

Both plain (file.zip) and binary-mode (*file.tar.gz) formats are supported.

Error Handling

On mismatch:

Checksum mismatch
  Expected: a1b2c3d4...
  Actual:   e5f6a7b8...

The error is a typed core.GogetError with Type: "CHECKSUM" and Details["expected"] / Details["actual"].

PGP / GPG

Signature Verification

Verify PGP detached signatures:

# With explicit signature file
goget --pgp-verify --pgp-sig file.sig --pgp-key public.key --url https://example.com/file

# Auto-detect signature file (tries: file.asc, file.sig, file.gpg)
goget --pgp-verify --pgp-key public.key --url https://example.com/file

Decryption

Decrypt PGP-encrypted files:

# Decrypt with key and passphrase
goget --pgp-decrypt --pgp-key private.key --pgp-passphrase "secret" --url https://example.com/file.gpg

# Read passphrase from file (safer)
goget --pgp-decrypt --pgp-key private.key --pgp-passphrase-file pass.txt --url https://example.com/file.gpg

The decrypted file replaces the encrypted one:

  • file.gpgfile
  • file.pgpfile
  • file.ascfile
  • Other → filename.decrypted

Note: PGP functionality uses golang.org/x/crypto/openpgp, which is frozen. A replacement will be provided in a future release.

SSRF Protection

By default, goget blocks connections to private and internal IP ranges:

Range CIDR Description
10.0.0.0/8 Private RFC 1918
172.16.0.0/12 Private RFC 1918
127.0.0.0/8 Loopback Internal
169.254.0.0/16 Link-local Auto-configuration
::1/128 IPv6 loopback Internal

IPv4-Mapped IPv6 Normalization

DNS-controlled IPv4-mapped IPv6 addresses (e.g. ::ffff:10.0.0.1) are now normalized to plain IPv4 before the private-IP check. This prevents an attacker from reaching internal hosts through DNS responses that embed IPv4 addresses in IPv6 form. Covered by a 17-case unit test in the transport layer.

Override with --allow-private:

goget --allow-private --url https://internal.example.com

DNS Security

Custom Resolvers

Bypass system DNS for specific queries:

goget --dns-servers 1.1.1.1,8.8.8.8 --url https://example.com

IPv6-First

The transport dialer prefers IPv6 and only falls back to IPv4 when no IPv6 address is available. This reduces NAT-related attack surface:

# IPv6 only (abort if no IPv6)
goget --no-ipv4 --url https://example.com

Credential Safety

Safe Error Logging

When a URL contains user credentials (https://user:pass@example.com), core.SafeURL() strips them from error messages and logs:

// Original: https://admin:secret@api.example.com/data
// Logged:   https://api.example.com/data

OAuth Error Sanitization

Non-2xx OAuth responses are sanitized to extract only the structured error / error_description fields (RFC 6749 §5.2). Providers that echo client_secret or other secrets in their error response bodies can no longer leak them into goget logs or error displays.

Config Sanitization

config.Save() strips sensitive fields before writing to disk:

  • auth.password
  • auth.oauth.client_secret
  • auth.oauth.access_token
  • auth.oauth.refresh_token

File Permission Hardening

Configuration files (config.toml), resume metadata sidecars (.goget.meta), and atomic temp files are written with mode 0600 (owner-only), so OAuth tokens, source URLs, and downloaded payloads are never world-readable on multi-user systems.

Environment Variables

  • GOGET_CONFIG — alternative config file path
  • GOGET_PASSWORD — password override (no file storage)
  • GOGET_HSTS — alternative HSTS cache path
  • NO_COLOR — disable color output

Timeouts & Limits

Feature Default Description
Connection timeout 30s (auto) Smart calculation based on file size
Max total time — (--max-time) Abort if exceeded
Max file size — (--max-filesize) Abort if server response exceeds limit
Max retries 3 Exponential backoff with 30s cap
Retry delay 1s initial, 2× multiplier Configurable via --retry-delay