-
Notifications
You must be signed in to change notification settings - Fork 32
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #27 from trailofbits/dev-javascript-apollo-graphql…
…-rules Add apollo-graphql semgrep rules
- Loading branch information
Showing
16 changed files
with
1,012 additions
and
20 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
// BAD: Has 'schemaDirectives' | ||
//ruleid: schema-directives | ||
const apollo_server_1 = new ApolloServer({ | ||
typeDefs, | ||
resolvers, | ||
schemaDirectives: { | ||
rateLimit: rateLimitDirective | ||
}, | ||
}); | ||
|
||
// Good: Does not have 'schemaDirectives' | ||
//ok: schema-directives | ||
const apollo_server_3 = new ApolloServer({ | ||
typeDefs, | ||
resolvers, | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
rules: | ||
- id: schema-directives | ||
message: >- | ||
The Apollo GraphQL uses the 'schemaDirectives' option. This works in ApolloServer v2, but does nothing in version >=3. Depending on what the directives are used for, this can expose authenticated endpoints, disable rate limiting, and more. See the references on how to create custom directives in v3 and v4. | ||
languages: [js, ts] | ||
severity: ERROR | ||
metadata: | ||
category: security | ||
cwe: "CWE-686: Function Call With Incorrect Argument Type" | ||
subcategory: [vuln] | ||
confidence: MEDIUM | ||
likelihood: MEDIUM | ||
impact: HIGH | ||
technology: | ||
- graphql | ||
- apollo-graphql-server | ||
description: "Use of outdated ApolloServer option 'schemaDirectives'" | ||
references: | ||
- https://www.apollographql.com/docs/apollo-server/schema/directives/#custom-directives | ||
|
||
pattern-either: | ||
- pattern: | | ||
new ApolloServer({..., schemaDirectives: ..., ...}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
//ruleid: use-of-graphql-upload | ||
app.use(graphqlUploadExpress()); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
rules: | ||
- id: use-of-graphql-upload | ||
languages: [js, ts] | ||
message: >- | ||
The Apollo GraphQL server is using the graphql-upload library. This library allows file uploads using POSTs with content-type: multipart/form-data, which can enable to CSRF attacks. Ensure that you are enabling CSRF protection if you really need to use graphql-upload . | ||
severity: WARNING | ||
metadata: | ||
category: security | ||
cwe: "CWE-352: Cross-Site Request Forgery (CSRF)" | ||
subcategory: [vuln] | ||
confidence: LOW | ||
likelihood: MEDIUM | ||
impact: MEDIUM | ||
technology: | ||
- graphql | ||
- apollo-graphql-server | ||
description: "Use of the graphql-upload library" | ||
references: | ||
- https://github.com/apollographql/apollo-server/security/advisories/GHSA-2p3c-p3qw-69r4 | ||
|
||
patterns: | ||
- pattern: app.use(graphqlUploadExpress()); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
import 'apollo-server'; | ||
|
||
// GOOD: CORS is defined to deny all | ||
const apollo_graphql_potentially_bad_cors_good_1 = new ApolloServer({ | ||
typeDefs, | ||
resolvers, | ||
//ok: v3-potentially-bad-cors | ||
cors: { origin: false } | ||
}); | ||
|
||
// GOOD: CORS is defined to deny all with [] | ||
const apollo_graphql_potentially_bad_cors_good_2 = new ApolloServer({ | ||
typeDefs, | ||
resolvers, | ||
//ok: v3-potentially-bad-cors | ||
cors: { origin: [] } | ||
}); | ||
|
||
// GOOD: CORS is defined to deny all with [] from var | ||
const apollo_graphql_potentially_bad_cors_good_3_var = { origin: [] } | ||
const apollo_graphql_potentially_bad_cors_good_3 = new ApolloServer({ | ||
typeDefs, | ||
resolvers, | ||
//ok: v3-potentially-bad-cors | ||
cors: apollo_graphql_potentially_bad_cors_good_3_var | ||
}); | ||
|
||
// ==================== | ||
// BAD: Has a very permissive 'cors' | ||
const apollo_server_bad_cors_bad_1 = new ApolloServer({ | ||
typeDefs, | ||
resolvers, | ||
//ruleid: v3-potentially-bad-cors | ||
cors: { origin: true } | ||
}); | ||
|
||
// BAD: Has a very permissive 'cors' from a variable | ||
const apollo_server_bad_cors_bad_2_var = { origin: true } | ||
const apollo_server_bad_cors_bad_2 = new ApolloServer({ | ||
typeDefs, | ||
resolvers, | ||
//ruleid: v3-potentially-bad-cors | ||
cors: apollo_server_bad_cors_bad_2_var | ||
}); | ||
|
||
// ==================== | ||
// BAD: string | ||
const apollo_graphql_potentially_bad_cors_bad_3 = new ApolloServer({ | ||
typeDefs, | ||
resolvers, | ||
//ruleid: v3-potentially-bad-cors | ||
cors: { origin: "attacker.com"} | ||
}); | ||
|
||
// BAD: regex | ||
const apollo_graphql_potentially_bad_cors_bad_4 = new ApolloServer({ | ||
typeDefs, | ||
resolvers, | ||
//ruleid: v3-potentially-bad-cors | ||
cors: { origin: /\.attacker\.com$/ } | ||
}); | ||
|
||
// BAD: array of strings | ||
const apollo_graphql_potentially_bad_cors_bad_5 = new ApolloServer({ | ||
typeDefs, | ||
resolvers, | ||
//ruleid: v3-potentially-bad-cors | ||
cors: { origin: ["attacker.com", "attacker2.com", "attacker3.com"]} | ||
}); | ||
|
||
|
||
// BAD: array of strings and regex | ||
const apollo_graphql_potentially_bad_cors_bad_6 = new ApolloServer({ | ||
typeDefs, | ||
resolvers, | ||
//ruleid: v3-potentially-bad-cors | ||
cors: { origin: ["attacker.com", /attacker2\.com/, "attacker3.com"]} | ||
}); | ||
|
||
// BAD: function | ||
const apollo_graphql_potentially_bad_cors_bad_7 = new ApolloServer({ | ||
typeDefs, | ||
resolvers, | ||
//ruleid: v3-potentially-bad-cors | ||
cors: { | ||
origin: function (origin, callback) { | ||
callback(null, true) | ||
} | ||
} | ||
}); | ||
|
||
// BAD: function from var | ||
const apollo_graphql_potentially_bad_cors_bad_8_var = { | ||
origin: function (origin, callback) { | ||
callback(null, true) | ||
} | ||
} | ||
const apollo_graphql_potentially_bad_cors_bad_8 = new ApolloServer({ | ||
typeDefs, | ||
resolvers, | ||
//ruleid: v3-potentially-bad-cors | ||
cors: apollo_graphql_potentially_bad_cors_bad_8_var | ||
}); | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
rules: | ||
# Rule for potentially bad CORS policies in the batteries-included apollo-server | ||
- id: v3-potentially-bad-cors | ||
languages: [js, ts] | ||
message: >- | ||
The Apollo GraphQL server is setup with a CORS policy that does not deny all origins. Carefully review the origins to see if any of them are incorrectly setup (third-party websites, bad regexes, functions that reflect every origin, etc.). | ||
severity: WARNING | ||
metadata: | ||
category: security | ||
cwe: "CWE-942: Permissive Cross-domain Policy with Untrusted Domains" | ||
subcategory: [audit] | ||
confidence: LOW | ||
likelihood: MEDIUM | ||
impact: MEDIUM | ||
technology: | ||
- graphql | ||
- apollo-graphql-server | ||
- apollo-graphql-server-v3 | ||
description: "Potentially bad CORS policy" | ||
references: | ||
- https://www.apollographql.com/docs/apollo-server/v3/security/cors#configuring-cors-options-for-apollo-server | ||
mode: taint | ||
|
||
pattern-sources: | ||
# Remove this once the above matches functions (https://github.com/returntocorp/semgrep/issues/6748) | ||
- pattern: | | ||
{ origin: function(...) {...} } | ||
- patterns: | ||
- pattern-inside: | | ||
{ origin: $NOT_KNOWN_GOOD_CORS_ORIGIN } | ||
- metavariable-pattern: | ||
metavariable: $NOT_KNOWN_GOOD_CORS_ORIGIN | ||
patterns: | ||
# 'false' denies every origin | ||
- pattern-not: | | ||
false | ||
# An empty array denies every origin. | ||
- pattern-not: | | ||
[] | ||
pattern-sinks: | ||
- patterns: | ||
- pattern: | | ||
{..., cors: $CORS_ORIGIN, ...} | ||
- focus-metavariable: $CORS_ORIGIN |
Oops, something went wrong.