CVE-2023-28322: more POST-after-PUT confusion
What the report claims
CVE-2022-32221 only fixed CURLOPT_POST but not CURLOPT_POSTFIELDS, which may be used instead, leading to potential misuse and security issues.
Compare with curl's recorded outcome
Known vulnerability
A real vulnerability: CVE-2023-28322 more POST-after-PUT confusion
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 provided curl source excerpts (CMakeLists.txt and curl_setup_once.h) do not contain the option handling code for CURLOPT_POST, CURLOPT_POSTFIELDS, CURLOPT_MIMEPOST, CURLOPT_COPYPOSTFIELDS, or CURLOPT_HTTPPOST where the alleged flaw would exist.
- The deterministic checks confirm these symbols exist in the codebase at the target revision, but the implementing code is not in the provided excerpts.
- The proof-of-concept is detailed and demonstrates a plausible state-confusion bug (PUT state persisting into a subsequent POST request when CURLOPT_POST is not explicitly set), which matches the pattern of CVE-2022-32221.
- A human reviewer needs to examine the actual option handling code (likely in lib/easy.c or lib/setopt.c) to verify whether CURLOPT_POSTFIELDS and related options correctly set data->set.upload = FALSE.
What still needs checking
- Source code for option handling (CURLOPT_POSTFIELDS, CURLOPT_MIMEPOST, CURLOPT_COPYPOSTFIELDS, CURLOPT_HTTPPOST) from the target revision
- Source code for CURLOPT_POST handling (for comparison with the CVE-2022-32221 fix)
- The data->set.upload field definition and usage in the transfer state machine
How this analysis ran 6 claims · 5 citations verified
Checked against curl master on 2023-04-19 (6b1e4dc6cdd2). 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 proof-of-concept. The issue you describe (POST-after-PUT confusion when CURLOPT_POST is not explicitly set) is plausible and matches the pattern of CVE-2022-32221. However, the source code excerpts provided for triage do not include the option handling implementation (likely in lib/easy.c or lib/setopt.c) where CURLOPT_POSTFIELDS, CURLOPT_MIMEPOST, and CURLOPT_COPYPOSTFIELDS are processed. Could you point to the specific file and function where these options are handled, or provide the relevant code sections? This will allow us to verify whether they correctly set data->set.upload = FALSE as CURLOPT_POST does.
Inspect all claims and source code 6 claims · 3 code excerpts
Report claims
CURLOPT_POST is not necessarily used when sending data with the POST method
Read the reasoning
The provided curl source excerpts only show CMakeLists.txt and curl_setup_once.h. The actual implementation of CURLOPT_POST, CURLOPT_POSTFIELDS, and related options (likely in lib/easy.c or lib/setopt.c) is not included, so the claim cannot be verified against the provided code.
CURLOPT_POSTFIELDS does not set a FALSE on data->set.upload
Read the reasoning
The claim concerns whether CURLOPT_POSTFIELDS sets data->set.upload to FALSE. The provided source does not include the option processing code where this would be implemented.
CURLOPT_POST is not used in the CURLOPT_MIMEPOST usage example
Read the reasoning
The provided source does not include the implementation of CURLOPT_MIMEPOST or its interaction with CURLOPT_POST.
Users may not use CURLOPT_POST when using CURLOPT_POSTFIELDS
Read the reasoning
This claim about user behavior patterns cannot be verified from the provided source code excerpts.
The statement on the official website implies that using CURLOPT_POSTFIELDS sets CURLOPT_POST to 1
Read the reasoning
The external source E1 (pipermail archive) was retrieved but the provided excerpt does not contain the specific statement 'Using CURLOPT_POSTFIELDS implies setting CURLOPT_POST to 1'. The claim about documentation content cannot be confirmed from the provided excerpt.
Some users do not use CURLOPT_POST
Read the reasoning
This claim about user behavior cannot be verified from the provided source code.
What the report says about other projects
not addressed Using CURLOPT_POSTFIELDS implies setting CURLOPT_POST to 1
Read the original report (excerpt)
Source code
| 24 | set(LIB_NAME libcurl) |
| C1: Provided source does not contain option handling code for CURLOPT_POST or CURLOPT_POSTFIELDS | |
| C2: Provided source does not contain option handling code for CURLOPT_POSTFIELDS or data->set.upload | |
| C3: Provided source does not contain CURLOPT_MIMEPOST handling code | |
| C4: Provided source does not contain user-facing option handling code | |
| C6: Provided source does not contain user behavior evidence | |
| 25 | set(LIBCURL_OUTPUT_NAME libcurl CACHE STRING "Basename of the curl library") |
| 26 | add_definitions(-DBUILDING_LIBCURL) |
| 27 | |
| 28 | if(BUILD_SHARED_LIBS) |
| 29 | set(CURL_STATICLIB NO) |
| 30 | else() |
| 31 | set(CURL_STATICLIB YES) |
| 32 | endif() |
| 33 | |
| 34 | # Use: |
| 35 | # * CURL_STATICLIB |
| 36 | configure_file(curl_config.h.cmake |
| 37 | ${CMAKE_CURRENT_BINARY_DIR}/curl_config.h) |
| 38 | |
| 39 | transform_makefile_inc("Makefile.inc" "${CMAKE_CURRENT_BINARY_DIR}/Makefile.inc.cmake") |
| 40 | include(${CMAKE_CURRENT_BINARY_DIR}/Makefile.inc.cmake) |
| 41 | |
| 42 | list(APPEND HHEADERS |
| 43 | ${CMAKE_CURRENT_BINARY_DIR}/curl_config.h |
| 44 | ) |
| 45 | |
| 46 | if(WIN32 AND NOT CURL_STATICLIB) |
| 47 | list(APPEND CSOURCES libcurl.rc) |
| 48 | endif() |
| 49 | |
| 50 | # The rest of the build |
| 51 | |
| 52 | include_directories(${CMAKE_CURRENT_BINARY_DIR}/../include) |
| 53 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/..) |
| 54 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../include) |
| 55 | include_directories(${CMAKE_CURRENT_BINARY_DIR}/..) |
| 56 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}) |
| 57 | include_directories(${CMAKE_CURRENT_BINARY_DIR}) |
| 58 | if(USE_ARES) |
| 59 | include_directories(${CARES_INCLUDE_DIR}) |
| 60 | endif() |
| 61 | |
| 62 | add_library( |
| 63 | ${LIB_NAME} |
| 64 | ${HHEADERS} ${CSOURCES} |
| 65 | ) |
| 66 | |
| 67 | add_library( |
| 68 | ${PROJECT_NAME}::${LIB_NAME} |
| 69 | ALIAS ${LIB_NAME} |
| 70 | ) |
| 71 | |
| 72 | if(NOT BUILD_SHARED_LIBS) |
| 73 | set_target_properties(${LIB_NAME} PROPERTIES INTERFACE_COMPILE_DEFINITIONS CURL_STATICLIB) |
| 74 | endif() |
| 75 | |
| 76 | target_link_libraries(${LIB_NAME} PRIVATE ${CURL_LIBS}) |
| 77 | |
| 78 | transform_makefile_inc("Makefile.soname" "${CMAKE_CURRENT_BINARY_DIR}/Makefile.soname.cmake") |
| 79 | include(${CMAKE_CURRENT_BINARY_DIR}/Makefile.soname.cmake) |
| 80 | |
| 81 | set_target_properties(${LIB_NAME} PROPERTIES |
| 82 | COMPILE_DEFINITIONS BUILDING_LIBCURL |
| 83 | OUTPUT_NAME ${LIBCURL_OUTPUT_NAME} |
| 84 | ) |
| 85 | |
| 86 | if(CMAKE_SYSTEM_NAME STREQUAL "AIX" OR |
| 87 | CMAKE_SYSTEM_NAME STREQUAL "Linux" OR |
| 88 | CMAKE_SYSTEM_NAME STREQUAL "Darwin" OR |
| 89 | CMAKE_SYSTEM_NAME STREQUAL "SunOS" OR |
| 90 | CMAKE_SYSTEM_NAME STREQUAL "GNU/kFreeBSD" OR |
| 91 | |
| 92 | # FreeBSD comes with the a.out and elf flavours |
| 93 | # but a.out was supported up to version 3.x and |
| 94 | # elf from 3.x. I cannot imagine someone running |
| 95 | # CMake on those ancient systems |
| 96 | CMAKE_SYSTEM_NAME STREQUAL "FreeBSD" OR |
| 97 | |
| 98 | CMAKE_SYSTEM_NAME STREQUAL "Haiku") |
| 99 | |
| 100 | math(EXPR CMAKESONAME "${VERSIONCHANGE} - ${VERSIONDEL}") |
| 101 | set(CMAKEVERSION "${CMAKESONAME}.${VERSIONDEL}.${VERSIONADD}") |
| 102 | |
| 103 | set_target_properties(${LIB_NAME} PROPERTIES |
| 104 | VERSION ${CMAKEVERSION} |
| 105 | SOVERSION ${CMAKESONAME} |
| 106 | ) |
| 107 | |
| 108 | endif() |
| 109 | |
| 110 | |
| 111 | if(HIDES_CURL_PRIVATE_SYMBOLS) |
| 112 | set_property(TARGET ${LIB_NAME} APPEND PROPERTY COMPILE_DEFINITIONS "CURL_HIDDEN_SYMBOLS") |
| 113 | set_property(TARGET ${LIB_NAME} APPEND PROPERTY COMPILE_FLAGS ${CURL_CFLAG_SYMBOLS_HIDE}) |
| 114 | endif() |
| 115 | |
| 116 | # Remove the "lib" prefix since the library is already named "libcurl". |
| 117 | set_target_properties(${LIB_NAME} PROPERTIES PREFIX "") |
| 118 | set_target_properties(${LIB_NAME} PROPERTIES IMPORT_PREFIX "") |
| 119 | |
| 120 | if(CURL_HAS_LTO) |
| 121 | set_target_properties(${LIB_NAME} PROPERTIES |
| 122 | INTERPROCEDURAL_OPTIMIZATION_RELEASE TRUE |
| 123 | INTERPROCEDURAL_OPTIMIZATION_RELWITHDEBINFO TRUE) |
| 124 | endif() |
| 125 | |
| 126 | if(WIN32) |
| 127 | if(BUILD_SHARED_LIBS) |
| 128 | if(MSVC) |
| 129 | # Add "_imp" as a suffix before the extension to avoid conflicting with |
| 130 | # the statically linked "libcurl.lib" |
| 131 | set_target_properties(${LIB_NAME} PROPERTIES IMPORT_SUFFIX "_imp.lib") |
| 132 | endif() |
| 133 | endif() |
| 134 | else() |
| 135 | # on not-Windows, check for writable argv[] |
| 136 | include(CheckCSourceRuns) |
| 137 | check_c_source_runs(" |
| 138 | int main(int argc, char **argv) |
| 139 | { |
| 140 | (void)argc; |
| 141 | argv[0][0] = ' '; |
| 142 | return (argv[0][0] == ' ')?0:1; |
| 143 | }" |
| 24 | set(LIB_NAME libcurl) |
| 25 | set(LIBCURL_OUTPUT_NAME libcurl CACHE STRING "Basename of the curl library") |
| 26 | add_definitions(-DBUILDING_LIBCURL) |
| 27 | |
| 28 | if(BUILD_SHARED_LIBS) |
| 29 | set(CURL_STATICLIB NO) |
| 30 | else() |
| 31 | set(CURL_STATICLIB YES) |
| 32 | endif() |
| 33 | |
| 34 | # Use: |
| 35 | # * CURL_STATICLIB |
| 36 | configure_file(curl_config.h.cmake |
| 37 | ${CMAKE_CURRENT_BINARY_DIR}/curl_config.h) |
| 38 | |
| 39 | transform_makefile_inc("Makefile.inc" "${CMAKE_CURRENT_BINARY_DIR}/Makefile.inc.cmake") |
| 40 | include(${CMAKE_CURRENT_BINARY_DIR}/Makefile.inc.cmake) |
| 41 | |
| 42 | list(APPEND HHEADERS |
| 43 | ${CMAKE_CURRENT_BINARY_DIR}/curl_config.h |
| 44 | ) |
| 45 | |
| 46 | if(WIN32 AND NOT CURL_STATICLIB) |
| 47 | list(APPEND CSOURCES libcurl.rc) |
| 48 | endif() |
| 49 | |
| 50 | # The rest of the build |
| 51 | |
| 52 | include_directories(${CMAKE_CURRENT_BINARY_DIR}/../include) |
| 53 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/..) |
| 54 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../include) |
| 55 | include_directories(${CMAKE_CURRENT_BINARY_DIR}/..) |
| 56 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}) |
| 57 | include_directories(${CMAKE_CURRENT_BINARY_DIR}) |
| 58 | if(USE_ARES) |
| 59 | include_directories(${CARES_INCLUDE_DIR}) |
| 60 | endif() |
| 61 | |
| 62 | add_library( |
| 63 | ${LIB_NAME} |
| 64 | ${HHEADERS} ${CSOURCES} |
| 65 | ) |
| 66 | |
| 67 | add_library( |
| 68 | ${PROJECT_NAME}::${LIB_NAME} |
| 69 | ALIAS ${LIB_NAME} |
| 70 | ) |
| 71 | |
| 72 | if(NOT BUILD_SHARED_LIBS) |
| 73 | set_target_properties(${LIB_NAME} PROPERTIES INTERFACE_COMPILE_DEFINITIONS CURL_STATICLIB) |
| 74 | endif() |
| 75 | |
| 76 | target_link_libraries(${LIB_NAME} PRIVATE ${CURL_LIBS}) |
| 77 | |
| 78 | transform_makefile_inc("Makefile.soname" "${CMAKE_CURRENT_BINARY_DIR}/Makefile.soname.cmake") |
| 79 | include(${CMAKE_CURRENT_BINARY_DIR}/Makefile.soname.cmake) |
| 80 | |
| 81 | set_target_properties(${LIB_NAME} PROPERTIES |
| 82 | COMPILE_DEFINITIONS BUILDING_LIBCURL |
| 83 | OUTPUT_NAME ${LIBCURL_OUTPUT_NAME} |
| 84 | ) |
| 85 | |
| 86 | if(CMAKE_SYSTEM_NAME STREQUAL "AIX" OR |
| 87 | CMAKE_SYSTEM_NAME STREQUAL "Linux" OR |
| 88 | CMAKE_SYSTEM_NAME STREQUAL "Darwin" OR |
| 89 | CMAKE_SYSTEM_NAME STREQUAL "GNU/kFreeBSD" OR |
| 90 | |
| 91 | # FreeBSD comes with the a.out and elf flavours |
| 92 | # but a.out was supported up to version 3.x and |
| 93 | # elf from 3.x. I cannot imagine someone running |
| 94 | # CMake on those ancient systems |
| 95 | CMAKE_SYSTEM_NAME STREQUAL "FreeBSD" OR |
| 96 | |
| 97 | CMAKE_SYSTEM_NAME STREQUAL "Haiku") |
| 98 | |
| 99 | math(EXPR CMAKESONAME "${VERSIONCHANGE} - ${VERSIONDEL}") |
| 100 | set(CMAKEVERSION "${CMAKESONAME}.${VERSIONDEL}.${VERSIONADD}") |
| 101 | |
| 102 | set_target_properties(${LIB_NAME} PROPERTIES |
| 103 | VERSION ${CMAKEVERSION} |
| 104 | SOVERSION ${CMAKESONAME} |
| 105 | ) |
| 106 | |
| 107 | endif() |
| 108 | |
| 109 | |
| 110 | if(HIDES_CURL_PRIVATE_SYMBOLS) |
| 111 | set_property(TARGET ${LIB_NAME} APPEND PROPERTY COMPILE_DEFINITIONS "CURL_HIDDEN_SYMBOLS") |
| 112 | set_property(TARGET ${LIB_NAME} APPEND PROPERTY COMPILE_FLAGS ${CURL_CFLAG_SYMBOLS_HIDE}) |
| 113 | endif() |
| 114 | |
| 115 | # Remove the "lib" prefix since the library is already named "libcurl". |
| 116 | set_target_properties(${LIB_NAME} PROPERTIES PREFIX "") |
| 117 | set_target_properties(${LIB_NAME} PROPERTIES IMPORT_PREFIX "") |
| 118 | |
| 119 | if(CURL_HAS_LTO) |
| 120 | set_target_properties(${LIB_NAME} PROPERTIES |
| 121 | INTERPROCEDURAL_OPTIMIZATION_RELEASE TRUE |
| 122 | INTERPROCEDURAL_OPTIMIZATION_RELWITHDEBINFO TRUE) |
| 123 | endif() |
| 124 | |
| 125 | if(WIN32) |
| 126 | if(BUILD_SHARED_LIBS) |
| 127 | if(MSVC) |
| 128 | # Add "_imp" as a suffix before the extension to avoid conflicting with |
| 129 | # the statically linked "libcurl.lib" |
| 130 | set_target_properties(${LIB_NAME} PROPERTIES IMPORT_SUFFIX "_imp.lib") |
| 131 | endif() |
| 132 | endif() |
| 133 | endif() |
| 134 | |
| 135 | target_include_directories(${LIB_NAME} INTERFACE |
| 136 | $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}> |
| 137 | $<BUILD_INTERFACE:${CURL_SOURCE_DIR}/include>) |
| 138 | |
| 139 | if(CURL_ENABLE_EXPORT_TARGET) |
| 140 | install(TARGETS ${LIB_NAME} |
| 141 | EXPORT ${TARGETS_EXPORT_NAME} |
| 142 | ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} |
| 143 | LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} |
| 144 | RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} |
| 145 | ) |
| 146 | |
| 147 | export(TARGETS ${LIB_NAME} |
| 148 | FILE ${PROJECT_BINARY_DIR}/libcurl-target.cmake |
| 149 | NAMESPACE ${PROJECT_NAME}:: |
| 150 | ) |
| 151 | endif() |
Show 1 lines (not cited by the judge)
| 273 | #define FALSE false |