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

Allow disabling introspection queries #456

Closed
bsmedberg-xometry opened this issue Nov 11, 2019 · 9 comments · Fixed by #1227
Closed

Allow disabling introspection queries #456

bsmedberg-xometry opened this issue Nov 11, 2019 · 9 comments · Fixed by #1227
Assignees
Labels
feature New feature or request k::api Related to API (application interface) k::security Related to security
Milestone

Comments

@bsmedberg-xometry
Copy link

Is your feature request related to a problem? Please describe.
I would like to avoid serving introspection in production builds of some services. I have a build pipeline that publishes the schema to an artifact at build time using juniper::introspect, so I really don't need the online schema to be available on my production services.

Describe the solution you'd like
I was looking for a way to disable introspection lookups on a RootNode, or filter introspection queries out at some layer of context, but I couldn't find an option to do that.

Describe alternatives you've considered
Haven't found an alternative yet.

Additional context
I'm happy to implement this but I'm not sure where to hang this. On the executor? That way in src/schema/schema.rs resolve_field, I could selectively resolve or fail depending on whether introspection was enabled or disabled on the executor, but would that involve passing in a new option to .execute(). Or does it makes sense to configure the root node with this flag?

@bsmedberg-xometry bsmedberg-xometry added the enhancement Improvement of existing features or bugfix label Nov 11, 2019
@bsmedberg-xometry bsmedberg-xometry changed the title Disable introspection queries Allow disabling introspection queries Nov 11, 2019
@davidpdrsn
Copy link
Contributor

It seems other graphql communities have something called "validations" that allow you to validate a query before even running it. Such as graphql-dotnet/graphql-dotnet#766. That should probably be able to handle this. I wonder if it could also handle this #447

@tyranron
Copy link
Member

I wonder if it could also handle this #447

Hmm... I guess not. The reason behind this that authorization is somewhat defined on user-defined GraphQL types, or even exists before any schema resolution (so schema in this case is authorization-agnostic), while the introspection query does not interact with user-defined types, but their meta (which handled by Juniper automatically).

I guess this could be solved either allowing to attach some code for meta resolving or deeply inspecting the request before executing.

@saskenuba
Copy link

saskenuba commented Oct 2, 2020

Any more thought was given to this? Introspection should be disabled in production environments unless you have a public-facing API where you need it, in order to avoid enumeration of types/queries.

It would be nice to opt queries and types out of the default public visibility.
Perhaps as a proc macro attribute where the default is to expose, but can be made private:

#[graphql(description = "..", visibility = "private")]
    fn query(context: &Context, ..) -> FieldResult<..> {
        //..
	}

But with this approach, there is the problem of: A change on type visibility should also affect related queries, or is the user responsibility to expose properly?

Or even the simplest option is to disable introspection server-wide while there is a better solution to individual visibility.

@LegNeato
Copy link
Member

LegNeato commented Oct 6, 2020

Is it even spec compliant to not allow introspection? We don't handle introspections in a special way, we just treat them as a normal query (and this is how they are handled in the spec).

@saskenuba
Copy link

While I am almost certain it is not mentioned in the spec, it is positively a good thing to have natively in the framework. Please forgive me if there is already a mechanism to implement something like this, I still do not have a lot of familiarity with juniper.

Several frameworks allow disabling introspection nativaly, such as Apollo Graphql, grapql-php, graphql-ruby

Other frameworks allow the user to replace the schema with another one through middleware, e.g Python Graphene

Like @tyranron suggested, most of them inspect the query to check for __schema and __type introspection entry points.

We can find several security-oriented websites that recommend disabling introspection to make potential attackers have more trouble finding vulnerabilities, avoid leaking non-public types, and errors in general:

@LegNeato
Copy link
Member

Thank you for this! I agree this is good to have.

@superkonduktr
Copy link

Hi! I’m wondering if this could be done with an optional Cargo feature that disables introspection queries entirely. Here’s a short version of how I did it in a project where introspection must be disabled due to security requirements. Would you be interested in adding something like this?

Thank you!

@tyranron tyranron added this to the 0.16.0 milestone Nov 9, 2023
@tyranron tyranron self-assigned this Nov 9, 2023
@tyranron tyranron added k::api Related to API (application interface) feature New feature or request k::security Related to security and removed enhancement Improvement of existing features or bugfix labels Nov 9, 2023
@tyranron
Copy link
Member

It seems other graphql communities have something called "validations" that allow you to validate a query before even running it. Such as graphql-dotnet/graphql-dotnet#766.

The GraphQL over HTTP spec mentions it too.

The server MAY, at its discretion, apply additional validation rules.

tyranron added a commit that referenced this issue Nov 28, 2023
- implement `validation::rules::disable_introspection`
- add `RootNode::disable_introspection()` and `RootNode::enable_introspection()` methods
@tyranron
Copy link
Member

As we don't have machinery for specifying custom validation rules at the moment, it's implemented via RootNode::disable_introspection() method, which applies the validation::rules::disable_introspection under-the-hood.

/// Disables introspection for this [`RootNode`], making it to return a [`FieldError`] whenever
/// its `__schema` or `__type` field is resolved.
///
/// By default, all introspection queries are allowed.
///
/// # Example
///
/// ```rust
/// # use juniper::{
/// # graphql_object, graphql_vars, EmptyMutation, EmptySubscription, GraphQLError,
/// # RootNode,
/// # };
/// #
/// pub struct Query;
///
/// #[graphql_object]
/// impl Query {
/// fn some() -> bool {
/// true
/// }
/// }
///
/// type Schema = RootNode<'static, Query, EmptyMutation<()>, EmptySubscription<()>>;
///
/// let schema = Schema::new(Query, EmptyMutation::new(), EmptySubscription::new())
/// .disable_introspection();
///
/// # // language=GraphQL
/// let query = "query { __schema { queryType { name } } }";
///
/// match juniper::execute_sync(query, None, &schema, &graphql_vars! {}, &()) {
/// Err(GraphQLError::ValidationError(errs)) => {
/// assert_eq!(
/// errs.first().unwrap().message(),
/// "GraphQL introspection is not allowed, but the operation contained `__schema`",
/// );
/// }
/// res => panic!("expected `ValidationError`, returned: {res:#?}"),
/// }
/// ```
pub fn disable_introspection(mut self) -> Self {

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature New feature or request k::api Related to API (application interface) k::security Related to security
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants