CVE-2022-35252: control code in cookie denial of service
What the report claims
An attacker can poison curl's cookie store with cookies containing control characters like form feed, causing Apache to reject subsequent requests with a 400 Bad Request and leading to denial of service.
Compare with curl's recorded outcome
Known vulnerability
A real vulnerability: CVE-2022-35252 control code in cookie denial of service
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 central claim (C1) is that curl lacks validation of control characters when saving cookies. The code that would confirm or contradict this (cookie parsing/storage in lib/cookie.c) is not included in the provided source snippets.
- The provided source only shows lib/urldata.h and a small part of lib/c-hyper.c, neither of which contains the Set-Cookie parsing logic.
- The RFC 6265 erratum (E1) confirms the spec excludes control characters from cookie-octet, but does not address Apache's behavior (C4).
- A human reviewer needs to examine lib/cookie.c (or equivalent) at the target revision to see if cookie name/value validation exists.
What still needs checking
- The cookie parsing and storage implementation (likely lib/cookie.c) from revision 7230b19a2e17
How this analysis ran 5 claims · 0 citations verified
Checked against curl master on 2022-06-26 (7230b19a2e17). Test 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. The cookie parsing and storage code (likely in lib/cookie.c) is not included in the source snippets we have for the target revision, so we cannot verify whether curl validates control characters when saving cookies. Could you point to the specific function or file where you believe the validation is missing? That will help us locate the relevant code for assessment.
Inspect all claims and source code 5 claims · 3 code excerpts
Report claims
curl does not implement character check on cookie name or value when saving to cookie store
Read the reasoning
The provided source code does not include the cookie parsing and storage logic (typically in lib/cookie.c). The snippets show only lib/urldata.h (CURLcode typedef) and lib/c-hyper.c (a function that calls Curl_http_cookies). The code that would validate or reject control characters when saving cookies is not present, so the claim cannot be verified from the provided code.
cookie store
Read the reasoning
Same as C1: the cookie store implementation is not in the provided source snippets.
a form feed character '\f' saved in cookie store
Read the reasoning
The trigger depends on the cookie parsing code accepting a form feed character, which is not in the provided source.
Apache rejects control characters other than \r or \n in the request head, returning 400 Bad Request
Read the reasoning
This claim is about Apache HTTP server behavior, not curl code. The provided external source (E1) is an RFC 6265 erratum discussing cookie-octet syntax (excluding control characters per the spec), but it does not state that Apache rejects such characters in request headers. No excerpt confirms Apache's behavior.
Save a cookie with form feed using curl -c cookies.txt and then request with that cookie store
Read the reasoning
The reproduction steps depend on the cookie parsing behavior that is not shown in the provided source.
What the report says about other projects
confirmed cookies should not contain control characters per RFC 6265
“cookie-octet = %x21 / %x23-2B / %x2D-3A / %x3C-5B / %x5D-7E ; US-ASCII characters excluding CTLs, ; whitespace DQUOTE, comma, semicolon, ; and backslash” source
not addressed Apache rejects control characters other than \r or \n in the request head
Read the original report (excerpt)
Source code
| 124 | typedef CURLcode (*Curl_datastream)(struct Curl_easy *data, |
| 125 | struct connectdata *conn, |
| 126 | int *didwhat, |
| 127 | bool *done, |
| 128 | int select_res); |
| 129 | #endif |
| 130 | |
| 131 | #include "mime.h" |
| 132 | #include "imap.h" |
| 133 | #include "pop3.h" |
| 134 | #include "smtp.h" |
| 135 | #include "ftp.h" |
| 136 | #include "file.h" |
| 137 | #include "vssh/ssh.h" |
| 138 | #include "http.h" |
| 139 | #include "rtsp.h" |
| 140 | #include "smb.h" |
| 141 | #include "mqtt.h" |
| 142 | #include "wildcard.h" |
| 143 | #include "multihandle.h" |
| 144 | #include "quic.h" |
| 145 | #include "c-hyper.h" |
| 146 | |
| 147 | #ifdef HAVE_GSSAPI |
| 148 | # ifdef HAVE_GSSGNU |
| 149 | # include <gss.h> |
| 150 | # elif defined HAVE_GSSAPI_GSSAPI_H |
| 151 | # include <gssapi/gssapi.h> |
| 152 | # else |
| 153 | # include <gssapi.h> |
| 154 | # endif |
| 155 | # ifdef HAVE_GSSAPI_GSSAPI_GENERIC_H |
| 156 | # include <gssapi/gssapi_generic.h> |
| 157 | # endif |
| 158 | #endif |
| 159 | |
| 160 | #ifdef HAVE_LIBSSH2_H |
| 161 | #include <libssh2.h> |
| 162 | #include <libssh2_sftp.h> |
| 163 | #endif /* HAVE_LIBSSH2_H */ |
| 164 | |
| 165 | #define READBUFFER_SIZE CURL_MAX_WRITE_SIZE |
| 166 | #define READBUFFER_MAX CURL_MAX_READ_SIZE |
| 167 | #define READBUFFER_MIN 1024 |
| 168 | |
| 169 | /* The default upload buffer size, should not be smaller than |
| 170 | CURL_MAX_WRITE_SIZE, as it needs to hold a full buffer as could be sent in |
| 171 | a write callback. |
| 172 | |
| 173 | The size was 16KB for many years but was bumped to 64KB because it makes |
| 174 | libcurl able to do significantly faster uploads in some circumstances. Even |
| 175 | larger buffers can help further, but this is deemed a fair memory/speed |
| 176 | compromise. */ |
| 177 | #define UPLOADBUFFER_DEFAULT 65536 |
| 178 | #define UPLOADBUFFER_MAX (2*1024*1024) |
| 179 | #define UPLOADBUFFER_MIN CURL_MAX_WRITE_SIZE |
| 180 | |
| 181 | #define CURLEASY_MAGIC_NUMBER 0xc0dedbadU |
| 182 | #define GOOD_EASY_HANDLE(x) \ |
| 183 | ((x) && ((x)->magic == CURLEASY_MAGIC_NUMBER)) |
| 184 | |
| 185 | #ifdef HAVE_GSSAPI |
| 186 | /* Types needed for krb5-ftp connections */ |
| 187 | struct krb5buffer { |
| 188 | void *data; |
| 189 | size_t size; |
| 190 | size_t index; |
| 191 | BIT(eof_flag); |
| 192 | }; |
| 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 | }; |
Show 14 lines (not cited by the judge)
| 762 | static CURLcode cookies(struct Curl_easy *data, |
| 763 | struct connectdata *conn, |
| 764 | hyper_headers *headers) |
| 765 | { |
| 766 | struct dynbuf req; |
| 767 | CURLcode result; |
| 768 | Curl_dyn_init(&req, DYN_HTTP_REQUEST); |
| 769 | |
| 770 | result = Curl_http_cookies(data, conn, &req); |
| 771 | if(!result) |
| 772 | result = Curl_hyper_header(data, headers, Curl_dyn_ptr(&req)); |
| 773 | Curl_dyn_free(&req); |
| 774 | return result; |
| 775 | } |