diff --git a/security-baseline/profiles/security-baseline-level-1.yaml b/security-baseline/profiles/security-baseline-level-1.yaml index 697552e..defb7dd 100644 --- a/security-baseline/profiles/security-baseline-level-1.yaml +++ b/security-baseline/profiles/security-baseline-level-1.yaml @@ -9,7 +9,9 @@ remediate: "off" repository: # OSPS-AC-01: Require MFA for collaborators; depends on org entity # OSPS-AC-02: Hosted GitHub has this by default - + - name: osps-ac-02 + type: osps-ac-02 + def: {} # OSPS-AC-03: Prevent overwriting git history - name: osps-ac-03 type: osps-ac-03 @@ -23,7 +25,10 @@ repository: - name: osps-br-01 type: osps-br-01 def: {} - # OSPS-BR-03: Hosted GitHub has this by default + # OSPS-BR-03: Ensure secure channels for VCS + - name: osps-br-03 + type: osps-br-03 + def: {} # OSPS-BR-09: GitHub hosted releases have this, check for links in release text? # OSPS-BR-10: Not sure how to check this @@ -62,4 +67,7 @@ repository: # OSPS-SA-02: Need standardized format? Also strange that this is lv1, but user guides are lv2 - # OSPS-VM-05: Check for SECURITY.md or GitHub private vulnerability reporting \ No newline at end of file + # OSPS-VM-05: Check for SECURITY.md or GitHub private vulnerability reporting + - name: osps-vm-05 + type: osps-vm-05 + def: {} \ No newline at end of file diff --git a/security-baseline/rule-types/github/osps-ac-02.test.yaml b/security-baseline/rule-types/github/osps-ac-02.test.yaml new file mode 100644 index 0000000..7a916f8 --- /dev/null +++ b/security-baseline/rule-types/github/osps-ac-02.test.yaml @@ -0,0 +1,36 @@ +tests: + - name: repo exists and is public + def: {} + params: {} + entity: + type: repository + entity: + owner: mindersec + name: minder + expect: pass + http: + status: 200 + body: '{"visibility": "public"}' + - name: repo does not exist + def: {} + params: {} + entity: + type: repository + entity: + owner: findersec + name: finder + expect: fail + http: + status: 404 + - name: not public + def: {} + params: {} + entity: + type: repository + entity: + owner: mind-control-lazers-inc + name: watchtower + expect: "fail" + http: + status: 200 + body: '{"visibility": "private"}' diff --git a/security-baseline/rule-types/github/osps-ac-02.yaml b/security-baseline/rule-types/github/osps-ac-02.yaml new file mode 100644 index 0000000..a7075d6 --- /dev/null +++ b/security-baseline/rule-types/github/osps-ac-02.yaml @@ -0,0 +1,36 @@ +version: v1 +release_phase: alpha +type: rule-type +name: osps-ac-02 +display_name: Default collaborators to lowest privileges +short_failure_message: Collaborators default to privileged access +severity: + value: info +context: + provider: github +description: Verifies that project collaborators default to the lowest access level. +guidance: | + Reduce the risk of unauthorized access to the project’s repository + by limiting the permissions granted to collaborators. + + Most public version control systems (such as GitHub) are configured + in this manner. +def: + in_entity: repository + rule_schema: {} + ingest: + type: rest + rest: + endpoint: '/repos/{{.Entity.Owner}}/{{.Entity.Name}}' + parse: json + fallback: + - http_code: 404 + body: | + {"http_status": 404, "message": "Repo not found"} + eval: + type: jq + jq: + # Public repositories on GitHub will already have minimum _default_ permissions. + - ingested: + def: ".visibility" + constant: "public" diff --git a/security-baseline/rule-types/github/osps-br-03.test.yaml b/security-baseline/rule-types/github/osps-br-03.test.yaml new file mode 100644 index 0000000..aad0db0 --- /dev/null +++ b/security-baseline/rule-types/github/osps-br-03.test.yaml @@ -0,0 +1,36 @@ +tests: + - name: repo exists and is public + def: {} + params: {} + entity: + type: repository + entity: + owner: mindersec + name: minder + expect: pass + http: + status: 200 + body: '{"clone_url": "https://github.com/mindersec/minder.git"}' + - name: repo does not exist + def: {} + params: {} + entity: + type: repository + entity: + owner: findersec + name: finder + expect: fail + http: + status: 404 + - name: not public + def: {} + params: {} + entity: + type: repository + entity: + owner: mindersec + name: minder + expect: "fail" + http: + status: 200 + body: '{"clone_url": "http://github.com/mindersec/minder.git"}' diff --git a/security-baseline/rule-types/github/osps-br-03.yaml b/security-baseline/rule-types/github/osps-br-03.yaml new file mode 100644 index 0000000..abb52fe --- /dev/null +++ b/security-baseline/rule-types/github/osps-br-03.yaml @@ -0,0 +1,43 @@ +version: v1 +release_phase: alpha +type: rule-type +name: osps-br-03 +display_name: Development resources use secure channels +short_failure_message: Insecure access to VCS +severity: + value: info +context: + provider: github +description: Verifies that websites and version control systems for development use secure channels. +guidance: | + Any websites and version control systems involved in the project + development MUST be delivered using SSH, HTTPS, or other encrypted + channels. + + Protect the confidentiality and integrity of project source code during + development, reducing the risk of eavesdropping or data tampering. + + GitHub does this by default. +def: + in_entity: repository + rule_schema: {} + ingest: + type: rest + rest: + endpoint: '/repos/{{.Entity.Owner}}/{{.Entity.Name}}' + parse: json + fallback: + - http_code: 404 + body: | + {"http_status": 404, "message": "Repo not found"} + eval: + type: rego + rego: + type: deny-by-default + def: | + package minder + import rego.v1 + + default allow := false + + allow if startswith(input.ingested.clone_url, "https://") diff --git a/security-baseline/rule-types/github/osps-qa-01.test.yaml b/security-baseline/rule-types/github/osps-qa-01.test.yaml new file mode 100644 index 0000000..a326285 --- /dev/null +++ b/security-baseline/rule-types/github/osps-qa-01.test.yaml @@ -0,0 +1,49 @@ +tests: + - name: repo exists and is public + def: {} + params: {} + entity: + type: repository + entity: + owner: mindersec + name: minder + is_private: false + expect: pass + http: + status: 200 + body: '{"visibility": "public","clone_url": "https://github.com/mindersec/minder.git"}' + - name: repo does not exist + def: {} + params: {} + entity: + type: repository + entity: + owner: findersec + name: finder + expect: fail + http: + status: 404 + - name: not public + def: {} + params: {} + entity: + type: repository + entity: + owner: hidersec + name: hider + expect: fail + http: + status: 200 + body: '{"visibility": "private","clone_url": "http://github.com/mindersec/minder.git"}' + - name: no clone url + def: {} + params: {} + entity: + type: repository + entity: + owner: mindersec + name: minder + expect: fail + http: + status: 200 + body: '{"visibility": "public"}' diff --git a/security-baseline/rule-types/github/osps-qa-01.yaml b/security-baseline/rule-types/github/osps-qa-01.yaml index 24b0bb2..55942a2 100644 --- a/security-baseline/rule-types/github/osps-qa-01.yaml +++ b/security-baseline/rule-types/github/osps-qa-01.yaml @@ -39,5 +39,6 @@ def: allow if { # This rule checks whether the repository is private using # info tied to the entity itself. - not input.properties["is_private"] + input.ingested.visibility == "public" + input.ingested.clone_url != "" }