We were converting markdown to HTML every time we saved a record, which has the same problems as sanitizing HTML before saving it to the database, particularly because the body of a legislation draft is stored in a translations table. Performance-wise this isn't a problem: converting a text with more than 200_000 characters takes about a milisecond on my machine. Note we need to modify a migration generated by globalize, since the method `create_translation_table!` would fail now that we don't define `translates :body_html` in the model.
166 lines
4.6 KiB
Ruby
166 lines
4.6 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 "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_hierarchy_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
|