Files
grecia/spec/system/xss_spec.rb
Javi Martín ff93f5a591 Use "resolve" for polymorphic hierarchy paths
In the past, we couldn't use `polymorphic_path` in many places. For
instance, `polymorphic_path(budget, investment)` would return
`budget_budget_investment_path`, while in our routes we had defined
`budget_investment_path`.

With the `resolve` method, introduced in Rails 5.1, we can use symbols
to define we want it to use `investment` instead of `budget_investment`.
It also works with nested resources, so now we can write
`polymorphic_path(investment)`.

This makes the code for `resource_hierarchy_for` almost impossible to
understand. I reached this result after having a look at the internals
of the `resolve` method in order to get its results and then remove the
symbols we include.

Note using this method will not make admin routes compatible with
`polymorphic_path`. Quoting from the Rails documentation:

> This custom behavior only applies to simple polymorphic URLs where a
> single model instance is passed and not more complicated forms, e.g:
> [example showing admin routes won't work]

Also note that now the `admin_polymorphic_path` method will not work for
every model due to inconsistencies in our admin routes. For instance, we
define `groups` and `budget_investments`; we should either use the
`budget_` prefix in all places or remove it everywhere. Right now the
code only works for items with the prefix; it isn't a big deal because
we never call it with an item without the prefix.

Finally, for unknown reasons some routing tests fail if we use
`polymorphic_path`, so we need to redefine that method in those tests
and force the `only_path: true` option.
2020-06-15 11:54:05 +02:00

176 lines
4.9 KiB
Ruby

require "rails_helper"
describe "Cross-Site Scripting protection", :js do
let(:attack_code) { "<script>document.body.remove()</script>" }
scenario "valuators in admin investments index" do
hacker = create(:user, username: attack_code)
investment = create(:budget_investment, valuators: [create(:valuator, user: hacker)])
login_as(create(:administrator).user)
visit admin_budget_budget_investments_path(investment.budget)
expect(page.text).not_to be_empty
end
scenario "edit banner" do
banner = create(:banner, title: attack_code)
login_as(create(:administrator).user)
visit edit_admin_banner_path(banner)
title_id = find_field("Title")[:id]
execute_script "document.getElementById('#{title_id}').dispatchEvent(new Event('change'))"
expect(page.text).not_to be_empty
end
scenario "banner URL" do
banner = create(:banner, title: "Banned!", target_url: "javascript:document.body.remove()")
login_as(create(:administrator).user)
visit edit_admin_banner_path(banner)
find(:css, "a", text: "Banned!").click
expect(page.text).not_to be_empty
end
scenario "document title" do
process = create(:legislation_process)
create(:document, documentable: process, title: attack_code)
visit legislation_process_path(process)
expect(page.text).not_to be_empty
end
scenario "hacked translations" do
I18nContent.create!(key: "admin.budget_investments.index.list.title", value: attack_code)
login_as(create(:administrator).user)
visit admin_budget_budget_investments_path(create(:budget_investment).budget)
expect(page.text).not_to be_empty
end
scenario "accept terms label" do
I18nContent.create!(key: "form.accept_terms", value: attack_code)
login_as(create(:user))
visit new_debate_path
expect(page.text).not_to be_empty
end
scenario "link to sign in" do
I18nContent.create!(key: "budgets.investments.index.sidebar.not_logged_in", value: attack_code)
create(:budget, phase: "accepting")
visit budgets_path
expect(page.text).not_to be_empty
end
scenario "languages in use" do
I18nContent.create!(key: "shared.translations.languages_in_use", value: attack_code)
login_as(create(:administrator).user)
visit edit_admin_budget_path(create(:budget))
click_link "Remove language"
expect(page.text).not_to be_empty
end
scenario "proposal actions in dashboard" do
proposal = create(:proposal)
create(:dashboard_action, description: attack_code)
login_as(proposal.author)
visit recommended_actions_proposal_dashboard_path(proposal)
expect(page.text).not_to be_empty
end
scenario "new request for proposal action in dashboard" do
proposal = create(:proposal)
action = create(:dashboard_action, description: attack_code)
login_as(proposal.author)
visit new_request_proposal_dashboard_action_path(proposal, action)
expect(page.text).not_to be_empty
end
scenario "poll description setting in dashboard" do
Setting["proposals.poll_description"] = attack_code
proposal = create(:proposal)
login_as(proposal.author)
visit proposal_dashboard_polls_path(proposal)
expect(page.text).not_to be_empty
end
scenario "annotation context" do
annotation = create(:legislation_annotation)
annotation.update_column(:context, attack_code)
visit polymorphic_path(annotation)
expect(page.text).not_to be_empty
end
scenario "valuation explanations" do
investment = create(:budget_investment, price_explanation: attack_code)
valuator = create(:valuator, investments: [investment])
login_as(valuator.user)
visit valuation_budget_budget_investment_path(investment.budget, investment)
expect(page.text).not_to be_empty
end
scenario "proposal description" do
proposal = create(:proposal, description: attack_code)
visit proposal_path(proposal)
expect(page.text).not_to be_empty
end
scenario "investment description" do
investment = create(:budget_investment, description: attack_code)
visit budget_investment_path(investment.budget, investment)
expect(page.text).not_to be_empty
end
scenario "budget phase description" do
budget = create(:budget)
budget.current_phase.update!(description: attack_code)
visit budget_path(budget)
expect(page.text).not_to be_empty
end
scenario "markdown conversion" do
process = create(:legislation_process, description: attack_code)
visit legislation_process_path(process)
expect(page.text).not_to be_empty
end
scenario "legislation version body filters script tags but not header IDs" do
version = create(:legislation_draft_version, :published, body: "# Title 1\n#{attack_code}")
visit legislation_process_draft_version_path(version.process, version)
expect(page.text).not_to be_empty
expect(page).to have_css "h1#title-1", text: "Title 1"
end
end