Vulnerability Report: GO-2025-3488

An attacker can pass a malicious malformed token which causes unexpected memory to be consumed during parsing.

무엇이 패치되었을까 보니

// Verify tests whether the provided JWT token's signature was produced by the private key
// associated with the supplied public key.
func Verify(token string, key *rsa.PublicKey) error {
	parts := strings.Split(token, ".")
	if len(parts) != 3 {
		return errors.New("jws: invalid token received, token must have 3 parts")
	}
// Verify tests whether the provided JWT token's signature was produced by the private key
// associated with the supplied public key.
func Verify(token string, key *rsa.PublicKey) error {
	if strings.Count(token, ".") != 2 {
		return errors.New("jws: invalid token received, token must have 3 parts")
	}

	parts := strings.SplitN(token, ".", 3)

이렇게 바뀌었다.

기존 코드의 문제점은

parts := strings.Split(token, ".")
if len(parts) != 3 {
    return errors.New("jws: invalid token received, token must have 3 parts")
}

위 부분에서

공격자가 아래와 같은 악의적인 토큰을 전송할 수 있다

header.payload.signature...................." (수천 개의 점이 포함된 문자열)

strings.Split()은 구분자(.)를 기준으로 문자열을 모두 분할하므로 입력된 모든 점(.)에 대해 분할을 수행, 각 분할된 부분에 대해 새로운 메모리를 할당

결과적으로 수천 개의 빈 문자열을 포함하는 슬라이스가 생성이 된다.

예시 코드로 보는 메모리 소비

maliciousToken := "a" + strings.Repeat(".", 1000000)
parts := strings.Split(maliciousToken, ".") // 1,000,001개의 문자열이 메모리에 할당됨

패치를 통해서 아래와 같은 장점들이 생겼다!

  1. 메모리 소비가 입력 크기와 관계없이 일정하게 유지됨
  2. DoS(Denial of Service) 공격 가능성을 차단
  3. 불필요한 메모리 할당을 방지하여 전반적인 성능 향상