Shields: Redirector: [ERR_INVALID_CHAR]: Invalid character in header content ["Location"]

Created on 14 Sep 2019  路  4Comments  路  Source: badges/shields

Sentry Issue: SHIELDS-3Y

TypeError [ERR_INVALID_CHAR]: Invalid character in header content ["Location"]
  File "/home/m/shields/core/base-service/redirector.js", line 120, in camp.route
    ask.res.setHeader('Location', redirectUrl)
...
(5 additional frame(s) were not displayed)
bug core

All 4 comments

@calebcartwright Are you working on this?

@platan - no I'm not. Seems like it could basically be any of the redirectors though, presumably one that's missing an encoding of one or more params

We could add some validation to Redirector that checks for valid URL characters and includes the name of the service in the error message.

Though it wouldn't hurt to take a pass through and look for unencoded parameters!

ask.res.setHeader('Location', redirectUrl) throws an exception when redirect URL contains an invalid character. ask is a class from Scout Camp, and res is a Node.js class https://github.com/espadrine/sc/blob/master/doc/Readme.md#ask-and-augmented-request.
Valid characters for a header value are defined in https://github.com/nodejs/node/blob/v9.6.0/lib/_http_common.js#L245 (in v.9.4.0 definition is more complicated, but contains identical characters https://github.com/nodejs/node/blob/v9.4.0/lib/_http_common.js#L256).
Problem occurs when you put an encoded illegal character in a fragment of a request URI which is transformed to a path.
An example. https://github.com/badges/shields/blob/master/services/azure-devops/vso-redirect.service.js#L23-L28 has a definition:

    route: {
      base: 'vso/release',
      pattern: ':organization/:projectId/:definitionId/:environmentId',
    },
    transformPath: ({ organization, projectId, definitionId, environmentId }) =>
      `/azure-devops/release/${organization}/${projectId}/${definitionId}/${environmentId}`,

Putting %0a (encoded \n) in projectId will cause a problem:
http://localhost:8080/vso/release/to%0atodem/8cf3ec0e-d0c2-4fcd-8206-ad204f254a96/1/1.svg

But it's OK to put %0a a part of a request URI which is transformed to query param:
https://img.shields.io/codecov/c/token/abc123def%0a456/gh/codecov/private-example.svg

We have 25 redirectors defined in 19 files. I think most of them have this problem. More examples:
curl http://localhost:8080/vso/release/to%0atodem/8cf3ec0e-d0c2-4fcd-8206-ad204f254a96/1/1.svg -v
curl http://localhost:8080/codecov/c/token/abc123def456/gh/code%0acov/private-example.svg -v
curl http://localhost:8080/discourse/https/meta.discourse.org/stat%0aus.svg -v
curl http://localhost:8080/github/issues/detail/s/bad%0ages/shields/979.svg -v

If we want to handle such request properly we should encode every element of the path usingencodeURIComponent:

      `/azure-devops/release/${encodeURIComponent(organization)}/${encodeURIComponent(projectId)}/${encodeURIComponent(definitionId)}/${encodeURIComponent(environmentId)}`,

Alternatively we can leave it as it is and add a check for Location value:
https://github.com/badges/shields/compare/issue-4013-invalid-char-in-redirect?expand=1
Or we can mix both approaches.

What do you think?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

paladox picture paladox  路  72Comments

paulmelnikow picture paulmelnikow  路  30Comments

guylepage3 picture guylepage3  路  30Comments

Undistraction picture Undistraction  路  31Comments

adamjstone picture adamjstone  路  36Comments