{"answers":{"affected":"3 open source packages ship an affected version, including github.com/versity/versitygw.","exploited":"There is no known exploitation of GHSA-v2ch-c8v8-fgr7 in the wild and no public exploit code.","fix":"Upgrade github.com/versity/versitygw to 1.0.17 or later.","what":"GHSA-v2ch-c8v8-fgr7 is a denial of service vulnerability in github.com/versity/versitygw, published on 29 Aug 2025. An attacker can exploit it over the internet without logging in, with no action from the victim."},"fix_prompt":"Check this codebase for GHSA-v2ch-c8v8-fgr7 and fix it if it is affected.\n\nWhat it is: GHSA-v2ch-c8v8-fgr7 is a denial of service vulnerability in github.com/versity/versitygw, published on 29 Aug 2025. An attacker can exploit it over the internet without logging in, with no action from the victim.\nExploitation: There is no known exploitation of GHSA-v2ch-c8v8-fgr7 in the wild and no public exploit code.\n\nAffected packages and fixed versions:\n- github.com/versity/versitygw (Go): affected all versions; fixed in 1.0.17\n- github.com/versity/versitygw (Go): affected all versions; fixed in 1.0.17\n- github.com/versity/versitygw (Go): affected all versions; fixed in 1.0.17\n\nTask:\n1. Search the dependency manifests and lockfiles (for example package.json, package-lock.json, requirements.txt, poetry.lock, uv.lock, pom.xml, build.gradle, go.mod, Cargo.lock, Gemfile.lock) and any Dockerfiles for the affected packages, including transitive dependencies.\n2. If an affected version is in use, upgrade it to the fixed version for its release line with the project's package manager, so the lockfile is regenerated. Prefer the smallest upgrade that fixes it.\n3. If there is no fix, or the upgrade would break the build, do not guess: explain the risk and the safest workaround instead.\n4. Run the tests and summarise what changed and why.\n5. If nothing in the project is affected, say so and change nothing.\n\nReference: https://insights.sbomify.com/GHSA-v2ch-c8v8-fgr7/ (Markdown: https://insights.sbomify.com/GHSA-v2ch-c8v8-fgr7/index.md)","id":"GHSA-v2ch-c8v8-fgr7","markdown":"https://insights.sbomify.com/GHSA-v2ch-c8v8-fgr7/index.md","name":"GHSA-v2ch-c8v8-fgr7","record":{"aliases":["GO-2025-3925"],"analysis":{"component_type":"server_software","fix_type":"upgrade","impacts":["denial_of_service"],"network_reachable":"yes","non_default_config":false,"product_category":"Versity Gateway","requires_auth":"none","summary":"An attacker can cause a denial of service by sending AWS chunked data without a Content-Length header to the Versity server.","user_interaction":"not_required","vuln_class":"denial_of_service"},"analysis_generated_by":"qwen3.8-flash-next","assigner":null,"cpe":[],"cvss":{"score":null,"severity":null,"source":null,"vector":null,"version":null},"cwes":[],"description":"Sending AWS chunk data with no Content-Length HTTP header causes the panic, every time. \n\n### Reproduction\n\nSetup versity server running on port 7071, no SSL (for ease of packet tracing with tshark). Problem can be reproduced with or without SSL on the versity end. \n\nUse nginx to reverse proxy on port 7070. This does have to be SSL enabled for the repro to occur. nginx config: \n\n```\nupstream tony_versity {\n        server 127.0.0.1:7071;\n        keepalive 15;\n}\n\nserver {\n    listen       7070 ssl ;\n    access_log  /var/log/nginx/tony_versity_proxy.access.log;\n    error_log /var/log/nginx/tony_versity_proxy.error.log;\n\n    # Allow any size file to be uploaded.\n    client_max_body_size 0;\n    # Allow special characters in headers\n    ignore_invalid_headers off;\n    # Disable buffering\n    proxy_buffering off;\n    proxy_request_buffering off;\n\n    # Load configuration files for the default server block.\n    include /etc/nginx/default.d/*.conf;\n\n    ssl_certificate \"/WS/TEMP/lh.crt\";\n    ssl_certificate_key \"/WS/TEMP/lh.key\";\n    ssl_session_cache shared:SSL:1m;\n    ssl_session_timeout  10m;\n    ssl_ciphers HIGH:!aNULL:!MD5;\n    ssl_prefer_server_ciphers on;\n    ssl_protocols TLSv1.2 TLSv1.3;\n\n    location / {\n        allow all;\n        proxy_pass http://127.0.0.1:7071;\n        proxy_http_version 1.1;\n        proxy_read_timeout 120;\n        proxy_connect_timeout 300;\n\n        # Set headers\n        proxy_set_header Host $http_host;\n        proxy_set_header X-Real-IP $remote_addr;\n        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n        proxy_set_header X-Forwarded-Proto $scheme;\n        proxy_set_header Transfer-Encoding \"\";\n\n        # CORS headers\n        add_header 'Access-Control-Allow-Origin' '*' always;\n        add_header 'Access-Control-Allow-Credentials' 'true' always;\n        add_header 'Access-Control-Allow-Headers' 'Authorization,Accept,ETag,Origin,DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range' always;\n        add_header 'Access-Control-Allow-Methods' 'GET,POST,OPTIONS,PUT,DELETE,PATCH' always;\n        add_header 'Access-Control-Expose-Headers' 'ETag, Content-Length, Content-Range' always;\n\n        # Optional security headers\n        add_header X-Content-Type-Options nosniff always;\n        add_header X-Frame-Options DENY always;\n        add_header Referrer-Policy no-referrer always;\n\n        # Preflight (OPTIONS) handler\n        if ($request_method = OPTIONS) {\n            add_header Access-Control-Allow-Origin '*' always;\n            add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS, PUT, DELETE, PATCH' always;\n            add_header Access-Control-Allow-Headers 'Authorization,Accept,ETag,Origin,DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range' always;\n            add_header Access-Control-Expose-Headers 'ETag, Content-Length, Content-Range' always;\n            add_header Content-Type text/plain;\n            add_header Content-Length 0;\n            return 204;\n        }\n    }\n}\n```\n\nUse aws s3 cp to copy a large file (one that will trigger multipart upload) into versity via the nginx proxy on port 7070. AWS CLI must be version 2 for the repro to occur. Connecting directly to versity on port 7070 does not trigger the repro.\n\n \n### Initial crash analysis\n\nThe versity server enters a panic exception in function `HashReader` (csum-reader.go). The panic is due to a null value in the field r which should be a pointer to an io.Reader. \n\nThe reason this field is blank goes back to code in the `fasthttp` library, `ContinueReadBodyStream`. This function exits prematurely if the incoming request `ContentLength` field is set to `-2`, and therefore does not set up an io.Reader in the request context structure. \n\n`-2` is not a valid content-length for an HTTP message, it is a special value used internally by the `fasthttp` module. (Unfortunately the author hard coded the value rather than using a meaningful macro, which would have aided the understanding here. )\n\nThe reason for the `-2` can be found in function `parseHeaders`(headers.go in fasthttp). The header struct content length is set to `-2` at the start of the function, and will be overwritten if an HTTP content-length header is encountered during the parsing. If no such header is present in the request, it stays as `-2` with the later result of skipping the creation of an io.Reader. Seems reasonable - no content, no need for a reader? (Note that the presence of content-length triggers body reader creation even if the value is 0.) The fasthttp code replaces the illegal `-2` value with `0` before passing the request up to Versity. \n\nSo the pathway of this crash is receiving a request with no content-length, which means no body reader is set in the request context structure, but Versity tries to read anyway in the hash routines. \n\nThis pathology was confirmed by artificially creating a content-length on all incoming packets that didn’t have one, the outcome being that this panic did not occur, although the overall upload still reported failure (I didn’t go into exactly why as the point had been proven).\n\n \n### Further Analysis\n\nThe question becomes why there is no HTTP content-length header in this request. The answer to this is that the large transfer is being done using AWS chunking. Wireshark shows the packet structure. There is an initial POST request with content-length zero:\nHypertext Transfer Protocol\n```\n    POST /ttt/f2?uploads HTTP/1.1\\r\\n\n    Host: 127.0.0.1:7070\\r\\n\n    X-Real-IP: 127.0.0.1\\r\\n\n    X-Forwarded-For: 127.0.0.1\\r\\n\n    X-Forwarded-Proto: https\\r\\n\n    Connection: close\\r\\n\n    Content-Length: 0\\r\\n\n    Accept-Encoding: identity\\r\\n\n    x-amz-checksum-algorithm: CRC64NVME\\r\\n\n     [truncated]User-Agent: aws-cli/2.27.52 md/awscrt#0.26.1 ua/2.1 os/linux#4.18.0-553.16.1.el8_10.x86_64 md/arch#x86_64 lang/python#3.13.4 md/pyimpl#CPython m/E,Z,N,G,b cfg/retry-mode#standard md/installer#exe md/distrib#rhel.8 md/prompt#off\n    X-Amz-Date: 20250718T105915Z\\r\\n\n    X-Amz-Content-SHA256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\\r\\n\n     [truncated]Authorization: AWS4-HMAC-SHA256 Credential=AKIA000000000000000/20250718/us-east-1/s3/aws4_request, SignedHeaders=host;x-amz-checksum-algorithm;x-amz-content-sha256;x-amz-date, Signature=cd9f6a85ae2dd964aa44274d7d0642c51f8b32584\n    \\r\\n\n    [Full request URI: http://127.0.0.1:7070/ttt/f2?uploads]\n    [HTTP request 1/1]\n    [Response in frame: 6]\n```\n.. followed soon after by a PUT request with ‘content-encdoding: aws-chunked’. According to the AWS documentation, this encoding is used when the size of the upload is not known in advance, and a content-length header is expressly forbidden. AWS supplies other headers with size information, but these are not recognised by fasthttp.\nHypertext Transfer Protocol\n```\n    PUT /ttt/f2?uploadId=7170abfd-e29a-40fe-bd34-31b434cc1b6b\u0026partNumber=1 HTTP/1.1\\r\\n\n    Host: 127.0.0.1:7070\\r\\n\n    X-Real-IP: 127.0.0.1\\r\\n\n    X-Forwarded-For: 127.0.0.1\\r\\n\n    X-Forwarded-Proto: https\\r\\n\n    Connection: close\\r\\n\n    Accept-Encoding: identity\\r\\n\n    x-amz-sdk-checksum-algorithm: CRC64NVME\\r\\n\n     [truncated]User-Agent: aws-cli/2.27.52 md/awscrt#0.26.1 ua/2.1 os/linux#4.18.0-553.16.1.el8_10.x86_64 md/arch#x86_64 lang/python#3.13.4 md/pyimpl#CPython m/E,Z,N,G,b,W cfg/retry-mode#standard md/installer#exe md/distrib#rhel.8 md/prompt#o\n    Content-Encoding: aws-chunked\\r\\n\n    X-Amz-Trailer: x-amz-checksum-crc64nvme\\r\\n\n    X-Amz-Decoded-Content-Length: 8388608\\r\\n\n    X-Amz-Date: 20250718T105915Z\\r\\n\n    X-Amz-Content-SHA256: STREAMING-UNSIGNED-PAYLOAD-TRAILER\\r\\n\n     [truncated]Authorization: AWS4-HMAC-SHA256 Credential=AKIA000000000000000/20250718/us-east-1/s3/aws4_request, SignedHeaders=content-encoding;host;x-amz-content-sha256;x-amz-date;x-amz-decoded-content-length;x-amz-sdk-checksum-algorithm;x-\n    \\r\\n","ecosystems":["Go"],"exploits":{"exploitdb":null,"first_seen":null,"github_poc":null,"max_poc_stars":null,"metasploit":null,"nuclei":null,"refs":[],"tier":null},"has_fix":true,"headline":"Versity panic induced by AWS chunked data sent to port","id":"GHSA-v2ch-c8v8-fgr7","indexable":true,"kev":null,"kind":"advisory","links":{"ecosystem":"Go","product":null,"products":[],"type":"denial_of_service","year":"2025"},"n_packages":3,"n_references":null,"packages":[{"ecosystem":"Go","fixed":["1.0.17"],"introduced":["0"],"last_affected":[],"package":"github.com/versity/versitygw","purl":null,"source":"GHSA-v2ch-c8v8-fgr7"},{"ecosystem":"Go","fixed":["1.0.17"],"introduced":["0"],"last_affected":[],"package":"github.com/versity/versitygw","purl":"pkg:golang/github.com/versity/versitygw","source":"GHSA-v2ch-c8v8-fgr7"},{"ecosystem":"Go","fixed":["1.0.17"],"introduced":["0"],"last_affected":[],"package":"github.com/versity/versitygw","purl":"pkg:golang/github.com/versity/versitygw","source":"GO-2025-3925"}],"products":null,"published":"2025-08-29","related":[],"sources":[{"class":"attribution","licence":"CC BY 4.0","name":"GitHub Advisory Database","prefix":"GHSA"},{"class":"attribution","licence":"CC BY 4.0","name":"Go Vulnerability Database","prefix":"GO"}],"ssvc":{"automatable":null,"exploitation":null,"technical_impact":null},"state":null,"updated":null,"vendors":null},"summary":"An attacker can cause a denial of service by sending AWS chunked data without a Content-Length header to the Versity server.","url":"https://insights.sbomify.com/GHSA-v2ch-c8v8-fgr7/"}