Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

https://docs.github.com/en/rest?apiVersion=2022-11-28

Info

The set_score function is explained separately. It generates basic metrics.

Code Block
languagepy
def get_sast_issues_score(verbose=False, hed=dict, scope="", org="", repo="", rest_api_endpoint=""):
    """
    Ask GitHub Sec API for data about the CodeQL findings and analyze it
    :param verbose: boolean, flag
    :param hed: dict, auth data
    :param scope: string, part of REST API call
    :param org: string, part of REST API call
    :param repo: string, part of REST API call
    :param rest_api_endpoint: REST API URL
    :return: code_score (int), code_severity_list (DataFrame statistical object)
    """

    import sys

    req = "/code-scanning/alerts"
    url = rest_api_endpoint + "/" + scope + "/" + org + "/" + repo + req
    print("CodeQL Repo URL: " + url, file=sys.stdout)

    response = requests.get(url, headers=hed)

    if response.status_code == 404 or response.status_code == 403:
        # CodeQL support issue for some languages
        status = {"Status": "CodeQL disabled or unsupported language"}
        status_df = pd.DataFrame([status])
        print("CodeQL Status: " + "disabled or not supported for repo", file=sys.stdout)
        return 100, status_df

    parsed = json.loads(response.text)

    if verbose:
        print(json.dumps(parsed, indent=4, sort_keys=True))

    df = pd.DataFrame(parsed)

    if len(df) == 0 and response.status_code == 200:
        status = {"Status": "No findings"}
        status_df = pd.DataFrame([status])
        print("CodeQL Status: " + "no findings for repo", file=sys.stdout)
        return 0, status_df

    if len(df) > 0 and response.status_code == 200:
        print("CodeQL Status: " + "processing findings for repo", file=sys.stdout)

    df = pd.concat([df.drop(['rule'], axis=1), df['rule'].apply(pd.Series)], axis=1)
    df['state'] = df['state'].astype(str)
    df["state"] = df["state"].str.lower()

    if verbose:
        print(df[["number", "name", "state", "severity", "security_severity_level"]])

    # filter out anything that's not "open"
    df_open = df.loc[df['state'] == 'open']
    code_severity_list = df_open["security_severity_level"].value_counts()

    if verbose:
        print("Code Severity List (open)")
        print(code_severity_list)
        print("Code Severity Score (open)")
    code_score = set_score(severity_df=code_severity_list)

    # for better table style
    code_severity_list = code_severity_list.reset_index()
    code_severity_list.columns = ['Risk', 'Code Findings Reported']

    return code_score, code_severity_list

...