Skip to content

Conversation

@jordan-dr
Copy link
Contributor

No description provided.

@dryrunsecurity
Copy link

dryrunsecurity bot commented Oct 6, 2025

DryRun Security

🟡 Please give this pull request extra attention during review.

This pull request introduces direct create/update database operations in the GraphqlController that bypass GraphQL authorization, allowing unauthorised project creation and updates (IDOR) and enabling mass-assignment of user-controlled attributes (including user_id) because input is used without strong-parameter filtering or ownership checks.

🟡 Potential IDOR Vulnerability in app/controllers/graphql_controller.rb
Vulnerability Potential IDOR Vulnerability
Description The code in app/controllers/graphql_controller.rb performs project = Project.find(project_id) using a project_id derived from user-supplied variables. This lookup is not scoped to the current_user, nor is there any subsequent authorization check to ensure the current_user has permission to update the retrieved project. While the Project model belongs_to :user, this association is not utilized to enforce ownership during the find operation or the subsequent update!. There are no before_action filters in GraphqlController or ApplicationController that would apply authorization, and no explicit manual permission checks are performed. This allows an attacker to potentially update any project by supplying an arbitrary project_id.

project = Project.find(project_id)
project.update!(project_attrs)
render json: { data: { updateProject: project.as_json } } and return
end

Missing Authorization Checks and IDOR in app/controllers/graphql_controller.rb
Vulnerability Missing Authorization Checks and IDOR
Description The code introduces direct database operations for 'CreateProject' and 'UpdateProject' within the execute method of GraphqlController that bypass the standard GraphQL schema execution and any potential authorization layers it might provide. For 'CreateProject', there is no check to ensure the current_user is authorized to create a project. For 'UpdateProject', the code directly finds a project using a user-provided ID (project_id) and updates it (project.update!(project_attrs)) without verifying if the current_user has ownership or permission to modify that specific project. The Project model is associated with a User (belongs_to :user), indicating an ownership model exists, but it is not enforced in these new operations. This allows any authenticated user to create projects or update any existing project by supplying its ID, leading to an Insecure Direct Object Reference (IDOR) vulnerability for updates and a general lack of authorization for creation.

result = Project.create!(variables['project'])
render json: { data: { createProject: result.as_json } } and return
elsif operation_name == "UpdateProject"
project_id = variables.dig('project', 'id') || variables['id']
project_attrs = variables['project'] || {}
project = Project.find(project_id)
project.update!(project_attrs)

Mass Assignment in app/controllers/graphql_controller.rb
Vulnerability Mass Assignment
Description The Project.create! and project.update! methods in graphql_controller.rb directly accept a user-controlled hash (variables['project'] or project_attrs) without any sanitization or strong parameter filtering. This allows an attacker to set arbitrary attributes on the Project model, including sensitive ones like user_id, which determines project ownership.

# Query context goes here, for example:
# current_user: current_user,
}
if operation_name == "CreateProject"
result = Project.create!(variables['project'])
render json: { data: { createProject: result.as_json } } and return
elsif operation_name == "UpdateProject"
project_id = variables.dig('project', 'id') || variables['id']
project_attrs = variables['project'] || {}
project = Project.find(project_id)
project.update!(project_attrs)
render json: { data: { updateProject: project.as_json } } and return
end
result = ProjectManagementAppSchema.execute(query, variables: variables, context: context, operation_name: operation_name)
render json: result
rescue StandardError => e


All finding details can be found in the DryRun Security Dashboard.

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 this pull request may close these issues.

2 participants