How to filter advisories from GitHub GraphQL by ecosystem

Viewed 438

Links first

I am trying

{
    securityAdvisories(first: 100, ecosystem: nuget) {
    totalCount
    pageInfo {
        endCursor
        startCursor
    }
    nodes {
        description
        summary
        cvss {
        vectorString
        }
        databaseId
        identifiers {
        type
        value
        }
        ghsaId
    }
    }
}

I am getting Field 'securityAdvisories' doesn't accept argument 'ecosystem'" I see the field ecosystem in the https://docs.github.com/en/graphql/reference/objects#securityadvisorypackage

How do I filter by "ecosystem"?

This is possible, because I can do https://github.com/advisories?query=ecosystem%3Anuget How do I get all 113 advisories?

Update

I can filter vulnerabilities belonging to an advisory by ecosystem.

  vulnerabilities(first: 10, ecosystem: NUGET) {
    edges {
      node {
        advisory {
          id
        }
      }
    }

Update 2 I crawl the UI first

page=1;while [ 1 ];do  curl "https://github.com/advisories?page=$count&query=ecosystem%3Anuget" -o $count.txt;count=$((count+1));done
find -maxdepth 1 -name "*.txt" | xargs grep -oE "GHSA-\w{4}-\w{4}-\w{4}" 

After I have the list of GHSA I run this a bit cryptic Python

import requests
import easyargs

template="""
{"query": "query securityAdvisory(ghsaId: \\"GHSA_VALUE\\") {     id     description     ghsaId     permalink     summary     identifiers {       type       value     }     references {       url     }     origin     cwes(first: 10) {       nodes {         name         id         description         cweId       }     }     cvss {       score       vectorString     }     databaseId     publishedAt     notificationsPermalink     updatedAt     severity     withdrawnAt     vulnerabilities(first: 50) {       edges {         node {           severity           updatedAt           vulnerableVersionRange         }       }     }   } } "}
"""

# get token from https://github.com/settings/tokens
# ghsas is a list of GHSAs
@easyargs
def main(token=str, ghsas=str):
    with open(ghsas) as f:
        lines = f.readlines()

    for s in lines:
        s = s.strip()
        data=template.replace("GHSA_VALUE", s, 1)
        r = requests.post(url="https://api.github.com/graphql", data=data, headers={"Authorization":f"bearer {token}"})
        print(r.text)

if __name__ == '__main__':
    main()

I am sure there is a better solution. In the perfect world I would have a single line curl returning a JSON containing 113 Nuget related security avisories. I can't figure out how to query the GraphQL.

1 Answers

For the arguments you can filter by you need to look at documentation for the Query type, not the Object type, i.e. https://docs.github.com/en/graphql/reference/queries#securityadvisoryconnection

Since it doesn't have an entry for ecosystem you can't filter your query results by ecosystem. You can return the ecosystem though (by adding it to your node block), then filter the results by ecosystem once they've been returned to you.

The things you can filter by are stored as redundant data in the graph, which means the backend can avoid visiting the node altogether. Obviously there's a cost to that though, so it's only done for things that people will commonly want to filter by

Related