grpc / grpc/grpc-java

Metadata: Header value validation

Open
#11,679 6 comments 0 reactions 0 assignees View on GitHub
Dominant language
Java
Stars
12.1k
Forks
4k
Avg merge
2d 17h
Merged PRs (30d)
37

Description

### What version of gRPC-Java are you using?
1.41.x, but also observed in master branch

### What is your environment?
Linux/MacOs, n/a

### What did you expect to see?
Metadata validation is consistent between Java and Go implementations.

### What did you see instead?
Java treats differently some invalid characters.

## These are the rules for header values:
1. ASCII-Value should not have leading or trailing whitespace.
2. ASCII-Value → 1*( %x20-%x7E ) ; space and printable ASCII
3. "Implementations must not error due to receiving an invalid ASCII-Value that's a valid field-value in HTTP, but the precise behaviour is not strictly defined: they may throw the value away or accept the value. If accepted, care must be taken to make sure that the application is permitted to echo the value back as metadata."



### About rule 1 - ASCII-Value should not have leading or trailing whitespace.

We have not yet tested all the cases but it seems like neither Java nor Go are validating for this. Doesn't seem like there is a strong need to implement this.

### About rule 2 - ASCII-Value → 1*( %x20-%x7E ) ; space and printable ASCII

The current metadata object in grpc-java relies on `encoded.getBytes(US_ASCII);` :

https://github.com/grpc/grpc-java/blob/5081e60626d952c4ed60ecf57a85668b7b59064e/api/src/main/java/io/grpc/Metadata.java#L981-L985
https://github.com/grpc/grpc-java/blob/5081e60626d952c4ed60ecf57a85668b7b59064e/api/src/main/java/io/grpc/Metadata.java#L342-L353

The effects of this are that depending on the type of invalid character, the headers have different behaviours:
1. Characters outside of US_ASCII: The invalid character gets replaced by the replacement character (�), and after that substituted again for a question mark (?).
2. Non printable characters inside of US_ASCII range (e.g: \t or \n) are not substituted. This leads to the header being removed from the request.

In grpc-go there is a straight forward validation of all the bytes before sending the request. If the validation fails the request call results in error.

### About rule 3 - If accepted, care must be taken to make sure that the application is permitted to echo the value back as metadata.

Java uses the same validation as for request headers:
- Characters outside of US_ASCII: The application code in the server will see the received header with the character substituted by the replacement character (�). When echoing back the header, the server will send the header with the character substituted by the question mark (?)
- Non printable characters: The application code in the server will see those characters in the received headers but will drop the header from the response.

Go doesn't validate anything in the received headers nor in the response headers, so you are able to send back any header. You are also able to send any new headers that break all the rules in the response ( eg: "invalid-$":"Ĩñvá \t łið" )

### Steps to reproduce the bug

Edit: Fixed misunderstanding from our side.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.