Releases: webcodr/jwtd
Release list
v4.0.1
Homebrew: reverted to a formula
4.0.0 briefly shipped jwtd as a Homebrew cask. macOS Gatekeeper blocks casks whose binaries are not notarized, so jwtd failed to start with "could not be verified", and casks do not work on Linux at all. 4.0.x now ships as a formula again, which fixes both.
If you installed 4.0.0 via the cask, switch back once:
brew uninstall --cask jwtd
brew update
brew install webcodr/tap/jwtdbrew install webcodr/tap/jwtd works on both macOS and Linux again.
What's Changed
- docs: clear RELEASE_NOTES.md after 4.0.0 by @bsg62 in #6
- revert: publish Homebrew as a formula instead of a cask by @bsg62 in #7
Full Changelog: v4.0.0...v4.0.1
v3.0.0
Breaking changes
- Invalid signatures now exit nonzero. When a key is provided via
--key/-korJWTD_KEY, an invalid JWS signature still printsSignature: INVALIDwith the reason, but jwtd now exits with status 1. Scripts that gate on jwtd's exit status must expect failure for tokens that do not verify. - Malformed structured keys are rejected. Key input that looks like PEM, DER, an X.509 certificate, or a JWK/JWK Set but fails to parse is now an error. Previously such data silently fell back to being used as a raw symmetric key, which could turn a public certificate or a typo'd key file into an attacker-known HMAC secret. Opaque text and binary key files continue to work as symmetric keys.
- Error output format changed. Runtime errors print a single
Error: ...line to stderr; Cobra's usage text is no longer appended.
New
- X.509 certificates as verification keys. PEM and DER certificates are accepted anywhere a key is; the public key is extracted for signature verification. SEC 1 EC keys are also supported.
- Complete JWE protected header display. Every field of the compact protected header is shown, not just
alg/kid/jwk. - Exact number display. JSON numbers in headers, claims, and decrypted payloads are printed with full precision (no float64 rounding of large values), and
iat/exp/nbfformatting handles fractional timestamps. - Terminal-safe output. Control characters, DEL, C1 controls, invalid UTF-8, and bidirectional override characters in token content are escaped instead of being written raw to the terminal.
- Malformed or trailing JSON data in any displayed segment is rejected instead of partially rendered.
Release integrity
Releases are now built by a hardened pipeline: SHA-pinned actions, dispatch restricted to main, semver validation, the release tag cryptographically bound to the built commit, reproducible archives, and byte-for-byte verification of published assets against the build artifacts before the release is published.
Full changelog: v2.1.1...v3.0.0
v2.1.1
Fixed
- Signature verification reports only cryptographic validity. An expired token with a valid signature was shown as
Signature: INVALID; claims validation no longer affects the verdict. - Algorithm confusion is rejected outright. Verification restricts accepted
algvalues to those compatible with the provided key type (RS*/PS* for RSA, ES* for ECDSA, EdDSA for Ed25519, HS* for symmetric keys) and reports a clear reason. - No more duplicate output for token-lookalike payloads. A decrypted JWE payload that merely looks like a nested JWT/JWE (e.g. text containing dots) no longer produces a stray nested label and partial output.
- JWE part metadata flags corrupt encoding. Parts that are not valid base64url are shown as
invalid base64urlinstead of0 bytes. - go-jose updated to 4.1.4, fixing a high-severity panic in JWE decryption (GHSA advisory).
Added
raw:key prefix.--key raw:<secret>(also viaJWTD_KEY) passes a literal symmetric secret, bypassing file and base64 detection — previously a plain-text secret that happened to be valid base64 was silently decoded into the wrong bytes.- Friendlier key files. Text key files get the trailing newline editors add trimmed; binary key material is used byte-for-byte.
- Line-wrapped tokens just work. Tokens copied from logs or emails with embedded newlines are accepted via argument, stdin, and the interactive prompt.
CI
- Releases are published immediately instead of as drafts, so the Homebrew formula never points at unpublished download URLs.
- CI now enforces
gofmtandgo vet.
Full Changelog: v2.1.0...v2.1.1
v2.1.0
Features
- --version flag — jwtd --version now prints the build version, injected at compile time via ldflags
- Timestamps show original epoch value — Formatted timestamp fields now display both the human-readable date and the original Unix value, e.g. 2018-01-18T01:30:22Z (1516239022)
Bug Fixes
- JSON array payloads in JWE — Decrypted JWE payloads that are JSON arrays are now pretty-printed instead of causing a fallback to raw text
- Error propagation — printSection errors are now returned to the caller instead of being written to stderr
- Unchecked errors — All fmt.Fprintln, color.Fprintln, color.Fprintf, and rl.Close() return values are now properly checked and propagated
Refactoring
- Use cmd.OutOrStdout() instead of hardcoded os.Stdout for testable output
- verifySignature returns an error instead of printing directly to stderr
- Algorithm slices use package-level var declarations instead of function calls
Tests
- Added Ed25519 JWS signature verification coverage (valid with private key, valid with public key, invalid with wrong key)
Chores
- Ignore IntelliJ/IDEA project files
- Update to Go 1.26.1
v2.0.0
What's New
- JWE (JSON Web Encryption) support — JWE tokens are automatically detected (5 dot-separated parts) and their protected headers displayed. Provide a decryption key with --key/-k to decrypt and view the plaintext payload.
- JWS signature verification — Use --key/-k with a JWT to verify its signature. Displays Signature: VALID or Signature: INVALID with error details. Supports RSA, ECDSA, Ed25519, and HMAC algorithms.
- JWK and JWK Set key format — --key now accepts JWK (JSON Web Key) files and JWK Sets in addition to PEM and DER. For JWK Sets, the first key is used.
- Public key loading — Both private and public keys are supported for all formats (PEM, DER, JWK, base64). Private keys are automatically converted to their public counterpart for signature verification.
- JWTD_KEY environment variable — Set a default key without passing --key on every invocation. The --key flag always takes precedence.
- Nested token detection — Decrypted JWE payloads that are themselves a JWT or another JWE are automatically detected and decoded recursively.
- Interactive prompt updated — Now displays Enter JWT/JWE: to reflect support for both token types.
v1.2.0
v1.1.0
- Add artifact compression
- Add support for Linux ARM64 and Windows ARM64