mirror of
https://github.com/opf/openproject.git
synced 2026-06-13 19:20:00 +00:00
Merge pull request #23555 from opf/precise-ssrf-error
Be more precise about SSRF errors
This commit is contained in:
@@ -2197,17 +2197,14 @@ en:
|
||||
before: "must be before %{date}."
|
||||
before_or_equal_to: "must be before or equal to %{date}."
|
||||
blank: "can't be blank."
|
||||
not_before_start_date: "must not be before the start date."
|
||||
overlapping_range: "overlaps with an existing non-working day range."
|
||||
blank_nested: "needs to have the property '%{property}' set."
|
||||
cannot_delete_mapping: "is required. Cannot be deleted."
|
||||
is_for_all_cannot_modify: "is for all projects and can therefore not be modified."
|
||||
cant_link_a_work_package_with_a_descendant: "A work package cannot be linked to one of its subtasks."
|
||||
circular_dependency: "This relation would create a circular dependency."
|
||||
confirmation: "doesn't match %{attribute}."
|
||||
could_not_be_copied: "%{dependency} could not be (fully) copied."
|
||||
datetime_must_be_in_future: "must be in the future."
|
||||
does_not_exist: "does not exist."
|
||||
user_already_in_department: "User %{user_id} is already a member of department %{department_id}."
|
||||
error_enterprise_only: "%{action} is only available in the OpenProject Enterprise edition."
|
||||
error_unauthorized: "may not be accessed."
|
||||
error_readonly: "was attempted to be written but is not writable."
|
||||
@@ -2228,36 +2225,38 @@ en:
|
||||
greater_than_or_equal_to: "must be greater than or equal to %{count}."
|
||||
greater_than_or_equal_to_start_date: "must be greater than or equal to the start date."
|
||||
greater_than_start_date: "must be greater than the start date."
|
||||
hexcode_invalid: "is not a valid 6-digit hexadecimal color code."
|
||||
inclusion: "is not set to one of the allowed values."
|
||||
inclusion_nested: "is not set to one of the allowed values at path '%{path}'."
|
||||
invalid: "is invalid."
|
||||
invalid_uri: "must be a valid URI."
|
||||
invalid_url: "is not a valid URL."
|
||||
invalid_url_scheme: "is not a supported protocol (allowed: %{allowed_schemes})."
|
||||
is_for_all_cannot_modify: "is for all projects and can therefore not be modified."
|
||||
less_than_or_equal_to: "must be less than or equal to %{count}."
|
||||
not_available: "is not available due to a system configuration."
|
||||
not_before_start_date: "must not be before the start date."
|
||||
not_deletable: "cannot be deleted."
|
||||
not_editable: "cannot be edited because it is already in effect."
|
||||
not_current_user: "is not the current user."
|
||||
system_wide_non_working_day_exists: "conflicts with an existing system-wide non-working day for this date."
|
||||
not_found: "not found."
|
||||
not_a_date: "is not a valid date."
|
||||
not_a_datetime: "is not a valid date time."
|
||||
not_a_number: "is not a number."
|
||||
not_allowed: "is invalid because of missing permissions."
|
||||
host_not_allowed: "is not an allowed host."
|
||||
not_json: "is not parseable as JSON."
|
||||
not_json_object: "is not a JSON object."
|
||||
not_an_integer: "is not an integer."
|
||||
not_an_iso_date: "is not a valid date. Required format: YYYY-MM-DD."
|
||||
not_same_project: "doesn't belong to the same project."
|
||||
datetime_must_be_in_future: "must be in the future."
|
||||
odd: "must be odd."
|
||||
overlapping_range: "overlaps with an existing non-working day range."
|
||||
regex_match_failed: "does not match the regular expression %{expression}."
|
||||
regex_invalid: "could not be validated with the associated regular expression."
|
||||
regex_list_invalid: "Lines %{invalid_lines} could not be parsed as regular expression."
|
||||
hexcode_invalid: "is not a valid 6-digit hexadecimal color code."
|
||||
smaller_than_or_equal_to_max_length: "must be smaller than or equal to maximum length."
|
||||
ssrf_filtered: "violates the SSRF policy of this OpenProject instance."
|
||||
system_wide_non_working_day_exists: "conflicts with an existing system-wide non-working day for this date."
|
||||
taken: "has already been taken."
|
||||
too_long: "is too long (maximum is %{count} characters)."
|
||||
too_short: "is too short (minimum is %{count} characters)."
|
||||
@@ -2269,6 +2268,7 @@ en:
|
||||
unremovable: "cannot be removed."
|
||||
url_not_secure_context: >
|
||||
is not providing a "Secure Context". Either use HTTPS or a loopback address, such as localhost.
|
||||
user_already_in_department: "User %{user_id} is already a member of department %{department_id}."
|
||||
wrong_length: "is the wrong length (should be %{count} characters)."
|
||||
models:
|
||||
group:
|
||||
|
||||
@@ -19,7 +19,20 @@ In these Release Notes, we will give an overview of important feature changes. A
|
||||
|
||||
## Important updates and breaking changes
|
||||
|
||||
<!-- Remove this section if empty, add to it in pull requests linking to tickets and provide information -->
|
||||
### Integrations (e.g. Nextcloud and XWiki) respect global SSRF filters
|
||||
|
||||
To increase the security of OpenProject installations, we've added protections against server-side request forgery in previous releases
|
||||
of OpenProject. These prevent OpenProject from making network requests into private IP address space.
|
||||
|
||||
Starting with OpenProject 17.6, these protections expand into the code that's responsible for web requests of storage and wiki integrations as well.
|
||||
This means if you have a Nextcloud instance or an XWiki instance reachable via a private (i.e. not publicly routable) IP address, you need to
|
||||
add it to the SSRF allowlist to be able to keep the integration working. This is usually achieved by defining the following environment variable:
|
||||
|
||||
```
|
||||
OPENPROJECT_SSRF_PROTECTION_IP_ALLOWLIST=2001:db8:100::/48
|
||||
```
|
||||
|
||||
The list accepts one or multiple IP addresses or ranges (in CIDR notation) that shall be exempt from SSRF filtering.
|
||||
|
||||
<!-- BEGIN SECURITY FIXES AUTOMATED SECTION -->
|
||||
|
||||
|
||||
@@ -114,7 +114,7 @@ module OpenIDConnect
|
||||
if host.present? && OpenProject::SsrfProtection.safe_ip?(host)
|
||||
true
|
||||
else
|
||||
call.errors.add(:metadata_url, :host_not_allowed)
|
||||
call.errors.add(:metadata_url, :ssrf_filtered)
|
||||
call.success = false
|
||||
false
|
||||
end
|
||||
|
||||
+1
-1
@@ -92,7 +92,7 @@ RSpec.describe OpenIDConnect::Providers::UpdateService, type: :model do
|
||||
result = service_call
|
||||
|
||||
expect(result).not_to be_success
|
||||
expect(result.errors[:metadata_url]).to include("is not an allowed host.")
|
||||
expect(result.errors[:metadata_url]).to include("violates the SSRF policy of this OpenProject instance.")
|
||||
expect(httpx_session).not_to have_received(:get)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -50,7 +50,7 @@ class NextcloudCompatibleHostValidator < ActiveModel::EachValidator
|
||||
return false if host.blank?
|
||||
return true if OpenProject::SsrfProtection.safe_ip?(host)
|
||||
|
||||
contract.errors.add(attribute, :host_not_allowed)
|
||||
contract.errors.add(attribute, :ssrf_filtered)
|
||||
false
|
||||
rescue URI::InvalidURIError
|
||||
false
|
||||
|
||||
@@ -275,7 +275,7 @@ RSpec.shared_examples_for "nextcloud storage contract", :storage_server_helpers,
|
||||
context "when host is localhost" do
|
||||
let(:storage_host) { "http://localhost:1234" }
|
||||
|
||||
include_examples "contract is invalid", host: :host_not_allowed
|
||||
include_examples "contract is invalid", host: :ssrf_filtered
|
||||
|
||||
it "does not perform metadata discovery requests" do
|
||||
contract.validate
|
||||
@@ -288,7 +288,7 @@ RSpec.shared_examples_for "nextcloud storage contract", :storage_server_helpers,
|
||||
context "when host uses https protocol" do
|
||||
let(:storage_host) { "https://172.16.193.146" }
|
||||
|
||||
include_examples "contract is invalid", host: :host_not_allowed
|
||||
include_examples "contract is invalid", host: :ssrf_filtered
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
Reference in New Issue
Block a user