Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add check for OSPS-DO-03: repo contains end-user documentation #232

Merged
merged 8 commits into from
Jan 28, 2025
3 changes: 3 additions & 0 deletions security-baseline/profiles/security-baseline-level-1.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ repository:
# OSPS-BR-09: GitHub hosted releases have this, check for links in release text?

# OSPS-DO-03: Ensure user guides for all basic functionality
- name: osps-do-03
type: osps-do-03
def: {}
# OSPS-DO-05: Project documentation has a mechanism for reporting defects

# OSPS-GV-02: Projects has public discussion mechanisms
Expand Down
109 changes: 109 additions & 0 deletions security-baseline/rule-types/github/osps-do-03.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
---
version: v1
release_phase: alpha
type: rule-type
name: osps-do-03
display_name: OSPS-DO-03 The project documentation MUST provide user guides for all basic functionality
short_failure_message: No user guides or project documentation found
severity:
value: low
context:
provider: github
description: |
Verifies that the project documentation provides a user guide.

This rule attempts to locate user guides from several project documentation sources.

Currently, this rule checks the following:

* The GitHub repository's public link
* A `docs` directory in the default branch of the repository with .md, .rst, .html or .txt files
* A `documentation` entry in SECURITY-INSIGHTS.yaml
* A `README.md` file containing preformatted text (triple-backtick) or the headings
"usage" or "getting started"

For more information, see [OpenSSF Security Baseline](https://baseline.openssf.org/#osps-do-03).
guidance: |
Publish documentation in one of the following well-known locations:

* Set the repository homepage to a documentation URL.
* Add a SECURITY-INSIGHTS.yaml file with a `documentation` entry
* Create a `docs` directory in the default branch of the repository
* Add a "usage" or "getting started" section to `README.md`
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 rego.v1

default allow := false

repo := sprintf("%s/%s", [])

allow if {
# Check the SECURITY-INSIGHTS.yaml file
file.exists("SECURITY-INSIGHTS.yaml")
si_data := yaml.unmarshal(file.read("SECURITY-INSIGHTS.yaml"))
count(si_data.documentation) > 0
}

# TODO: these should trigger a remediation to put them in
# SECURITY-INSIGHTS.yaml, but also still pass the check(?)

allow if {
# Check the GitHub homepage link
out = minder.datasource.ghapi.repo_config({
"owner": input.properties["github/repo_owner"],
"repo": input.properties["github/repo_name"]
})
out.body.homepage != ""
}

allow if {
# Check the docs directory
mdDocs := file.ls_glob("docs/*.md")
rstDocs := file.ls_glob("docs/*.rst")
htmlDocs := file.ls_glob("docs/*.html")
txtDocs := file.ls_glob("docs/*.txt")
count(mdDocs) + count(rstDocs) + count(htmlDocs) + count(txtDocs) > 0
}

readme := file.read("README.md")
allow if {
# Check the README.md file for preformatted text after the first line
regex.match("\n *```", readme)
}
allow if {
regex.match("\n#+ (?i:Usage|Getting Started)", readme)
}

# Remediation is a work in progress -- ideally, we could read which location(s)
# contained the documentation, and automatically update SECURITY-INSIGHTS.yaml
# with any missing documentation locations.
# remediate:
# type: pull_request
# pull_request:
# title: "Add documentation to security-insights.yaml"
# body: |
# This is a Minder automated pull request.

# This pull request links the discovered documentation in the security-insights.yaml file.
# method: minder.yq.evaluate
# params:
# # TODO: need to be able to feed output from eval into remediate
# expression: |
# .documentation = [ "./README.md" ]
# patterns:
# # TODO: need to be able to create files as well as match existing files
# - pattern: "SECURITY-INSIGHTS.yaml"
# type: glob