Skip to content

Servers incorrectly accept any request body when the modeled operation input is empty or non-existent #3723

Open
@david-perez

Description

@david-perez

When there is operation input:

$version: "2.0"

namespace com.amazonaws.simple

use aws.protocols#restJson1
use smithy.test#httpMalformedRequestTests

@restJson1
service SimpleService {
    operations: [
        Operation
    ]
}

@http(uri: "/operation", method: "POST")
operation Operation {
    input: OperationInputOutput
    output: OperationInputOutput
}

structure OperationInputOutput {
    message: String
}

servers correctly reject a request that contains additional tokens past where we expect the end of the body:

apply Operation @httpMalformedRequestTests([
    {
        id: "AdditionalTokensEmptyStruct"
        documentation: """
        When additional tokens are found past where we expect the end of the body,
        the request should be rejected with a serialization exception."""
        protocol: restJson1
        request: {
            method: "POST"
            uri: "/operation"
            headers: {
                "Content-Type": "application/json"
            }
            body: "{}{}"
        },
        response: {
            headers: {
                "x-amzn-errortype": "SerializationException"
            }
            code: 400,
        }
    }
])

That is because JsonParserGenerator.kt asserts that there are no leftover tokens after parsing the operation input:

private fun RustWriter.expectEndOfTokenStream() {
rustBlock("if tokens.next().is_some()") {
rustTemplate(
"return Err(#{Error}::custom(\"found more JSON tokens after completing parsing\"));",
*codegenScope,
)
}
}

However, when the modeled operation input is empty:

structure OperationInputOutput { }

Or when there is no operation input (removing the Content-Type header in this case):

@http(uri: "/operation", method: "POST")
operation Operation { }

We don't generate a deserializer for the operation, and so we don't even attempt to inspect the body, accepting anything:

thread 'operation::operation_test::additional_tokens_empty_struct_malformed_request' panicked at simple/rust-server-codegen/src/operation.rs:112:52:
request should have been rejected, but we accepted it; we parsed operation input `OperationInput`

This bug affects all protocols. Note that in some protocols, like restJson1 and rpcv2Cbor (and perhaps all?), servers must accept both no request body and empty object in request body when the modeled operation input is empty. However, they shouldn't accept anything.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workinggood first issueGood for newcomersserverRust server SDK

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions