CVE-2022-27775: Bad local IPv6 connection reuse
What the report claims
Curl reuses IPv6 connections without considering zone index, causing incorrect connection reuse.
Compare with curl's recorded outcome
Known vulnerability
A real vulnerability: CVE-2022-27775 Bad local IPv6 connection reuse
Shown for comparison after analysis. The pipeline did not see this label.
ProveIt's finding
The available evidence does not settle the report. A maintainer should investigate.
Why this finding?
- The report describes a concrete, plausible flaw in IPv6 connection reuse with zone index and provides reproducible steps.
- The provided source code snippets do not include the connection reuse logic (curl_conn.c, Curl_conninfo, etc.) that would confirm or contradict the claim.
- Per the rules, when the deciding code is not provided, claims are not_verifiable and the verdict is needs_human.
What still needs checking
- Source code for connection pooling/reuse (likely lib/conncache.c, lib/url.c, or lib/connect.c in this revision) showing how IPv6 addresses are compared for reuse, including whether zone index (scope_id) is part of the comparison.
How this analysis ran 5 claims · 0 citations verified
Checked against curl master on 2022-04-21 (e498a9b1fe59). Dev evaluation split. Citation verification checks that a referenced line was in the evidence; it does not prove the model interpreted it correctly.
Review a draft reply to the reporter
Edit and verify before sending.
Thank you for the detailed report and reproduction steps. The connection reuse logic for IPv6 (including zone index handling) is not in the source snippets we were given for triage. Could you point to the specific file and function (e.g., in conncache.c or connect.c) where IPv6 addresses are compared for connection reuse? That will let us verify whether the zone index is checked.
Inspect all claims and source code 5 claims · 4 code excerpts
Report claims
curl reuses connections based on IPv6 address without checking zone index
Read the reasoning
The claim concerns connection reuse logic for IPv6 addresses with zone index. The provided source snippets (urldata.h, easy.c, urlapi.c) do not contain connection pooling/reuse code. Files referenced in the claim (curl_conn.c, Curl_conninfo, Curl_conninfo_copy) are not included in the provided source.
in connection reuse logic for IPv6 addresses
Read the reasoning
The claim points to connection reuse logic in curl_conn.c and related functions. None of these files or functions appear in the provided source code snippets.
using IPv6 address with zone index in URL
Read the reasoning
The claim describes using an IPv6 address with zone index in a URL (e.g., `[ipv6addr%25lo]`). The provided urlapi.c snippet only shows the `curl_url()` allocator; the URL parsing logic that handles zone indices is not present.
disclosure of confidential information via wrong connection reuse
Read the reasoning
The impact claim depends on the underlying flaw (C1) being real. Since the connection reuse code is not provided, the impact cannot be verified from the given source.
connect to server via IPv6 address and reuse with zone index variant
Read the reasoning
The reproduction steps are clear, but the code path they exercise (connection reuse with IPv6 zone index) is not in the provided source snippets.
Read the original report
Source code
| 122 | typedef CURLcode (*Curl_datastream)(struct Curl_easy *data, |
| 123 | struct connectdata *conn, |
| 124 | int *didwhat, |
| 125 | bool *done, |
| 126 | int select_res); |
| 127 | #endif |
| 128 | |
| 129 | #include "mime.h" |
| 130 | #include "imap.h" |
| 131 | #include "pop3.h" |
| 132 | #include "smtp.h" |
| 133 | #include "ftp.h" |
| 134 | #include "file.h" |
| 135 | #include "vssh/ssh.h" |
| 136 | #include "http.h" |
| 137 | #include "rtsp.h" |
| 138 | #include "smb.h" |
| 139 | #include "mqtt.h" |
| 140 | #include "wildcard.h" |
| 141 | #include "multihandle.h" |
| 142 | #include "quic.h" |
| 143 | #include "c-hyper.h" |
| 144 | |
| 145 | #ifdef HAVE_GSSAPI |
| 146 | # ifdef HAVE_GSSGNU |
| 147 | # include <gss.h> |
| 148 | # elif defined HAVE_GSSAPI_GSSAPI_H |
| 149 | # include <gssapi/gssapi.h> |
| 150 | # else |
| 151 | # include <gssapi.h> |
| 152 | # endif |
| 153 | # ifdef HAVE_GSSAPI_GSSAPI_GENERIC_H |
| 154 | # include <gssapi/gssapi_generic.h> |
| 155 | # endif |
| 156 | #endif |
| 157 | |
| 158 | #ifdef HAVE_LIBSSH2_H |
| 159 | #include <libssh2.h> |
| 160 | #include <libssh2_sftp.h> |
| 161 | #endif /* HAVE_LIBSSH2_H */ |
| 162 | |
| 163 | #define READBUFFER_SIZE CURL_MAX_WRITE_SIZE |
| 164 | #define READBUFFER_MAX CURL_MAX_READ_SIZE |
| 165 | #define READBUFFER_MIN 1024 |
| 166 | |
| 167 | /* The default upload buffer size, should not be smaller than |
| 168 | CURL_MAX_WRITE_SIZE, as it needs to hold a full buffer as could be sent in |
| 169 | a write callback. |
| 170 | |
| 171 | The size was 16KB for many years but was bumped to 64KB because it makes |
| 172 | libcurl able to do significantly faster uploads in some circumstances. Even |
| 173 | larger buffers can help further, but this is deemed a fair memory/speed |
| 174 | compromise. */ |
| 175 | #define UPLOADBUFFER_DEFAULT 65536 |
| 176 | #define UPLOADBUFFER_MAX (2*1024*1024) |
| 177 | #define UPLOADBUFFER_MIN CURL_MAX_WRITE_SIZE |
| 178 | |
| 179 | #define CURLEASY_MAGIC_NUMBER 0xc0dedbadU |
| 180 | #define GOOD_EASY_HANDLE(x) \ |
| 181 | ((x) && ((x)->magic == CURLEASY_MAGIC_NUMBER)) |
| 182 | |
| 183 | /* the type we use for storing a single boolean bit */ |
| 184 | #ifdef _MSC_VER |
| 185 | typedef bool bit; |
| 186 | #define BIT(x) bool x |
| 187 | #else |
| 188 | typedef unsigned int bit; |
| 189 | #define BIT(x) bit x:1 |
| 190 | #endif |
| 191 | |
| 192 | #ifdef HAVE_GSSAPI |
| 193 | /* Types needed for krb5-ftp connections */ |
| 194 | struct krb5buffer { |
| 195 | void *data; |
| 196 | size_t size; |
| 197 | size_t index; |
| 198 | BIT(eof_flag); |
| 199 | }; |
| 706 | CURLcode curl_easy_perform(struct Curl_easy *data) |
| 707 | { |
| 708 | return easy_perform(data, FALSE); |
| 709 | } |
Show 4 lines (not cited by the judge)
| 1167 | CURLU *curl_url(void) |
| 1168 | { |
| 1169 | return calloc(sizeof(struct Curl_URL), 1); |
| 1170 | } |
Show 24 lines (not cited by the judge)
| 282 | struct Curl_easy *curl_easy_init(void) |
| 283 | { |
| 284 | CURLcode result; |
| 285 | struct Curl_easy *data; |
| 286 | |
| 287 | /* Make sure we inited the global SSL stuff */ |
| 288 | if(!initialized) { |
| 289 | result = curl_global_init(CURL_GLOBAL_DEFAULT); |
| 290 | if(result) { |
| 291 | /* something in the global init failed, return nothing */ |
| 292 | DEBUGF(fprintf(stderr, "Error: curl_global_init failed\n")); |
| 293 | return NULL; |
| 294 | } |
| 295 | } |
| 296 | |
| 297 | /* We use curl_open() with undefined URL so far */ |
| 298 | result = Curl_open(&data); |
| 299 | if(result) { |
| 300 | DEBUGF(fprintf(stderr, "Error: Curl_open failed\n")); |
| 301 | return NULL; |
| 302 | } |
| 303 | |
| 304 | return data; |
| 305 | } |