JCMais / JCMais/node-libcurl

Possible use-after-free in retained HTTP/2 push headers

Open
#452 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
TypeScript
Stars
718
Forks
135
PR merge metrics
No merged PRs in 30d

Description

# Possible use-after-free in retained HTTP/2 push headers

I found a possible use-after-free if an `Http2PushFrameHeaders` object is retained after the push callback returns.

Files: `src/Multi.cc`, `src/Http2PushFrameHeaders.cc`

Functions: `Multi::CbPushFunction`, `Http2PushFrameHeaders::GetByIndex`, `Http2PushFrameHeaders::GetByName`

Relevant code:

```cpp
auto headersExternal = Napi::External::New(env, headers);
headersExternal.TypeTag(&HTTP2_PUSH_FRAME_HEADERS_TYPE_TAG);

auto http2PushFrameJsObj = curl->Http2PushFrameHeadersConstructor.New({
headersExternal,
Napi::Number::New(env, numberOfHeaders),
});

Napi::Value returnValueCallback = callback.MakeCallback(obj->Value(),
{
parentEasyJsObj,
childEasyJsObj,
http2PushFrameJsObj,
},
asyncContext);
```

The wrapper stores the raw `curl_pushheaders*`:

```cpp
auto maybeHeadersExternal = info[0].As>();
this->headers = maybeHeadersExternal.Data();
```

Later method calls use that stored pointer:

```cpp
char* result = curl_pushheader_bynum(this->headers, static_cast(index));
```

```cpp
char* result = curl_pushheader_byname(this->headers, name.c_str());
```

libcurl documents these push-header accessors as valid only during the push
callback. The TypeScript docs also warn that `Http2PushFrameHeaders` must not be
used outside the callback. However, the native wrapper does not enforce this
lifetime boundary, so ordinary JavaScript can retain the object and call
`getByIndex()` or `getByName()` after libcurl has freed the callback-local
header data.

Suggested fix: copy the headers into owned storage before passing them to
JavaScript, or invalidate the wrapper immediately after the callback returns so
later method calls throw instead of using a stale `curl_pushheaders*`.

Contributor guide

Open the contributing guide

Research direction

Start by tracing Multi::CbPushFunction in src/Multi.cc and the wrapper methods in src/Http2PushFrameHeaders.cc. Verify how the retained curl_pushheaders* pointer behaves after the push callback returns. Done means retained JavaScript objects no longer access freed header data, either by copying headers into owned storage or by invalidating later calls as described; add coverage if the existing test layout supports it.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp, javascript, node.js
Domain
api, backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
52/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.