Skip to content

Commit

Permalink
feat: Ruby policy for exposure of data category to third party (#210)
Browse files Browse the repository at this point in the history
  • Loading branch information
spdawson authored Dec 7, 2022
1 parent f54b737 commit df6790b
Show file tree
Hide file tree
Showing 11 changed files with 343 additions and 0 deletions.
101 changes: 101 additions & 0 deletions integration/flags/.snapshots/TestInitCommand-init
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,34 @@ scan:
stored: false
detect_presence: false
omit_parent: false
detect_ruby_third_party_data_send:
disabled: false
type: risk
languages:
- ruby
param_parenting: false
processors: []
patterns:
- pattern: |
Sentry::Breadcrumb.new(<$ARGUMENT>)
filters: []
- pattern: |
Sentry.init do |config|
config.before_breadcrumb = lambda do |breadcrumb, hint|
breadcrumb.message = $ANYTHING
breadcrumb
end
end
filters: []
- pattern: |
Sentry.set_user(<$ARGUMENT>)
filters: []
root_singularize: false
root_lowercase: false
metavars: {}
stored: false
detect_presence: false
omit_parent: false
detect_sql_create_public_table:
disabled: false
type: data_type
Expand Down Expand Up @@ -1047,6 +1075,79 @@ scan:

import future.keywords

policy_breach contains item if {
some detector in input.dataflow.risks
detector.detector_id == input.policy_id

data_type = detector.data_types[_]

location = data_type.locations[_]
item := {
"category_groups": data.bearer.common.groups_for_datatype(data_type),
"severity": data.bearer.common.severity_of_datatype(data_type),
"filename": location.filename,
"line_number": location.line_number,
"parent_line_number": location.parent.line_number,
"parent_content": location.parent.content
}
}
sending_data_in_category_to_third_party:
query: |
policy_breach = data.bearer.third_party_data_category.policy_breach
id: detect_ruby_third_party_data_send
name: Third-party data category exposure
description: Sending data in category to third party
level: ""
modules:
- path: policies/common.rego
name: bearer.common
content: |
package bearer.common

import future.keywords

sensitive_data_group_uuid := "f6a0c071-5908-4420-bac2-bba28d41223e"
personal_data_group_uuid := "e1d3135b-3c0f-4b55-abce-19f27a26cbb3"

severity_of_datatype(data_type) := "critical" if {
some category in input.data_categories
category.uuid == data_type.category_uuid

some group in category.groups
group.uuid == sensitive_data_group_uuid
}

severity_of_datatype(data_type) := "high" if {
some category in input.data_categories
category.uuid == data_type.category_uuid

some group in category.groups
group.uuid == personal_data_group_uuid

every group_1 in category.groups {
group_1.uuid != sensitive_data_group_uuid
}
}

groups_for_datatype(data_type) := x if {
some category in input.data_categories
category.uuid == data_type.category_uuid

x := {name | name := category.groups[_].name}
}

groups_for_datatypes(data_types) := groups if {
groups := {name | name := groups_for_datatype(data_types[_])[_]}
}
- path: policies/third_party_data_category.rego
name: bearer.third_party_data_category
content: |
package bearer.third_party_data_category

import data.bearer.common

import future.keywords

policy_breach contains item if {
some detector in input.dataflow.risks
detector.detector_id == input.policy_id
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
high:
- policy_name: Third-party data category exposure
policy_description: Sending data in category to third party
line_number: 12
filename: testdata/ruby/sending_data_in_category_to_third_party.rb
category_groups:
- PHI
- PII
parent_line_number: 10
parent_content: |-
Sentry::Breadcrumb.new(
category: "auth",
message: "Authenticated user #{user.email}",
level: "info"
)
omit_parent: false
- policy_name: Third-party data category exposure
policy_description: Sending data in category to third party
line_number: 18
filename: testdata/ruby/sending_data_in_category_to_third_party.rb
category_groups:
- PHI
- PII
parent_line_number: 16
parent_content: |-
Sentry.init do |config|
config.before_breadcrumb = lambda do |breadcrumb, hint|
breadcrumb.message = "Authenticated user #{current_user.email}"
breadcrumb
end
end
omit_parent: false
- policy_name: Third-party data category exposure
policy_description: Sending data in category to third party
line_number: 24
filename: testdata/ruby/sending_data_in_category_to_third_party.rb
category_groups:
- PHI
- PII
parent_line_number: 24
parent_content: 'Sentry.set_user(email: user.email)'
omit_parent: false


--

1 change: 1 addition & 0 deletions integration/policies/policies_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ func TestPolicies(t *testing.T) {
newPolicyTest("insecure_smtp", []string{"ruby/insecure_smtp.rb"}),
newPolicyTest("insecure_communication", []string{"ruby/insecure_communication.rb"}),
newPolicyTest("insecure_ftp", []string{"ruby/insecure_ftp.rb"}),
newPolicyTest("sending_data_in_category_to_third_party", []string{"ruby/sending_data_in_category_to_third_party.rb"}),
}

testhelper.RunTests(t, tests)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Ruby third-party data send

class User
attr_accessor :email
end

current_user = user = User.new

## Detected
Sentry::Breadcrumb.new(
category: "auth",
message: "Authenticated user #{user.email}",
level: "info"
)

Sentry.init do |config|
config.before_breadcrumb = lambda do |breadcrumb, hint|
breadcrumb.message = "Authenticated user #{current_user.email}"
breadcrumb
end
end

# https://docs.sentry.io/platforms/ruby/guides/rails/enriching-events/identify-user/
Sentry.set_user(email: user.email)
16 changes: 16 additions & 0 deletions pkg/commands/process/settings/custom_detector.yml
Original file line number Diff line number Diff line change
Expand Up @@ -214,3 +214,19 @@ detect_rails_insecure_ftp:
languages:
- ruby
detect_presence: true
detect_ruby_third_party_data_send:
type: "risk"
patterns:
- |
Sentry::Breadcrumb.new(<$ARGUMENT>)
- |
Sentry.init do |config|
config.before_breadcrumb = lambda do |breadcrumb, hint|
breadcrumb.message = $ANYTHING
breadcrumb
end
end
- |
Sentry.set_user(<$ARGUMENT>)
languages:
- ruby
11 changes: 11 additions & 0 deletions pkg/commands/process/settings/policies.yml
Original file line number Diff line number Diff line change
Expand Up @@ -119,3 +119,14 @@ insecure_http_with_data_category:
name: bearer.common
- path: policies/insecure_http_with_data_category.rego
name: bearer.insecure_http_with_data_category
sending_data_in_category_to_third_party:
description: "Sending data in category to third party"
name: "Third-party data category exposure"
id: "detect_ruby_third_party_data_send"
query: |
policy_breach = data.bearer.third_party_data_category.policy_breach
modules:
- path: policies/common.rego
name: bearer.common
- path: policies/third_party_data_category.rego
name: bearer.third_party_data_category
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package bearer.third_party_data_category

import data.bearer.common

import future.keywords

policy_breach contains item if {
some detector in input.dataflow.risks
detector.detector_id == input.policy_id

data_type = detector.data_types[_]

location = data_type.locations[_]
item := {
"category_groups": data.bearer.common.groups_for_datatype(data_type),
"severity": data.bearer.common.severity_of_datatype(data_type),
"filename": location.filename,
"line_number": location.line_number,
"parent_line_number": location.parent.line_number,
"parent_content": location.parent.content
}
}
56 changes: 56 additions & 0 deletions pkg/detectors/custom/.snapshots/TestRubyThirdPartyDataSendJSON
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
[
{
"type": "custom",
"detector_type": "detect_ruby_third_party_data_send",
"source": {
"filename": "config.rb",
"language": "Ruby",
"language_type": "programming",
"line_number": 6,
"column_number": 39,
"text": null
},
"value": {
"object_name": "user",
"field_name": "email",
"field_type": "",
"field_type_simple": "unknown"
}
},
{
"type": "custom",
"detector_type": "detect_ruby_third_party_data_send",
"source": {
"filename": "config.rb",
"language": "Ruby",
"language_type": "programming",
"line_number": 12,
"column_number": 61,
"text": null
},
"value": {
"object_name": "current_user",
"field_name": "email",
"field_type": "",
"field_type_simple": "unknown"
}
},
{
"type": "custom",
"detector_type": "detect_ruby_third_party_data_send",
"source": {
"filename": "config.rb",
"language": "Ruby",
"language_type": "programming",
"line_number": 18,
"column_number": 29,
"text": null
},
"value": {
"object_name": "user",
"field_name": "email",
"field_type": "",
"field_type_simple": "unknown"
}
}
]
32 changes: 32 additions & 0 deletions pkg/detectors/custom/custom_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ var configInsecureCommunication []byte
//go:embed testdata/config/insecure_ftp.yml
var configInsecureFTP []byte

//go:embed testdata/config/ruby_third_party_data_send.yml
var configRubyThirdPartyDataSend []byte

func TestRailsSessionsJSON(t *testing.T) {
var rulesConfig map[string]settings.Rule

Expand Down Expand Up @@ -336,3 +339,32 @@ func TestInsecureFTPJSON(t *testing.T) {

cupaloy.SnapshotT(t, string(bytes))
}

func TestRubyThirdPartyDataSendJSON(t *testing.T) {
var rulesConfig map[string]settings.Rule

detector := custom.New(&nodeid.IntGenerator{Counter: 0})
err := yaml.Unmarshal(configRubyThirdPartyDataSend, &rulesConfig)
if err != nil {
t.Fatal(err)
return
}
customDetector := detector.(*custom.Detector)
err = customDetector.CompileRules(rulesConfig)
if err != nil {
t.Fatal(err)
}

var registrations = []detectors.InitializedDetector{{
Type: detectorType,
Detector: detector}}
detectorReport := testhelper.Extract(t, filepath.Join("testdata", "ruby", "third_party_data_send"), registrations, detectorType)

bytes, err := json.MarshalIndent(detectorReport.CustomDetections, "", " ")

if err != nil {
t.Fatal(err)
}

cupaloy.SnapshotT(t, string(bytes))
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
detect_ruby_third_party_data_send:
type: "risk"
patterns:
- |
Sentry::Breadcrumb.new(<$ARGUMENT>)
- |
Sentry.init do |config|
config.before_breadcrumb = lambda do |breadcrumb, hint|
breadcrumb.message = $ANYTHING
breadcrumb
end
end
- |
Sentry.set_user(<$ARGUMENT>)
languages:
- ruby
18 changes: 18 additions & 0 deletions pkg/detectors/custom/testdata/ruby/third_party_data_send/config.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Ruby third-party data send

## Detected
Sentry::Breadcrumb.new(
category: "auth",
message: "Authenticated user #{user.email}",
level: "info"
)

Sentry.init do |config|
config.before_breadcrumb = lambda do |breadcrumb, hint|
breadcrumb.message = "Authenticated user #{current_user.email}"
breadcrumb
end
end

# https://docs.sentry.io/platforms/ruby/guides/rails/enriching-events/identify-user/
Sentry.set_user(email: user.email)

0 comments on commit df6790b

Please sign in to comment.