{"id":20259980,"url":"https://github.com/influxdata/sedg","last_synced_at":"2026-02-03T12:37:27.887Z","repository":{"id":153736015,"uuid":"410092141","full_name":"influxdata/sedg","owner":"influxdata","description":"Tools for tracking security issues flexibly in version control","archived":false,"fork":false,"pushed_at":"2024-10-22T14:29:00.000Z","size":1125,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-03-24T22:42:06.211Z","etag":null,"topics":["cve-tracking","cve-triage","security","vulnerability-tracking"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/influxdata.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-09-24T20:21:48.000Z","updated_at":"2024-10-22T14:30:41.000Z","dependencies_parsed_at":null,"dependency_job_id":"e969fd0c-9585-4f4d-897a-33ac0afdaf92","html_url":"https://github.com/influxdata/sedg","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/influxdata%2Fsedg","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/influxdata%2Fsedg/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/influxdata%2Fsedg/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/influxdata%2Fsedg/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/influxdata","download_url":"https://codeload.github.com/influxdata/sedg/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248325347,"owners_count":21084908,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cve-tracking","cve-triage","security","vulnerability-tracking"],"created_at":"2024-11-14T11:17:30.908Z","updated_at":"2026-02-03T12:37:22.855Z","avatar_url":"https://github.com/influxdata.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Using\n\n 1. Clone this repo (https://github.com/influxdata/sedg)\n\n 2. Create a venv for it (a venv is recommended to ensure you have the proper\n    versions of dependencies to avoid mismatches and bugs (eg, requests_cache\n    1.0.1 is known to have issues with system python packages from Ubuntu 20.04\n    LTS)):\n\n    ```\n    $ cd /path/to/sedg\n    $ make install-venv\n    ```\n\n    `make install-venv` does the following:\n    ```\n    $ python3 -m venv .venv\n    $ . ./.venv/bin/activate\n    (venv) $ pip install ./requirements.txt\n    ```\n\n 3. Clone CVE data into `/path/to/cve-data`\n\n 4. Optionally create a shell function to setup your environment for using sedg\n    with your CVE data. Eg, in `~/.bashrc`:\n\n    ```\n    cve_env() {\n        sedgpath=\"/path/to/sedg\"\n\n        test \"$VIRTUAL_ENV\" = \"$sedgpath/.venv\" \u0026\u0026 return  # already activated\n\n        echo \"Entering venv for 'sedg' tooling. Use 'deactivate' when done.\"\n        VIRTUAL_ENV_DISABLE_PROMPT=1 . \"$sedgpath/.venv/bin/activate\"\n\n        cd \"/path/to/cve-data\"\n    }\n    ```\n\n 4. Create `~/.config/sedg/sedg.conf` to have:\n\n    ```\n    [Locations]\n    cve-data = /path/to/cve-data\n    ```\n\n    Optionally add any template URLs for GitHub alert template text to the\n    `Behavior` section (comma-separated):\n\n    ```\n    [Behavior]\n    template-urls = https://url1,https://url2\n    ```\n\n    Optionally add OCI product overrides. By default, `cve-report gar|quay`\n    security scan reports will use `oci/gar-\u003cGAR_LOCATION\u003e.\u003cGAR_PROJECT\u003e` or\n    `oci/quay-\u003cQUAY_ORG\u003e` depending on where the security report is coming\n    from. Use `oci-cve-override-where` to override this behavior to always use\n    `oci/gar-\u003cOCI_WHERE\u003e` or `oci/quay-\u003cOCI_WHERE\u003e`. Eg:\n\n    ```\n    [Behavior]\n    oci-cve-override-where = myorg\n    ```\n\n 5. Do stuff\n\n    ```\n    # if added shell function\n    $ cve_env\n    # otherwise\n    $ cd /path/to/cve-data\n    $ VIRTUAL_ENV_DISABLE_PROMPT=1 . /path/to/sedg/.venv/bin/activate\n\n    # create a CVE against a particular package\n    $ cve-add --cve CVE-2020-1234 -p git/foo-org_foo\n\n    # create a placeholder CVE against a particular package\n    $ cve-add -c CVE-2020-NNN1 -p git/foo-org_foo\n\n    # create a new placeholder CVE for this year against a particular package\n    # (creates CVE-\u003cYEAR\u003e-NNN1 if it doesn't exist or incremements the highest\n    # found for the year and adds it (eg, if CVE-\u003cYEAR\u003e-NNN9 exists,\n    # CVE-\u003cYEAR\u003e-NN10 is created))\n    $ cve-add -c next -p git/foo-org_foo\n\n    # create a GitHub placholder CVE from the GitHub url using this year\n    $ cve-add --cve https://github.com/...\n\n    # create a GitHub placeholder CVE with a particular id and package\n    # template\n    $ cve-add -c CVE-2020-GH1234#foo -p git/foo-org_foo --package-template=bar\n\n    $ \u003cwork on CVEs in .../\u003ccve-data\u003e\n    $ cve-check-syntax\n\n    # various reports for humans (add --help to see additional options)\n    $ cve-report summary\t\t\t# summary\n    $ cve-report todo           \t\t# todo list\n\n    # various machine reports\n    $ cve-report influxdb               \t# InfluxDB line protocol\n\n    # GitHub-specific reports\n    $ cve-report gh --org \u003corg\u003e --status=active\n    $ cve-report gh --org \u003corg\u003e --alerts --since YYYY-MM-DD\n\n    # GAR container security reports\n    $ cve-report gar --list \u003cproject\u003e/\u003clocation\u003e\n    $ cve-report gar --list-digest \u003cproject\u003e/\u003clocation\u003e/\u003crepo\u003e/\u003cname\u003e\n    $ cve-report gar --alerts --name \u003cproject\u003e/\u003clocation\u003e/\u003crepo\u003e/\u003cname\u003e@\u003cdigest\u003e\n\n    # quay.io container security reports\n    $ cve-report quay --list \u003corg\u003e\n    $ cve-report quay --list-digest \u003corg\u003e/\u003cname\u003e\n    $ cve-report quay --alerts --name \u003corg\u003e/\u003cname\u003e@\u003cdigest\u003e\n\n    # Docker DSO container security reports\n    $ cve-report dso --list-digest \u003crepo\u003e[:\u003ctag\u003e|@\u003csha256\u003e]\n    $ cve-report dso --alerts --name \u003crepo\u003e[:\u003ctag\u003e|@\u003csha256\u003e]\n\n    # if desired, leave the venv\n    $ deactivate\n    ```\n\n 6. (Optional) If vim user, symlink `extras/vim/syntax/cve.vim` in\n    `~/.vim/syntax` or `~/.config/nvim/syntax`, symlink\n    `extras/vim/indent/cve.vim` in `~/.vim/indent` or `~/.config/nvim/indent`\n    and add to VIMRC:\n    ```\n    \" CVEs\n    augroup cve\n      autocmd!\n      autocmd BufNewFile,BufRead CVE-[0-9][0-9][0-9][0-9]-[0-9GN]* set ft=cve\n      autocmd BufNewFile,BufRead CVE-[0-9][0-9][0-9][0-9]-[0-9GN]* set syntax=cve\n      autocmd BufNewFile,BufRead CVE-[0-9][0-9][0-9][0-9]-[0-9GN]* set autoindent\n      autocmd BufNewFile,BufRead CVE-[0-9][0-9][0-9][0-9]-[0-9GN]* setlocal indentexpr=GetCVEIndent()\n      autocmd BufNewFile,BufRead */path/to/cve-data-dir/templates/* set ft=cve\n      autocmd BufNewFile,BufRead */path/to/cve-data-dir/templates/* set syntax=cve\n      autocmd BufNewFile,BufRead */path/to/cve-data-dir/templates/* set autoindent\n      autocmd BufNewFile,BufRead */path/to/cve-data-dir/templates/* setlocal indentexpr=GetCVEIndent()\n    augroup END\n    ```\n\n# Staying up to date\n\nAssuming you've setup sedg as described in 'Using', can stay up to date with:\n\n    ```\n    $ cd /path/to/sedg\n    $ git checkout main\n    $ git fetch \u0026\u0026 git pull --ff-only\n    $ make install-venv\n    ```\n\n# Uninstalling\n\nSince `sedg` is installed to a venv, uninstall is as simple as:\n\n    ```\n    $ rm -rf /path/to/sedg/.venv\n    ```\n\n# Tests\n\nDevelopment should be done in a venv, see 'Using' above to set one up. Once\nsetup, develop like so:\n\n    $ cd /path/to/sedg\n    $ VIRTUAL_ENV_DISABLE_PROMPT=1 . ./venv/bin/activate\n    $ pip install .[dev]   # install extra development dependencies\n    $\n    \u003cdo stuff\u003e\n    $ deactivate\n\nRun all checks:\n\n    $ make check\n\nRun unittests:\n\n    $ make test\n    ...\n    Ran 116 tests in 0.219s\n    OK\n\nor a single test file:\n\n    # template\n    $ python3 -m unittest tests.test_foo\n    # example\n    $ python3 -m unittest tests.test_cve\n\nor a single test:\n\n    # template\n    $ python3 -m unittest tests.test_foo.TestFoo.test_bar\n    # example\n    $ python3 -m unittest tests.test_cve.TestCve.test___init__valid\n\n\n# CVE File format\n\nThe CVE file format follows RFC5322. In essence:\n\n```\n    Field1: single-line value\n    Field2:\n     multi-line values start on the following line with each line always\n     preceded by a space\n```\n\nThis file format is compliant with various language libraries, such as Python's\nemail.policy.Compat32 (compat since it doesn't conform to Python's shipping\npolicies). Since RFC5322 doesn't support utf-8, utf-8 is not properly supported\nby the file format. The format could be moved to RFC6532 at a future date.\nItems within `[]` are optional.\n\n```\n    Candidate: CVE-\u003cyear\u003e-\u003cnumber\u003e | CVE-\u003cyear\u003e-GH\u003cissue/pull\u003e#\u003cproject\u003e | CVE-\u003cyear\u003e-NNNX\n    OpenDate: YYYY-MM-DD [ HH:MM:SS [ TZ|+-N ] ]\n    CloseDate: YYYY-MM-DD [ HH:MM:SS [ TZ|+-N ] ]\n    PublicDate: YYYY-MM-DD [ HH:MM:SS [ TZ|+-N ] ]\n    CRD: YYYY-MM-DD [ HH:MM:SS [ TZ|+-N ] ]\n    References:\n     \u003curl\u003e\n     \u003curl\u003e (with comment)\n    Description:\n     Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod\n     tempor incididunt ut labore et dolore magna aliqua. Aliquam sem et tortor\n     consequat id porta nibh venenatis.\n     .\n     Tellus orci ac auctor augue mauris augue neque.\n    [GitHub-Advanced-Security:\n     - type: dependabot\n       dependency: \u003c3rd party software\u003e\n       detectedIn: path/to/file\n       advisory: https://github.com/advisories/GHSA-... | unavailable\n       severity: low | moderate | high | critical\n       status: needs-triage | needed | released | removed | dismissed (\u003creason\u003e; \u003cwho\u003e)\n       url: https://github.com/ORG/REPO/security/dependabot/N | unavailable\n     - type: secret\n       secret: \u003cfound secret description\u003e\n       detectedIn: path/to/file\n       status: needs-triage |needed | released | dismissed (\u003creason\u003e; \u003cwho\u003e)\n       url: https://github.com/ORG/REPO/security/secret-scanning/N | unavailable]\n    [Scan-Reports:\n     - type: oci\n       component: \u003caffected software\u003e\n       detectedIn: \u003cOCI image name\u003e\n       advisory: \u003curl for relevant security advisory\u003e | unavailable\n       fixedBy: \u003cversion\u003e | unavailable\n       severity: low | moderate | high | critical\n       status: needs-triage|needed|released|dismissed (\u003creason\u003e; \u003cwho\u003e)\n       url: \u003curl to scan report\u003e | unavailable]\n    Notes:\n     person\u003e One line note\n     person\u003e Multi-line note. Lorem ipsum dolor sit amet, consectetur adipiscing\n      elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n      Aliquam sem et tortor consequat id porta nibh venenatis.\n      .\n      Tellus orci ac auctor augue mauris augue neque.\n    Mitigation: \u003cmitigation\u003e\n    Bugs:\n     \u003curl\u003e\n     \u003curl\u003e\n    Priority: negligible | low | medium | high | critical\n    Discovered-by: First Last [ @\u003cslack\u003e | \u003cgithubUser\u003e ], ...\n    Assigned-to: First Last [ @\u003cslack\u003e | \u003cgithubUser\u003e ]\n    CVSS:\n     \u003cwho\u003e: \u003cCVSS string\u003e [(\u003cscore\u003e [low|medium|high|critical)]\n\n    Patches_\u003csoftware1\u003e:\n     upstream | vendor | distro | other: \u003curl\u003e\n    [CloseDate_\u003csoftware1\u003e: YYYY-MM-DD [ HH:MM:SS [ TZ|+-N ] ]\n    [CloseDate_\u003csoftware1\u003e[/modifier]: YYYY-MM-DD [ HH:MM:SS [ TZ|+-N ] ]\n    [Tags_\u003csoftware1\u003e: \u003ctag1\u003e \u003ctag2\u003e]\n    [Tags_\u003csoftware1\u003e[/\u003cmodifier\u003e]: \u003ctag1\u003e \u003ctag2\u003e]\n    [Priority_\u003csoftware1\u003e: negligible | low | medium | high | critical]\n    [Priority_\u003csoftware1\u003e[/modifier]: negligible | low | medium | high | critical]\n    \u003cproduct1\u003e[/\u003cwhere\u003e]_\u003csoftware1\u003e[/\u003cmodifier\u003e]: \u003cstatus\u003e [(\u003cwhen\u003e)]\n    \u003cproduct2\u003e[/\u003cwhere\u003e]_\u003csoftware1\u003e[/\u003cmodifier\u003e]: \u003cstatus\u003e [(\u003cwhen\u003e)]\n\n    Patches_\u003csoftware2\u003e:\n     upstream | vendor | distro | other: \u003curl\u003e\n    [CloseDate_\u003csoftware2\u003e: YYYY-MM-DD [ HH:MM:SS [ TZ|+-N ] ]\n    [CloseDate_\u003csoftware2\u003e[/modifier]: YYYY-MM-DD [ HH:MM:SS [ TZ|+-N ] ]\n    [Tags_\u003csoftware2\u003e: \u003ctag1\u003e \u003ctag2\u003e]\n    [Tags_\u003csoftware2\u003e[/modifier]: \u003ctag1\u003e \u003ctag2\u003e]\n    [Priority_\u003csoftware2\u003e: negligible | low | medium | high | critical]\n    [Priority_\u003csoftware2\u003e[/\u003cmodifier\u003e]: negligible | low | medium | high | critical]\n    \u003cproduct1\u003e[/\u003cwhere\u003e]_\u003csoftware2\u003e[/\u003cmodifier\u003e]: \u003cstatus\u003e [(\u003cwhen\u003e)]\n    \u003cproduct2\u003e[/\u003cwhere\u003e]_\u003csoftware2\u003e[/\u003cmodifier\u003e]: \u003cstatus\u003e [(\u003cwhen\u003e)]\n\n    ... \u003cadditional software\u003e ...\n```\n\nThe CVE format can be thought of in two sections: the global section and the\nsoftware section. Since CVE identifiers often apply to more than one product,\nsoftware version, etc, the global section is meant to generally apply to all\nsoftware declared in the CVE, whereas the software section lists specifics for\neach software product, version, etc. In this manner, a single CVE file may\ncontain all pertinent information for the CVE on the whole with per-software\nentries showing status for this issue.\n\n\n## Global section\n\nFor each field in the global section:\n * `Candidate` is the CVE identifier for this issue. 3 formats are supported:\n   * `CVE-\u003cyear\u003e-\u003cnumber\u003e` (eg, `CVE-2020-1234`) is used for tracking publicly\n     assigned issues\n   * `CVE-\u003cyear\u003e-NNNX` (eg, `CVE-2020-NNN1` or `CVE-2020-NNN2`) is used for\n     tracking non-public issues. This might be useful for tracking before a\n     public assignment or when tracking a private issue. By convention, when\n     first creating a non-public CVE, choose the current year and increment the\n     value of `X` like so: `CVE-2020-NNN1`, `CVE-2020-NNN2`, ...,\n     `CVE-2020-NNN9`, `CVE-2020-NN10`, ..., `CVE-2020-N999`, `CVE-2020-N1000`,\n     etc)\n   * `CVE-\u003cyear\u003e-GH\u003cissue/pull\u003e#\u003cproject\u003e` (eg, `CVE-2020-GH1234#foo`) is used\n     for tracking a non-public or a not-yet-assigned-CVE identifier issue in\n     GitHub. It encodes both the GitHub repository and issue number/pull\n     request, such that `CVE-2020-GH1234#foo` corresponds with\n     `https://github.com/\u003cyourorg\u003e/foo/issues/1234`. This is particularly\n     useful for organizations with lots of repositories.\n * `OpenDate` is the date the CVE was created\n * `CloseDate` is the date the CVE was closed (nothing 'need-triage', 'needed'\n   or 'pending'). Per-software close date overrides are possible in the\n   software section (below).\n * `PublicDate` is the date that a private CVE was made public\n * `CRD` is the Coordinated Release Date. This can be used for coordinating\n   with other parties to make a CVE public at a specific time\n * `References` contains a list of URLs, one per line, relevant for the CVE\n * `Description` contains the general description for the CVE. It may contain\n   details for a specific piece of software (but typically not details on how\n   other software might use it)\n * `GitHub-Advanced-Security` is optional and may be used to track GitHub\n   dependabot alerts and secret scanning\n * `Scan-Reports` is optional and may be used to track OCI scan reports\n * `Notes` contains information from triagers, developers, etc to give more\n   insight into the vulnerability, particularly how it pertains to individual\n   pieces of software, configuration, build artifacts, etc. It will often\n   contain rationale for entries in the software section (below), but may\n   contain anything that is relevant\n * `Mitigation` contains information on how available mitigations may be\n   applied before patching\n * `Bugs` contains a list of Bug tracker URLs, one per line. These may also be\n   listed in the References section\n * `Priority` contains the priority for fixing the CVE, typically as it pertains\n   to the item described in the `Description` (above). Per-software priority\n   overrides are possible in the software section (below). Supported\n   priorities are:\n   * `negligible`\n   * `low`\n   * `medium`\n   * `high`\n   * `critical`\n * `Discovered-by` is a comma-separated list of names, slack handles, GitHub\n   usernames, etc and used for attribution. `gh-dependabot` and `gh-secret` are\n   used when using `GitHub-Advanced-Security` (above). `quay.io`, `gar` and\n   `docker` are used when using `Scan-Reports` (above) with specific\n   report URLs.\n * `Assigned-to` contains the name, slack handle, GitHub username, etc of the\n   person assigned to this issue\n * `CVSS` contains a list of CVSS scores as assigned by different entities (eg,\n   'nvd', 'redhat', 'ubuntu', etc)\n\n\n## Software section\n\nBy convention, the software section is typically divided into stanzas grouped\nby software. The blank line before each software section is not required but is\nnormally used since it makes the CVE easier to read.\n\nFor each field in the software section:\n * `Patches_\u003csoftwareN\u003e` (eg, `Patches_foo` or `Patches_bar`) contains a list\n   of patch URLs, one per line, with provenance prefixed\n * `CloseDate_\u003csoftwareN\u003e[/modifier]` (eg, `CloseDate_foo` or\n   `CloseDate_bar/v1`) is optional and when specified contains a close date\n   override for `\u003csoftwareN\u003e[/modifier]`\n * `Tags_\u003csoftwareN\u003e[/modifier]` (eg, `Tags_foo` or `Tags_bar/v1`) is optional\n   and when specified contains a comma-separated list of tags. Tags have\n   historically been used to describe a mitigating factor provided by the OS\n   (ie, without user intervention, so different than the `Mitigation` section,\n   above). The `limit-report` tag is used to manipulate reports in different\n   ways. Currently supported tags are:\n   * `apparmor`\n   * `fortify-source`\n   * `hardlink-restriction`\n   * `heap-protector`\n   * `limit-report`\n   * `pie`\n   * `stack-protector`\n   * `symlink-restriction`\n * `Priority_\u003csoftwareN\u003e[/modifier]` (eg, `Priority_foo` or `Priority_bar/v1`)\n   is optional and when specified contains a priority override for\n   `\u003csoftwareN\u003e[/modifier]`\n * `\u003cproduct\u003e` is the supporting technology (eg, a VCS system, build artifact\n   or operating system) or simply `upstream`. Supported `\u003cproduct\u003e`s:\n   * VCS: bzr, cvs, git, hg or svn\n   * build artifacts: appimage, archive, deb, dmg, exe, flatpak, oci, rpm,\n     shell, snap\n   * OS: alpine, android, centos, debian, distroless, flatcar, ios, opensuse,\n     osx, rhel, suse, ubuntu, windows\n * `\u003cwhere\u003e` indicates where the software lives or in the case of technologies\n   with a concept of publishers, who the publisher is. For OS (eg, `ubuntu`,\n   `debian`, `suse`, etc), `\u003cwhere\u003e` indicates the release of the distribution\n   (eg, `ubuntu/focal` indicates 20.04 for Ubuntu where `ubuntu` is the\n   `\u003cproduct\u003e` (distro) and `focal` is the `\u003cwhere\u003e` (distro release)). For\n   `git`, `\u003cwhere\u003e` could indicate the source code hosting provider (eg,\n   `github`, `gitlab`, `launchpad`, etc) or could be used to indicate the\n   organization/user in a hosting provider. Eg, `git/github_foo` indicates that\n   `foo` is somewhere in GitHub whereas `git/bar_foo` could be used to indicate\n   that `foo` is in some provider's organization/user. How `\u003cwhere\u003e` is used is\n   not prescribed and the `\u003cproduct\u003e/\u003cwhere\u003e` combination is not meant to\n   capture everything where the software lives. It is meant to be flexible to\n   allow triagers a means to discern these differences as appropriate for their\n   requirements (eg, perhaps the triager wants to track the status of the\n   `targz` vs `zip`, one might use `archive/targz` and `archive/zip`).\n * `\u003csoftware\u003e` is the name of the software as dictated by the product (eg, the\n   name of the github project, the name of the OCI image, the deb source\n   package, the name of the build artifact, etc)\n * `\u003cmodifier\u003e` is an optional key for grouping collections of packages (eg,\n   'v1' for the project's `v1` branch, `v2`, etc)\n * `\u003cstatus\u003e` indicates the status of fixing the issue for this software (eg,\n   `needs-triage`, `needed`, `pending`, `released`, `not-affected` and\n   `deferred`).\n * `\u003cwhen\u003e` is optional and when specified occurs within parentheses and\n   indicates when the software will be/was fixed when used with the `pending`,\n   `released` or `not-affected` status. When may be a version number (for\n   software with releases), a git hash (for continuous development), a revision\n   number or a date (eg, for an OCI image).\n   * As a special case for `not-affected` and `deferred` the `\u003cwhen\u003e`\n     parenthetical might give a hint as to why (eg `code-not-present` with\n     `not-affected`). Typical hints for 'not-affected':\n     * `code-not-present`: project does not contain the vulnerable code path\n     * `code-not-compiled`: project does not compile the vulnerable code path\n     * `code-not-imported`: project does not import the vulnerable code path\n     * `code-not-used`: project contains/imports/etc the code but does use it\n     * YYYY-MM-DD with deferred: date when entry was put into the deferred\n       status\n   * `not-affected` and `released` are similar but convey different things. Eg\n     `not-affected (1.2.3)` vs `released (1.2.1+patch1)` is saying that `1.2.3`\n     wasn't ever affected (ie, didn't require anything to be done) but\n     `1.2.1+patch1` was affected but is now fixed. This can be useful for\n     software following a release schedule or tracking updates within a Linux\n     distribution.\n\nTypical software stanza examples:\n```\n    # Simple example for some upstream project\n    Patches_foo:\n    upstream_foo: released (1.2)\n\n    # github-hosted example for https://github.com/barproj/bar\n    Patches_bar:\n    git/barprog_bar: needed\n\n    # github-hosted example for https://github.com/barproj/baz with different\n    # branches for different releases for v1/v2 and continuous development on\n    # main\n    Patches_baz:\n     upstream: https://github.com/org/baz/pull/123\n    git/barproj_baz/v1: pending\n    git/barproj_baz/v2: released (2.0.13)\n    git/barproj_baz/main: released (907e560b)\n\n    # OCI images for different registries\n    Patches_norf:\n    Tags_norf: pie\n    oci/dockerhub_norf: needs-triage\n\n    # Linux distribution\n    Patches_corge:\n    upstream_corge: released (1.2)\n    debian/buster_corge: needed\n    ubuntu/xenial_corge: not-affected (code-not-present)\n    ubuntu/bionic_corge: needed\n    ubuntu/focal_corge: not-affected (1.2-3)\n    ubuntu/groovy_corge: not-affected (1.4-1)\n\n    # Snap for different publishers\n    Patches_qux:\n    snap/pub1_qux: released (1234)\n    snap/pub2_qux: not-affected (code-not-compiled)\n```\n\nThe format offers considerable flexibility. For example, to capture upstream vs\nGitLab vs GitHub (where, for example, GitHub and GitLab might be forks of\nupstream), one might use:\n\n```\n    Patches_foo:\n    upstream_foo: needed\n    github/someacct_foo: needed\n    gitlab/otheracct_foo: needed\n```\n\n\n## Ubuntu compatibility\nThe file format was initially defined in Ubuntu and the syntax above is largely\ncompatible with the Ubuntu CVE tracker (UCT) and a longer term goal of this\nproject is to push this tooling to UCT. The above format is more generalized,\nstrict and applicable to other projects. If using this tooling with UCT data,\nthen adjust `~/.config/sedg_ubuntu.conf` to contain:\n\n```\n    [Behavior] compat-ubuntu = yes\n```\n\nWhen specifying compat mode:\n* `CVSS` is single line instead of multiline list. Eg:\n  `CVSS: \u003cCVSS string\u003e [\\[\u003cscore\u003e LOW|MEDIUM|HIGH|CRITICAL\\]]`\n* `\u003cproduct\u003e` may specify Ubuntu releases as a shorthand (eg, `focal` instead\n  of `ubuntu/focal`)\n* patches can specify various other types (eg, in addition to `distro`,\n  `other`, `upstream` and `vendor`, allow `debdiff`, `diff`, `fork`, `merge`,\n  etc)\n* For `Tags...` and `Priority...`, disallow `_` in `\u003csoftware\u003e`, allow `/` in\n  `\u003cmodifier\u003e` and allow `_` as the delimiter for their use of\n  `_\u003crelease\u003e[/\u003cmodifier\u003e]` (eg, `Tags_foo_precise/esm`)\n\nPackage stanzas then become:\n```\n    Patches_\u003csoftware\u003e:\n     upstream | vendor | debdiff | other | debdiff | diff | ...: \u003curl\u003e\n    [Tags_\u003csoftware\u003e: \u003ctag1\u003e \u003ctag2\u003e]\n    [Tags_\u003csoftware\u003e[_\u003cubuntu release\u003e[/\u003cmodifier\u003e]]: \u003ctag1\u003e \u003ctag2\u003e]\n    [Priority_\u003csoftware\u003e: negligible | low | medium | high | critical]\n    [Priority_\u003csoftware\u003e[_\u003cubuntu release\u003e[/\u003cmodifier\u003e]]: negligible | low | medium | high | critical]\n    \u003cubuntu release\u003e_\u003csoftware\u003e[/\u003cmodifier\u003e]: \u003cstatus\u003e [(\u003cwhen\u003e)]\n    \u003cproduct\u003e[/\u003cwhere\u003e]_\u003csoftware\u003e[/\u003cmodifier\u003e]: \u003cstatus\u003e [(\u003cwhen\u003e)]\n```\n\n# Monitoring\n\n`bin/cve-report` can be used to generate human-readable output or line protocol\nsuitable for sending to InfluxDB. Eg:\n\n```\n$ cve-report influxdb\ncvelog,priority=medium,status=needed,product=git id=\"CVE-2020-1234\",software=\"foo\",modifier=\"\" 1633040641675003246\n...\n\n# or pipe into 'influx write' (InfluxData Cloud 2 or InfluxDB 2.x):\n$ cve-report influxdb | influx write --host $URL --org-id $ORGID --bucket-id $BUCKETID --token $TOKEN\n\n# or pipe into 'curl' (omit '\u0026org=$INFLUX_ORG' when not using InfluxData Cloud\n# 2 and InfluxDB 2.x (eg, InfluxData Cloud Dedicated))\n$ export INFLUX_URL=https://...\n$ export INFLUX_BUCKET=...\n$ export INFLUX_ORG=...\n$  export INFLUX_TOKEN=...\n$ cve-report influxdb | curl --header \"Authorization: Bearer $INFLUX_TOKEN\" --header \"Content-Type: text/plain; charset=utf-8\" --header \"Accept: application/json\" --request POST \"$INFLUX_HOST/api/v2/write?bucket=$INFLUX_BUCKET\u0026org=$INFLUX_ORG\" --data-binary @-\n```\n\nFor now, paste this into 'Add Data/Line Protocol' whenever you make relevant\nchanges to the CVE data. A tool will eventually be provided to make this\neasier.\n\nThis line protocol can then be queried in various ways. Since CVE data is not\nexpected to be updated on a daily basis, the following techniques of using two\n`aggregateWindow()` functions, the first with `createEmpty: false` and the\nsecond with `createEmpty: true` (the default) and a `noop`, allows for graphs\nto be filled in for any days that are missing (both in the middle and at the\nend). The start time must necessarily have at least one point to work. If\nsending data in daily, you can skip the `noop()` function and at the end use a\nsingle `aggregateWindow(every: 1d, count)` without a `fill()`.\n\nIt is possible to backfill by checking out a commit and running `cve-report`\nwith `--starttime`. Eg:\n```\n$ cve-report influxdb --starttime $(date --date \"8 days ago\" \"+%s\")\n```\n\nTODO: there is also a telegraf/github plugin that could be investigated.\n\n## Total unique open issues\n```\nfrom(bucket: \"sec-issues\")\n  |\u003e range(start: v.timeRangeStart, stop: v.timeRangeStop)\n  |\u003e filter(fn: (r) =\u003e r[\"_measurement\"] == \"cvelog\" and r[\"_field\"] == \"id\")\n  |\u003e keep(columns: [\"_time\", \"_value\", \"_field\", \"priority\"])\n  |\u003e window(every: 1d)\n  |\u003e unique()\n  |\u003e group(columns: [\"priority\"])\n  // https://community.influxdata.com/t/advice-how-to-carry-forward-data-from-the-previous-day/21895\n  // get all the counts, but don't create any empty data since count() has the\n  // side-effect of turning nulls to 0s\n  |\u003e aggregateWindow(every: 1d, createEmpty: false, fn: count)\n  // create the empty data with nulls intact\n  |\u003e aggregateWindow(every: 1d, fn: (tables=\u003c-, column=\"_value\") =\u003e tables)\n  // convert nulls in \"_value\" to the previous row\n  |\u003e fill(usePrevious: true)\n```\n\nBest viewed as stacked graph with static legend.\n\n## Open issues in affected software\n\nGrouped by software:\n```\nimport \"strings\"\nfrom(bucket: \"sec-issues\")\n  |\u003e range(start: v.timeRangeStart, stop: v.timeRangeStop)\n  |\u003e filter(fn: (r) =\u003e r[\"_measurement\"] == \"cvelog\" and (r[\"_field\"] == \"id\" or r[\"_field\"] == \"software\"))\n  |\u003e pivot(rowKey: [\"_time\"], columnKey: [\"_field\"], valueColumn: \"_value\")\n  |\u003e map(fn: (r) =\u003e ({\n    r with\n    _value: strings.joinStr(arr: [r.software, r.id, r.priority], v: \":\")\n  }))\n  |\u003e drop(columns: [\"id\", \"product\", \"status\"])\n  |\u003e group(columns: [\"software\"])\n  |\u003e window(every: 1d)\n  |\u003e unique()\n  // https://community.influxdata.com/t/advice-how-to-carry-forward-data-from-the-previous-day/21895\n  |\u003e aggregateWindow(every: 1d, createEmpty: false, fn: count)\n  |\u003e aggregateWindow(every: 1d, fn: (tables=\u003c-, column=\"_value\") =\u003e tables)\n  |\u003e fill(usePrevious: true)\n```\n\nBest viewed as stacked graph with static legend.\n\nOld (grouped by priority):\n```\nimport \"strings\"\nfrom(bucket: \"sec-issues\")\n  |\u003e range(start: v.timeRangeStart, stop: v.timeRangeStop)\n  |\u003e filter(fn: (r) =\u003e r[\"_measurement\"] == \"cvelog\" and (r[\"_field\"] == \"id\" or r[\"_field\"] == \"software\"))\n  |\u003e pivot(rowKey: [\"_time\"], columnKey: [\"_field\"], valueColumn: \"_value\")\n  |\u003e map(fn: (r) =\u003e ({\n    r with\n    _value: strings.joinStr(arr: [r.software, r.id, r.priority], v: \":\")\n  }))\n  |\u003e drop(columns: [\"id\", \"product\", \"status\", \"software\"])\n  |\u003e group(columns: [\"priority\"])\n  |\u003e window(every: 1d)\n  |\u003e unique()\n  |\u003e aggregateWindow(every: 1d, fn: count)\n```\n\n### Open issues by software/priority\n```\nimport \"strings\"\nfrom(bucket: \"sec-issues\")\n  |\u003e range(start: v.timeRangeStart, stop: v.timeRangeStop)\n  |\u003e filter(fn: (r) =\u003e r[\"_measurement\"] == \"cvelog\" and (r[\"_field\"] == \"id\" or r[\"_field\"] == \"software\"))\n  |\u003e pivot(rowKey: [\"_time\"], columnKey: [\"_field\"], valueColumn: \"_value\")\n  |\u003e map(fn: (r) =\u003e ({\n    r with\n    tuple: strings.joinStr(arr: [r.software, r.priority], v: \":\"),\n    _value: strings.joinStr(arr: [r.software, r.priority, r.id], v: \":\")\n  }))\n  |\u003e drop(columns: [\"id\", \"product\", \"status\", \"software\"])\n  |\u003e group(columns: [\"tuple\"])\n  |\u003e window(every: 1d)\n  |\u003e unique()\n  // https://community.influxdata.com/t/advice-how-to-carry-forward-data-from-the-previous-day/21895\n  |\u003e aggregateWindow(every: 1d, createEmpty: false, fn: count)\n  |\u003e aggregateWindow(every: 1d, fn: (tables=\u003c-, column=\"_value\") =\u003e tables)\n  |\u003e fill(usePrevious: true)\n```\n\nBest viewed as stacked graph with static legend.\n\n\n### Alert on open issues\n```\nimport \"influxdata/influxdb/secrets\"\nimport \"slack\"\n\n// secret is https://hooks.slack.com/services/X/Y/Z\nwebhook_url = secrets.get(key: \"my-webhook-url\")\nendpoint = slack.endpoint(url: webhook_url)\n\nmapFnCrit = (r) =\u003e ({\n  text: if r._value == 1 then \"${r._value} open critical security issue\" else \"${r._value} open critical security issues\",\n  color: \"danger\",\n  channel: \"\",\n})\ntoSlackCrit = endpoint(mapFn: mapFnCrit)\n\nmapFnHigh = (r) =\u003e ({\n  text: if r._value == 1 then \"${r._value} open high security issue\" else \"${r._value} open high security issues\",\n  color: \"danger\",\n  channel: \"\",\n})\ntoSlackHigh = endpoint(mapFn: mapFnHigh)\n\ncritlvl = 0\nhighlvl = 0\n\n// grab everything from the last 30 days and filter down once so we don't\n// have to keep doing it. We'll filter down more as we go.\ndata = from(bucket: \"jdstrand-sec-stats\")\n  |\u003e range(start: -30d, stop: now())\n  |\u003e filter(fn: (r) =\u003e r[\"_measurement\"] == \"cvelog\" and r[\"_field\"] == \"id\")\n\ngetLatest = (tables=\u003c-) =\u003e {\n  row = tables\n    |\u003e group(columns: [\"_time\"])\n    |\u003e aggregateWindow(every: 1d, createEmpty: false, fn: count)\n    |\u003e group(columns: [\"_time\"], mode: \"except\")\n    |\u003e last()\n    |\u003e limit(n: 1)\n    // we only have 1 row at this point, but fn must be specified\n    |\u003e findRecord(fn: (key) =\u003e true, idx: 0)\n  return row._time\n}\n\nlatest = data\n  |\u003e getLatest()\n\n// check for statuses for the 24 hour period before time of the latest entry\ncheckStatus = (tables=\u003c-, priority, threshold) =\u003e\n  tables\n    |\u003e range(start: -24h, stop: latest)\n    |\u003e filter(fn: (r) =\u003e r[\"priority\"] == priority)\n    |\u003e group(columns: [\"priority\"])\n    |\u003e window(every: 1d)\n    |\u003e unique()\n    |\u003e aggregateWindow(every: 1d, createEmpty: false, fn: count)\n    |\u003e last()\n    |\u003e limit(n: 1)\n    |\u003e filter(fn: (r) =\u003e r[\"_value\"] \u003e threshold)\n\ncrit = data\n  |\u003e checkStatus(priority: \"critical\", threshold: critlvl)\n  |\u003e toSlackCrit()\n  |\u003e yield(name: \"critical\")\n\nhigh = data\n  |\u003e checkStatus(priority: \"high\", threshold: highlvl)\n  |\u003e toSlackHigh()\n  |\u003e yield(name: \"high\")\n```\n\n# GitHub and CVE data\nGitHub does not provide easy mechanisms to subscribe to labels in repos or\nacross the org and also doesn't provide issue label information in their email\nheaders for bug comments. Combined, we must poll GitHub for information to\ndetect new issues or issues that have received updates. The\n`cve-report` tool aims to address this gap. Example usage:\n```\n    # first export a GitHub Personal Access Token that can read issues:\n    $  export GHTOKEN=...\n\n    # Show issues that are referenced in open CVE data that have been\n    # updated since last week\n    $ cve-report gh --updated --org foo --since $(date --date \"7 days ago\" \"+%s\")\n    Updated issues:\n     https://github.com/foo/bar/issues/123\n     https://github.com/foo/baz/issues/234\n\n    # Show list of issues for specific repos in an org with different\n    # labels, but without label 'skipme'\n    $ cve-report gh --missing \\\n        --org foo \\\n        --labels=\"bar:baz\" \\\n        --excluded-labels=\"skipme\" \\\n        --repos=norf,corge,qux\n    Fetching list of repos: ...... done!\n    Fetching list of issues for:\n     foo/corge: .. done!\n     foo/norf: .. done!\n     foo/qux: . done!\n     ...\n    Issues missing from CVE data:\n     https://github.com/foo/corge/issues/345\n     https://github.com/foo/quz/issues/456\n\n    # Show dependabot alerts since last stamp file update (does not filter on\n    # 'active' status)\n    $ cve-report gh --alerts \\\n        --org foo \\\n        --since-stamp /path/to/stamp\n    Collecting repo status: [#########################################] 100%\n    Collecting alerts: [##############################################] 100%\n    Updated vulnerability alerts:\n     bar (https://github.com/foo/bar/security/dependabot):\n      lodash\n      - severity: high\n      - yarn.lock\n      - https://github.com/advisories/GHSA-35jh-r3h4-6jhm\n```\n\n`cve-report gh --updated` also supports `--since-stamp` as a convenience and\nwill set the since time to the `mtime` of the specified file. Eg, to bootstrap\nand then just use the stamp file, use:\n```\n    # first time only\n    $ cve-report gh --updated --org foo --since $(date --date \"7 days ago\" \"+%s\")\n\n    # hereafter\n    $ cve-report gh --updated \\\n        --org foo \\\n        --since-stamp /path/to/stamp\n```\n\nThe `cve-report` script can also be used to show a few things about GitHub\nrepos. Eg, to show archived repos:\n\n```\n$ cve-report gh --org foo --status=archived\nnorf\n```\n\nTo show active repos:\n```\n$ cve-report gh --org foo --status=active\nbar\nbaz\n```\n\nThis can, for example, by used to manage a file of active repos that can be fed\ninto other tools. Eg:\n```\n# for private repos\n$  export GHUSER=...\n$  export GHTOKEN=...\n$ cve-report gh --org foo --status=active | sort -f \u003e foo-repos.txt\n$ cve-report summary --software=\"foo-repos.txt\"\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Finfluxdata%2Fsedg","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Finfluxdata%2Fsedg","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Finfluxdata%2Fsedg/lists"}