diff --git a/data-sources/ghapi.yaml b/data-sources/ghapi.yaml index f9c8fcc..c821367 100644 --- a/data-sources/ghapi.yaml +++ b/data-sources/ghapi.yaml @@ -14,3 +14,13 @@ rest: type: string repo: type: string + repo: + endpoint: https://api.github.com/repos/{owner}/{repo} + parse: json + input_schema: + type: object + properties: + owner: + type: string + repo: + type: string diff --git a/rule-types/github/branch_protection_allow_deletions.test.yaml b/rule-types/github/branch_protection_allow_deletions.test.yaml new file mode 100644 index 0000000..eb94da2 --- /dev/null +++ b/rule-types/github/branch_protection_allow_deletions.test.yaml @@ -0,0 +1,49 @@ +tests: + - name: "force push not allowed" + def: {} + params: {} + entity: + type: repository + entity: + owner: "mindersec" + name: "minder" + expect: "pass" + http: + status: 200 + body: '{"allow_deletions": {"enabled": false}}' + - name: "force push allowed" + def: {} + params: {} + entity: + type: repository + entity: + owner: "mindersec" + name: "minder" + expect: "fail" + http: + status: 200 + body: '{"allow_deletions": {"enabled": true}}' + - name: "not found" + def: {} + params: {} + entity: + type: repository + entity: + owner: "mindersec" + name: "minder" + expect: "fail" + http: + status: 404 + body: '{"woot": "woot"}' + - name: "internal error" + def: {} + params: {} + entity: + type: repository + entity: + owner: "mindersec" + name: "minder" + expect: "fail" + http: + status: 502 + body: '{"woot": "woot"}' diff --git a/rule-types/github/branch_protection_allow_force_pushes.test.yaml b/rule-types/github/branch_protection_allow_force_pushes.test.yaml new file mode 100644 index 0000000..5d44329 --- /dev/null +++ b/rule-types/github/branch_protection_allow_force_pushes.test.yaml @@ -0,0 +1,49 @@ +tests: + - name: "force push not allowed" + def: {} + params: {} + entity: + type: repository + entity: + owner: "mindersec" + name: "minder" + expect: "pass" + http: + status: 200 + body: '{"allow_force_pushes": {"enabled": false}}' + - name: "force push allowed" + def: {} + params: {} + entity: + type: repository + entity: + owner: "mindersec" + name: "minder" + expect: "fail" + http: + status: 200 + body: '{"allow_force_pushes": {"enabled": true}}' + - name: "not found" + def: {} + params: {} + entity: + type: repository + entity: + owner: "mindersec" + name: "minder" + expect: "fail" + http: + status: 404 + body: '{"woot": "woot"}' + - name: "internal error" + def: {} + params: {} + entity: + type: repository + entity: + owner: "mindersec" + name: "minder" + expect: "fail" + http: + status: 502 + body: '{"woot": "woot"}' diff --git a/rules_test.go b/rules_test.go index 42ef0c4..42b438a 100644 --- a/rules_test.go +++ b/rules_test.go @@ -131,50 +131,52 @@ func TestRuleTypes(t *testing.T) { require.NoError(t, os.Setenv("REGO_ENABLE_PRINT", "true")) - // iterate rule types directory - err := walkRuleTypesTests(t, func(t *testing.T, rt *minderv1.RuleType, tc *RuleTest, rtDataPath string) { - var opts []tkv1.Option - if rt.Def.Ingest.Type == "git" { - opts = append(opts, gitTestOpts(t, tc, rtDataPath)) - } else if rt.Def.Ingest.Type == "rest" { - opts = append(opts, httpTestOpts(t, tc, rtDataPath)) - } else { - t.Skipf("Unsupported ingest type %s", rt.Def.Ingest.Type) - } + for _, folder := range []string{"rule-types", "security-baseline/rule-types"} { + // iterate rule types directory + err := walkRuleTypesTests(t, folder, func(t *testing.T, rt *minderv1.RuleType, tc *RuleTest, rtDataPath string) { + var opts []tkv1.Option + if rt.Def.Ingest.Type == "git" { + opts = append(opts, gitTestOpts(t, tc, rtDataPath)) + } else if rt.Def.Ingest.Type == "rest" { + opts = append(opts, httpTestOpts(t, tc, rtDataPath)) + } else { + t.Skipf("Unsupported ingest type %s", rt.Def.Ingest.Type) + } - ztw := zerolog.NewTestWriter(t) - zerolog.SetGlobalLevel(zerolog.DebugLevel) - ctx := zerolog.New(ztw).With().Timestamp().Logger().WithContext(context.Background()) + ztw := zerolog.NewTestWriter(t) + zerolog.SetGlobalLevel(zerolog.DebugLevel) + ctx := zerolog.New(ztw).With().Timestamp().Logger().WithContext(context.Background()) - tk := tkv1.NewTestKit(opts...) - rte, err := rtengine.NewRuleTypeEngine(ctx, rt, tk, nil) - require.NoError(t, err) + tk := tkv1.NewTestKit(opts...) + rte, err := rtengine.NewRuleTypeEngine(ctx, rt, tk, nil) + require.NoError(t, err) - val := rte.GetRuleInstanceValidator() - require.NoError(t, val.ValidateRuleDefAgainstSchema(tc.Def), "Failed to validate rule definition against schema") - require.NoError(t, val.ValidateParamsAgainstSchema(tc.Params), "Failed to validate params against schema") + val := rte.GetRuleInstanceValidator() + require.NoError(t, val.ValidateRuleDefAgainstSchema(tc.Def), "Failed to validate rule definition against schema") + require.NoError(t, val.ValidateParamsAgainstSchema(tc.Params), "Failed to validate params against schema") - if tk.ShouldOverrideIngest() { - rte.WithCustomIngester(tk) - } + if tk.ShouldOverrideIngest() { + rte.WithCustomIngester(tk) + } - _, err = rte.Eval(ctx, tc.Entity.Entity, tc.Def, tc.Params, tkv1.NewVoidResultSink()) - if tc.Expect == ExpectPass { - require.NoError(t, err) - } else { - require.Error(t, err) - } - }) + _, err = rte.Eval(ctx, tc.Entity.Entity, tc.Def, tc.Params, tkv1.NewVoidResultSink()) + if tc.Expect == ExpectPass { + require.NoError(t, err) + } else { + require.Error(t, err) + } + }) - if err != nil { - t.Error(err) + if err != nil { + t.Error(err) + } } } -func walkRuleTypesTests(t *testing.T, testfunc RuleTypeTestFunc) error { +func walkRuleTypesTests(t *testing.T, folder string, testfunc RuleTypeTestFunc) error { t.Helper() - return filepath.Walk("rule-types", func(path string, info os.FileInfo, err error) error { + return filepath.Walk(folder, func(path string, info os.FileInfo, err error) error { if err != nil { return err } diff --git a/security-baseline/data-sources/ghapi.yaml b/security-baseline/data-sources/ghapi.yaml new file mode 120000 index 0000000..48e59b4 --- /dev/null +++ b/security-baseline/data-sources/ghapi.yaml @@ -0,0 +1 @@ +data-sources/ghapi.yaml \ No newline at end of file diff --git a/security-baseline/rule-types/github/osps-ac-03.test.yaml b/security-baseline/rule-types/github/osps-ac-03.test.yaml new file mode 100644 index 0000000..5d44329 --- /dev/null +++ b/security-baseline/rule-types/github/osps-ac-03.test.yaml @@ -0,0 +1,49 @@ +tests: + - name: "force push not allowed" + def: {} + params: {} + entity: + type: repository + entity: + owner: "mindersec" + name: "minder" + expect: "pass" + http: + status: 200 + body: '{"allow_force_pushes": {"enabled": false}}' + - name: "force push allowed" + def: {} + params: {} + entity: + type: repository + entity: + owner: "mindersec" + name: "minder" + expect: "fail" + http: + status: 200 + body: '{"allow_force_pushes": {"enabled": true}}' + - name: "not found" + def: {} + params: {} + entity: + type: repository + entity: + owner: "mindersec" + name: "minder" + expect: "fail" + http: + status: 404 + body: '{"woot": "woot"}' + - name: "internal error" + def: {} + params: {} + entity: + type: repository + entity: + owner: "mindersec" + name: "minder" + expect: "fail" + http: + status: 502 + body: '{"woot": "woot"}' diff --git a/security-baseline/rule-types/github/osps-ac-03.yaml b/security-baseline/rule-types/github/osps-ac-03.yaml new file mode 100644 index 0000000..041c638 --- /dev/null +++ b/security-baseline/rule-types/github/osps-ac-03.yaml @@ -0,0 +1,38 @@ +version: v1 +release_phase: alpha +type: rule-type +name: osps-ac-04 +display_name: Prevent overwriting git history +short_failure_message: Force pushes are allowed +severity: + value: info +context: + provider: github +description: Disallow force pushes to the branch +guidance: | + Ensure that the appropriate setting is disabled for the branch + protection rule. + + This setting prevents users with push access to force push to the + branch. + + For more information, see [GitHub's + documentation](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-protected-branches/managing-a-branch-protection-rule). +def: + in_entity: repository + rule_schema: {} + ingest: + type: rest + rest: + endpoint: '/repos/{{.Entity.Owner}}/{{.Entity.Name}}/branches/{{ .Entity.DefaultBranch }}/protection' + parse: json + fallback: + - http_code: 404 + body: | + {"http_status": 404, "message": "Not Protected"} + eval: + type: jq + jq: + - ingested: + def: ".allow_force_pushes.enabled" + constant: false diff --git a/security-baseline/rule-types/github/osps-ac-04.test.yaml b/security-baseline/rule-types/github/osps-ac-04.test.yaml new file mode 100644 index 0000000..eb94da2 --- /dev/null +++ b/security-baseline/rule-types/github/osps-ac-04.test.yaml @@ -0,0 +1,49 @@ +tests: + - name: "force push not allowed" + def: {} + params: {} + entity: + type: repository + entity: + owner: "mindersec" + name: "minder" + expect: "pass" + http: + status: 200 + body: '{"allow_deletions": {"enabled": false}}' + - name: "force push allowed" + def: {} + params: {} + entity: + type: repository + entity: + owner: "mindersec" + name: "minder" + expect: "fail" + http: + status: 200 + body: '{"allow_deletions": {"enabled": true}}' + - name: "not found" + def: {} + params: {} + entity: + type: repository + entity: + owner: "mindersec" + name: "minder" + expect: "fail" + http: + status: 404 + body: '{"woot": "woot"}' + - name: "internal error" + def: {} + params: {} + entity: + type: repository + entity: + owner: "mindersec" + name: "minder" + expect: "fail" + http: + status: 502 + body: '{"woot": "woot"}' diff --git a/security-baseline/rule-types/github/osps-ac-04.yaml b/security-baseline/rule-types/github/osps-ac-04.yaml new file mode 100644 index 0000000..7c06c24 --- /dev/null +++ b/security-baseline/rule-types/github/osps-ac-04.yaml @@ -0,0 +1,37 @@ +version: v1 +release_phase: alpha +type: rule-type +name: osps-ac-04 +display_name: Prevent permanent branch deletion +short_failure_message: Branch protection allows deletions +severity: + value: info +context: + provider: github +description: Prevents the branch from being deleted +guidance: | + Ensure that the "Allow deletions" setting is disabled for the branch + protection rule. + + Prevent users from deleting matching branches. + + For more information, see [GitHub's + documentation](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-protected-branches/managing-a-branch-protection-rule). +def: + in_entity: repository + rule_schema: {} + ingest: + type: rest + rest: + endpoint: '/repos/{{.Entity.Owner}}/{{.Entity.Name}}/branches/{{ .Entity.DefaultBranch }}/protection' + parse: json + fallback: + - http_code: 404 + body: | + {"http_status": 404, "message": "Not Protected"} + eval: + type: jq + jq: + - ingested: + def: ".allow_deletions.enabled" + constant: false diff --git a/security-baseline/rule-types/github/osps-do-01.yaml b/security-baseline/rule-types/github/osps-do-01.yaml new file mode 100644 index 0000000..b14096c --- /dev/null +++ b/security-baseline/rule-types/github/osps-do-01.yaml @@ -0,0 +1,54 @@ +version: v1 +release_phase: alpha +type: rule-type +name: osps-do-01 +display_name: The project has mechanisms for public discussion +short_failure_message: The project does not publicize mechanisms for public discussion. +severity: + value: info +context: + provider: github +description: | + Projects should encourage open communication and collaboration + within the their community, enabling users to provide feedback and + discuss proposed changes or usage challenges. +guidance: | + Enable "Issues" or "Discussions" via the + [Settings](https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/enabling-features-for-your-repository) + page on GitHub. +def: + in_entity: repository + rule_schema: {} + ingest: + type: git + eval: + type: rego + data_sources: + - name: ghapi + rego: + type: deny-by-default + def: | + package minder + + import future.keywords.every + import future.keywords.if + + default allow := false + + allow if { + repo := minder.datasource.ghapi.repo({ + "owner": input.properties["github/repo_owner"], + "repo": input.properties["github/repo_name"] + }) + + repo.body.has_issues + } + + allow if { + repo := minder.datasource.ghapi.repo({ + "owner": input.properties["github/repo_owner"], + "repo": input.properties["github/repo_name"] + }) + + repo.body.has_discussions + } diff --git a/security-baseline/rule-types/github/osps-do-02.test.yaml b/security-baseline/rule-types/github/osps-do-02.test.yaml new file mode 100644 index 0000000..5bdb54d --- /dev/null +++ b/security-baseline/rule-types/github/osps-do-02.test.yaml @@ -0,0 +1,25 @@ +tests: + - name: "Should find CONTRIBUTING" + def: {} + params: {} + expect: "pass" + git: + repo_base: contributing_file_no_extension + - name: "Should find CONTRIBUTING.md" + def: {} + params: {} + expect: "pass" + git: + repo_base: contributing_file + - name: "Should find CONTRIBUTING folder" + def: {} + params: {} + expect: "pass" + git: + repo_base: contributing_folder + - name: "Should fail if absent" + def: {} + params: {} + expect: "fail" + git: + repo_base: no_data diff --git a/security-baseline/rule-types/github/osps-do-02.testdata/contributing_file/CONTRIBUTING.md b/security-baseline/rule-types/github/osps-do-02.testdata/contributing_file/CONTRIBUTING.md new file mode 100644 index 0000000..3a34bc3 --- /dev/null +++ b/security-baseline/rule-types/github/osps-do-02.testdata/contributing_file/CONTRIBUTING.md @@ -0,0 +1,7 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +... diff --git a/security-baseline/rule-types/github/osps-do-02.testdata/contributing_file_no_extension/CONTRIBUTING b/security-baseline/rule-types/github/osps-do-02.testdata/contributing_file_no_extension/CONTRIBUTING new file mode 100644 index 0000000..3a34bc3 --- /dev/null +++ b/security-baseline/rule-types/github/osps-do-02.testdata/contributing_file_no_extension/CONTRIBUTING @@ -0,0 +1,7 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +... diff --git a/security-baseline/rule-types/github/osps-do-02.testdata/contributing_folder/CONTRIBUTING/myfile b/security-baseline/rule-types/github/osps-do-02.testdata/contributing_folder/CONTRIBUTING/myfile new file mode 100644 index 0000000..3a34bc3 --- /dev/null +++ b/security-baseline/rule-types/github/osps-do-02.testdata/contributing_folder/CONTRIBUTING/myfile @@ -0,0 +1,7 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +... diff --git a/security-baseline/rule-types/github/osps-do-02.testdata/no_data/foo b/security-baseline/rule-types/github/osps-do-02.testdata/no_data/foo new file mode 100644 index 0000000..3d42fcb --- /dev/null +++ b/security-baseline/rule-types/github/osps-do-02.testdata/no_data/foo @@ -0,0 +1 @@ +I'm empty! \ No newline at end of file diff --git a/security-baseline/rule-types/github/osps-do-02.yaml b/security-baseline/rule-types/github/osps-do-02.yaml new file mode 100644 index 0000000..875e452 --- /dev/null +++ b/security-baseline/rule-types/github/osps-do-02.yaml @@ -0,0 +1,48 @@ +version: v1 +release_phase: alpha +type: rule-type +name: osps-do-02 +display_name: Contribution process is explained +short_failure_message: No CONTRIBUTING file or folder was found +severity: + value: info +context: + provider: github +description: | + Ensure that either a CONTRIBUTING file or CONTRIBUTING/ folder is + available. +guidance: | + Source code must be accompanied by a `CONTRIBUTING` file or a + `CONTRIBUTING/` folder at the root of the project source tree. +def: + in_entity: repository + rule_schema: {} + ingest: + type: git + eval: + type: rego + rego: + type: deny-by-default + def: | + package minder + + import future.keywords.every + import future.keywords.if + + default allow := false + + allow if { + files := file.ls_glob("./CONTRIBUTING*") + + some name + content := file.read(files[name]) + "" != content + } + + allow if { + files := file.ls_glob("./CONTRIBUTING/*") + + some name + content := file.read(files[name]) + "" != content + } diff --git a/security-baseline/rule-types/github/osps-le-02.yaml b/security-baseline/rule-types/github/osps-le-02.yaml new file mode 100644 index 0000000..2c0a82d --- /dev/null +++ b/security-baseline/rule-types/github/osps-le-02.yaml @@ -0,0 +1,55 @@ +version: v1 +release_phase: alpha +type: rule-type +name: osps-le-02 +display_name: License meets the OSI or the FSF definition +short_failure_message: License does not meet OSI or FSF definition +severity: + value: info +context: + provider: github +description: | + Ensure that the project’s source code is distributed under a + recognized and legally enforceable open source software license. +guidance: | + Ensure that the project’s source code is distributed under a + recognized and legally enforceable open source software license, + providing clarity on how the code can be used and shared by others. +def: + in_entity: repository + rule_schema: {} + ingest: + type: rest + rest: + endpoint: '/repos/{{.Entity.Owner}}/{{.Entity.Name}}/license' + parse: json + fallback: + - http_code: 404 + body: | + {"http_status": 404, "message": "License details not found} + eval: + type: rego + data_sources: + - name: spdx + rego: + type: constraints + def: | + package minder + + import future.keywords.every + import future.keywords.if + + violations[{"msg": msg}] { + license := input.ingested.license.spdx_id + + resp2 := minder.datasource.spdx.licenses({}) + licenses := resp2.body.licenses + osi := { l.licenseId | l := licenses[_]; l.isOsiApproved } + fsf := { l.licenseId | l := licenses[_]; l.isFsfLibre } + approved_licenses := osi | fsf + + count(approved_licenses) != 0 + license != null + not license in approved_licenses + msg := sprintf("License %s is not OSI/FSF approved", [license]) + } diff --git a/security-baseline/rule-types/github/osps-le-03.test.yaml b/security-baseline/rule-types/github/osps-le-03.test.yaml new file mode 100644 index 0000000..a1de54c --- /dev/null +++ b/security-baseline/rule-types/github/osps-le-03.test.yaml @@ -0,0 +1,31 @@ +tests: + - name: "Should find LICENSE" + def: {} + params: {} + expect: "pass" + git: + repo_base: license_file_no_extension + - name: "Should find LICENSE.md" + def: {} + params: {} + expect: "pass" + git: + repo_base: license_file + - name: "Should find COPYING" + def: {} + params: {} + expect: "pass" + git: + repo_base: copying_file + - name: "Should find LICENSE folder" + def: {} + params: {} + expect: "pass" + git: + repo_base: license_folder + - name: "Should fail if absent" + def: {} + params: {} + expect: "fail" + git: + repo_base: no_data diff --git a/security-baseline/rule-types/github/osps-le-03.testdata/copying_file/COPYING b/security-baseline/rule-types/github/osps-le-03.testdata/copying_file/COPYING new file mode 100644 index 0000000..45706de --- /dev/null +++ b/security-baseline/rule-types/github/osps-le-03.testdata/copying_file/COPYING @@ -0,0 +1,28 @@ + + Note that the only valid version of the GPL as far as this project + is concerned is _this_ particular version of the license (ie v2, not + v2.2 or v3.x or whatever), unless explicitly otherwise stated. + + HOWEVER, in order to allow a migration to GPLv3 if that seems like + a good idea, I also ask that people involved with the project make + their preferences known. In particular, if you trust me to make that + decision, you might note so in your copyright message, ie something + like + + This file is licensed under the GPL v2, or a later version + at the discretion of Linus. + + might avoid issues. But we can also just decide to synchronize and + contact all copyright holders on record if/when the occasion arises. + + Linus Torvalds + +---------------------------------------- + + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. diff --git a/security-baseline/rule-types/github/osps-le-03.testdata/license_file/LICENSE.md b/security-baseline/rule-types/github/osps-le-03.testdata/license_file/LICENSE.md new file mode 100644 index 0000000..3a34bc3 --- /dev/null +++ b/security-baseline/rule-types/github/osps-le-03.testdata/license_file/LICENSE.md @@ -0,0 +1,7 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +... diff --git a/security-baseline/rule-types/github/osps-le-03.testdata/license_file_no_extension/LICENSE b/security-baseline/rule-types/github/osps-le-03.testdata/license_file_no_extension/LICENSE new file mode 100644 index 0000000..3a34bc3 --- /dev/null +++ b/security-baseline/rule-types/github/osps-le-03.testdata/license_file_no_extension/LICENSE @@ -0,0 +1,7 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +... diff --git a/security-baseline/rule-types/github/osps-le-03.testdata/license_folder/LICENSE/myfile b/security-baseline/rule-types/github/osps-le-03.testdata/license_folder/LICENSE/myfile new file mode 100644 index 0000000..3a34bc3 --- /dev/null +++ b/security-baseline/rule-types/github/osps-le-03.testdata/license_folder/LICENSE/myfile @@ -0,0 +1,7 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +... diff --git a/security-baseline/rule-types/github/osps-le-03.testdata/no_data/foo b/security-baseline/rule-types/github/osps-le-03.testdata/no_data/foo new file mode 100644 index 0000000..3d42fcb --- /dev/null +++ b/security-baseline/rule-types/github/osps-le-03.testdata/no_data/foo @@ -0,0 +1 @@ +I'm empty! \ No newline at end of file diff --git a/security-baseline/rule-types/github/osps-le-03.yaml b/security-baseline/rule-types/github/osps-le-03.yaml new file mode 100644 index 0000000..40e89b7 --- /dev/null +++ b/security-baseline/rule-types/github/osps-le-03.yaml @@ -0,0 +1,56 @@ +version: v1 +release_phase: alpha +type: rule-type +name: osps-le-03 +display_name: LICENSE or COPYING files are available available +short_failure_message: No LICENSE or COPYING file found. +severity: + value: info +context: + provider: github +description: | + Ensure that either LICENSE file, COPYING file, or LICENSE/ folder + are available. +guidance: | + Source code must be accompanied by a `LICENSE` or `COPYING` file, or + a `LICENSE/` folder at the root of the project source tree. +def: + in_entity: repository + rule_schema: {} + ingest: + type: git + eval: + type: rego + rego: + type: deny-by-default + def: | + package minder + + import future.keywords.every + import future.keywords.if + + default allow := false + + allow if { + files := file.ls_glob("./LICENSE*") + + some name + content := file.read(files[name]) + "" != content + } + + allow if { + files := file.ls_glob("./COPYING*") + + some name + content := file.read(files[name]) + "" != content + } + + allow if { + files := file.ls_glob("./LICENSE/*") + + some name + content := file.read(files[name]) + "" != content + } diff --git a/security-baseline/rule-types/github/osps-qa-01.yaml b/security-baseline/rule-types/github/osps-qa-01.yaml new file mode 100644 index 0000000..e8837f7 --- /dev/null +++ b/security-baseline/rule-types/github/osps-qa-01.yaml @@ -0,0 +1,40 @@ +version: v1 +release_phase: alpha +type: rule-type +name: osps-qa-01 +display_name: The project's source code is publicly readable +short_failure_message: The project's source code is not publicly readable. +severity: + value: info +context: + provider: github +description: | + Enable users to access and review the project’s source code and + history, promoting transparency and collaboration within the project + community. +guidance: | + Change repository visibility via the + [Settings](https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/managing-repository-settings/setting-repository-visibility#changing-a-repositorys-visibility) + page on GitHub. +def: + in_entity: repository + rule_schema: {} + ingest: + type: git + eval: + type: rego + rego: + type: deny-by-default + def: | + package minder + + import future.keywords.every + import future.keywords.if + + default allow := false + + allow if { + # This rule checks whether the repository is private using + # info tied to the entity itself. + not input.properties["is_private"] + }