Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fails to parse cookie if it has % in its name #2504

Closed
t-ae opened this issue Oct 12, 2020 · 1 comment · Fixed by #2511
Closed

Fails to parse cookie if it has % in its name #2504

t-ae opened this issue Oct 12, 2020 · 1 comment · Fixed by #2511

Comments

@t-ae
Copy link
Contributor

t-ae commented Oct 12, 2020

Vapor cannot parse the cookies that has % in its name.
(Similar issue: #2359)

According to RFC6265 cookie-name = <token, defined in [RFC2616], Section 2.2>.
And accodging to RFC2616:

token          = 1*<any CHAR except CTLs or separators>
CHAR           = <any US-ASCII character (octets 0 - 127)>
CTL            = <any US-ASCII control character
                        (octets 0 - 31) and DEL (127)>
separators     = "(" | ")" | "<" | ">" | "@"
                | "," | ";" | ":" | "\" | <">
                | "/" | "[" | "]" | "?" | "="
                | "{" | "}" | SP | HT

If I understand correctly, % is valid.

firstParameterToken tries to find = to separate cookie name and value.
But it fails when it find character that is !character.isDirectiveKey.

private func firstParameterToken() -> Substring.Index? {
for index in self.current.indices {
let character = self.current[index]
if character == .equals {
return index
} else if !character.isDirectiveKey {
return nil
}
}
return nil
}

And % is not isDirectiveKey.

var isDirectiveKey: Bool {
self.isLetter || self.isNumber || self == .dash || self == .underscore || self == .period
}

Steps to reproduce

Open developer tool and create new cookie that has % in its name.
You'll find request.cookies.all is empty.

My problem

My site is mysite.example.com and example.com is not under my control.
When user access to example.com, it sets the cookie some%40key=value and Domain=.example.com (%40 is url encoded @).
This cookie also affects my site.

HTTPCookies.init returns nil if there's invalid directive.

init?(directives: [HTTPHeaders.Directive]) {
self.cookies = [:]
for directive in directives {
guard let value = directive.parameter else {
return nil
}
self.cookies[.init(directive.value)] = .init(string: .init(value))
}
}

So % cookie breaks all other cookies.
(I think this initializer should just ignore invalid directives)

@gregoryyoung2
Copy link
Contributor

I'm experiencing the same issue!

0xTim pushed a commit that referenced this issue Dec 11, 2020
* still return cookies if some fail to parse values, and accept % in directive name

* added tests for cookie parsing
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants