-
Notifications
You must be signed in to change notification settings - Fork 86
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
Consider using an API design that prevents injection attacks #2
Comments
Thanks Teddy, I’ll look into it |
This is very interesting, thanks again for raising the issue! I haven’t worked with tagged templates yet, I’ll see how the escaping / replacement with variables could work. If I understand correctly we want
I like the Such a GraphQL query parsing function sounds like a good utility that would be useful in general, are you aware if it already exists? If not it would be cool to build it independent of octokit I think, wanna collaborate on that? I know https://www.npmjs.com/package/graphql-tag but we don’t want to work with ASTs |
Does that look good? example 1const repoId = 123
const result = query`
mutation {
addStar(input: {clientMutationId: "x", starrableId: "${repoId}"}) {
clientMutationId
}
}
`
{
query: 'mutation {\n addStar(input: {clientMutationId: "x", starrableId: "$starrableId"}) {\n clientMutationId\n }\n }',
variables: {
starrableId: 123
}
} example 2const fields = ['login', 'bio']
const result = query`
{
viewer {
${fields.join('\n')}
}
}
` Throws an error
|
people might still want to construct dynamic queries, we could provide some workaround that makes clear that what they do has the danger of query injections |
Sounds good to me. |
I've added a note to the README referencing this issue. I have decided not going to change the API. Thanks for making me aware of the potential injection attack and for bearing with me :) |
Suppose someone is using this library to adding a star to a repository, where the repository ID comes from user input. If they don't know about GraphQL variables and they're being careless, they might implement it like this:
This example code is vulnerable to a "GraphQL injection" attack, where someone could modify the structure of the query or perform additional actions by supplying malicious user input. (This works in a similar manner to a SQL injection attack.) For example, a malicious user could provide the following string in this case to maliciously add a topic to a repository:
...which would result in the following malicious query getting executed after string concatenation happens:
It's true that there's a way to rewrite this function to be safer (by using GraphQL variables), and similarly SQL engines usually allow for prepared statements. However, in SQL's case, developers still frequently shoot themselves in the foot and add injection vulnerabilities by using string concatenation, either by mistake or due to not knowing better. As a result, the broad consensus is that it's better if SQL libraries prevent string concatenation entirely (e.g. by not accepting strings as arguments). I think it would be a good idea if this library did a similar thing for GraphQL queries.
What would you think about the following alternative API?
The library would expose a template tag function which either escapes embedded expressions or replaces them all embedded expressions with GraphQL variables, and adds them to the query appropriately. As far as I can tell, this would make it extremely difficult for someone to shoot themself in the foot and introduce an injection attack, because there would be no easy way to concatenate a string while still calling a template tag function.
If someone needed to use additional arguments (e.g. headers), they could use
graphql.defaults
:(With this design, you would probably want to guard against someone accidentally calling
graphql(`foo`)
orgraphql([`foo`])
instead ofgraphql`foo`
. This could be accomplished by making sure the first argument to thegraphql
function is an array with araw
property.)Thanks for considering -- I don't mean to drop into the issue tracker and tell you how you should be designing your library. That said, I think a change like this would prevent a significant number of security bugs, and it would be easier to make earlier before compatibility is too big a concern.
The text was updated successfully, but these errors were encountered: