mirror of
https://github.com/actions-rust-lang/audit.git
synced 2025-12-27 01:43:48 -05:00
Compare commits
183 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5c5da92c03 | ||
|
|
17d62dc82d | ||
|
|
733aff2088 | ||
|
|
95e05e5d8e | ||
|
|
969643f199 | ||
|
|
7614934373 | ||
|
|
946808f018 | ||
|
|
1fcfd212ac | ||
|
|
d26dd44917 | ||
|
|
645e2942e8 | ||
|
|
965b6233a3 | ||
|
|
9fe902be91 | ||
|
|
94cd57b0d8 | ||
|
|
5330a4041e | ||
|
|
531fba54da | ||
|
|
31383575a9 | ||
|
|
e2ad894c8f | ||
|
|
e4b4ec6817 | ||
|
|
b0169fdb1a | ||
|
|
de48309832 | ||
|
|
f007442857 | ||
|
|
8a4f84d32b | ||
|
|
4a6925b10a | ||
|
|
fae1c3e0b7 | ||
|
|
7fe0328ae6 | ||
|
|
e3466a0192 | ||
|
|
1bedf5d769 | ||
|
|
4ef6a36667 | ||
|
|
9a5a196eb1 | ||
|
|
74871ea769 | ||
|
|
62b30a4d5b | ||
|
|
fa1f058f19 | ||
|
|
1e389b4122 | ||
|
|
a6eeed1940 | ||
|
|
1ca8cd30ac | ||
|
|
0ddaadad09 | ||
|
|
160ac8b6ed | ||
|
|
b8800a8c21 | ||
|
|
1010e1e336 | ||
|
|
72f0fdca3b | ||
|
|
cbff13557b | ||
|
|
08bf11f3ea | ||
|
|
7049db077c | ||
|
|
e8ea165957 | ||
|
|
1926841165 | ||
|
|
08a60eccbb | ||
|
|
16af786dc7 | ||
|
|
ddc21578b3 | ||
|
|
c37ceabcab | ||
|
|
342fdff255 | ||
|
|
b719ea468c | ||
|
|
25528f1e0b | ||
|
|
f4430692fd | ||
|
|
0f2a92891d | ||
|
|
c248204ea6 | ||
|
|
e7db852e4a | ||
|
|
494d723603 | ||
|
|
50559e3f2c | ||
|
|
27b62ea8ec | ||
|
|
e207bcd5c9 | ||
|
|
7d76eb83b1 | ||
|
|
3e63858e0b | ||
|
|
5308f89d29 | ||
|
|
65c5146921 | ||
|
|
6e072ef47a | ||
|
|
8001bc456e | ||
|
|
cbfe81d58f | ||
|
|
89b10d9af6 | ||
|
|
61ccdfe0c5 | ||
|
|
959eb6cc5c | ||
|
|
96eb2dcbe4 | ||
|
|
6943412b48 | ||
|
|
9c29543ade | ||
|
|
dd7ccfd1ab | ||
|
|
70c2c66eb8 | ||
|
|
dfa1ce2e0a | ||
|
|
0c92230a3a | ||
|
|
170a3db2a9 | ||
|
|
656c0afdef | ||
|
|
ff8437a517 | ||
|
|
8d10929ca1 | ||
|
|
e46b8c0d76 | ||
|
|
7b3777bcef | ||
|
|
2ed876b7ce | ||
|
|
69f891a4a1 | ||
|
|
d5ad8c50af | ||
|
|
681351af46 | ||
|
|
d974e8cc12 | ||
|
|
211345ef5d | ||
|
|
001355d0d6 | ||
|
|
f3073563ad | ||
|
|
fe37c9c299 | ||
|
|
d691f93a68 | ||
|
|
be90b61479 | ||
|
|
b4cfb1363f | ||
|
|
6628342aa6 | ||
|
|
c6ef88d85a | ||
|
|
a69554ff2e | ||
|
|
8f7e2d1bd1 | ||
|
|
44e5adf23b | ||
|
|
c696842dcb | ||
|
|
3852156fff | ||
|
|
246a8329c9 | ||
|
|
fad8f7b7af | ||
|
|
799fa87586 | ||
|
|
677ff77e8c | ||
|
|
0a72dd284e | ||
|
|
672ca0693e | ||
|
|
7feab04f1a | ||
|
|
feb1d0bdca | ||
|
|
7e6721cf40 | ||
|
|
660e5d19a6 | ||
|
|
19016ced74 | ||
|
|
4af958f59b | ||
|
|
2dc31fb5ef | ||
|
|
ca4f182e86 | ||
|
|
19c45e9a43 | ||
|
|
22e7edaffe | ||
|
|
c367d7a394 | ||
|
|
d8f9adf642 | ||
|
|
2d2ada1a62 | ||
|
|
73e05e72a7 | ||
|
|
ce625a3fb1 | ||
|
|
0273520156 | ||
|
|
01252679fb | ||
|
|
0ea49bd8cb | ||
|
|
b91ce6d80f | ||
|
|
3f91ab5f83 | ||
|
|
debd2dd3cc | ||
|
|
64f6d2e350 | ||
|
|
87ce76a59f | ||
|
|
f3aaeb714e | ||
|
|
d13447f935 | ||
|
|
bdd908fe01 | ||
|
|
3164457fe4 | ||
|
|
023bfd076f | ||
|
|
5e37004d2c | ||
|
|
06034075ba | ||
|
|
fe269d550e | ||
|
|
b6da146557 | ||
|
|
e661f5f79f | ||
|
|
6c5b44595d | ||
|
|
b4f705152a | ||
|
|
38e4be49ce | ||
|
|
c93937eff7 | ||
|
|
b890df83b8 | ||
|
|
8d89530feb | ||
|
|
7e63792ca8 | ||
|
|
229220ba5c | ||
|
|
0fd4d6ceb9 | ||
|
|
26cc152162 | ||
|
|
839e077185 | ||
|
|
a4304b40f7 | ||
|
|
de4a880f36 | ||
|
|
60557a6189 | ||
|
|
fc8955c20d | ||
|
|
5e0c395775 | ||
|
|
362dc829f3 | ||
|
|
ea1aefd179 | ||
|
|
0d6847edc7 | ||
|
|
058839aa82 | ||
|
|
165ccb4a64 | ||
|
|
623cff7dbe | ||
|
|
2406ebfa1e | ||
|
|
bbbc43cd45 | ||
|
|
44f419d83a | ||
|
|
bf3d0bcece | ||
|
|
cf4c31eba1 | ||
|
|
13b59a5eab | ||
|
|
502e7e5028 | ||
|
|
8ee9b53721 | ||
|
|
2c37721442 | ||
|
|
65677fab72 | ||
|
|
8de7e6de94 | ||
|
|
a1194263c1 | ||
|
|
88907a355a | ||
|
|
568294585d | ||
|
|
ec48ef0b45 | ||
|
|
b8f4057e9c | ||
|
|
92881e10cb | ||
|
|
ece2fac1af | ||
|
|
16d3c44a77 | ||
|
|
3164ded2e4 |
2
.github/workflows/autotag-releases.yml
vendored
2
.github/workflows/autotag-releases.yml
vendored
@@ -15,7 +15,7 @@ jobs:
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Get version from tag
|
||||
id: tag_name
|
||||
run: |
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
repos:
|
||||
- repo: https://github.com/psf/black
|
||||
rev: 22.10.0
|
||||
rev: 24.10.0
|
||||
hooks:
|
||||
- id: black
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v4.3.0
|
||||
rev: v5.0.0
|
||||
hooks:
|
||||
- id: check-ast
|
||||
- id: check-case-conflict
|
||||
@@ -14,19 +14,25 @@ repos:
|
||||
- id: end-of-file-fixer
|
||||
- id: trailing-whitespace
|
||||
- repo: https://github.com/PyCQA/isort
|
||||
rev: 5.10.1
|
||||
rev: 5.13.2
|
||||
# https://github.com/psf/black/blob/main/docs/guides/using_black_with_other_tools.md
|
||||
hooks:
|
||||
- id: isort
|
||||
args: ["--profile=black"]
|
||||
- repo: https://github.com/asottile/pyupgrade
|
||||
rev: v3.2.0
|
||||
rev: v3.19.0
|
||||
hooks:
|
||||
- id: pyupgrade
|
||||
args: ["--py37-plus"]
|
||||
- repo: https://github.com/pre-commit/mirrors-mypy
|
||||
rev: v0.982
|
||||
rev: v1.13.0
|
||||
hooks:
|
||||
- id: mypy
|
||||
additional_dependencies:
|
||||
- types-requests
|
||||
- repo: https://github.com/python-jsonschema/check-jsonschema
|
||||
rev: 0.29.4
|
||||
hooks:
|
||||
- id: check-dependabot
|
||||
- id: check-github-actions
|
||||
- id: check-github-workflows
|
||||
|
||||
69
CHANGELOG.md
69
CHANGELOG.md
@@ -7,6 +7,75 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [1.2.2] - 2024-11-06
|
||||
|
||||
* Update `cargo-audit` to 0.21.0
|
||||
|
||||
## [1.2.1] - 2024-07-31
|
||||
|
||||
* Temporarily remove `--locked` from the install instructions again, since cargo-audit relies on an old version of `time` that is incompatible with Rust 1.80.
|
||||
|
||||
## [1.2.0] - 2024-03-05
|
||||
|
||||
* feat: add --locked to cargo install cargo-audit by @lwshang in #72
|
||||
* Add working directory input to configure where cargo audit executes by @jonasbb in #78
|
||||
|
||||
## [1.1.14] - 2024-02-18
|
||||
|
||||
* Update `cargo-audit` to 0.20.0
|
||||
|
||||
## [1.1.13] - 2024-02-03
|
||||
|
||||
* Update `cargo-audit` to 0.19.0
|
||||
|
||||
## [1.1.12] - 2024-01-20
|
||||
|
||||
* Fix default of `file` argument to make it work again for repositories without `Cargo.lock` checked in.
|
||||
|
||||
## [1.1.11] - 2024-01-18
|
||||
|
||||
* Allow specifying the path to the `Cargo.lock` file, in case it is not in the root of the repository (#55)
|
||||
* Update the example in the readme, to have the correct permissions for private repositories.
|
||||
|
||||
## [1.1.10] - 2023-11-02
|
||||
|
||||
* Fix running the action, by using the correct version of the cache action.
|
||||
|
||||
## [1.1.9] - 2023-11-01
|
||||
|
||||
* Update `cargo-audit` to 0.18.3
|
||||
|
||||
## [1.1.8] - 2023-08-23
|
||||
|
||||
* Handle missing data in advisories better to prevent crashing (#40)
|
||||
|
||||
## [1.1.7] - 2023-05-12
|
||||
|
||||
* Update `cargo-audit` to 0.17.6
|
||||
|
||||
## [1.1.6] - 2023-03-24
|
||||
|
||||
* Update `cargo-audit` to 0.17.5
|
||||
|
||||
## [1.1.5] - 2022-12-22
|
||||
|
||||
* Fix duplicate issues for yanked crates.
|
||||
|
||||
The previous version introduced a bug where existing issues were not properly detected.
|
||||
This only affected issues for yanked crates.
|
||||
Now duplicate issues will no longer be created.
|
||||
|
||||
## [1.1.4] - 2022-12-22
|
||||
|
||||
* Handle warnings without any associated advisory.
|
||||
|
||||
This occurs for yanked crates, where the `advisory` field is `null` in the JSON output.
|
||||
Now a message is shown that the crate and version is yanked.
|
||||
|
||||
## [1.1.3] - 2022-12-05
|
||||
|
||||
* Fix the path to the cargo installation directory to fix caching.
|
||||
|
||||
## [1.1.2] - 2022-11-09
|
||||
|
||||
### Changed
|
||||
|
||||
35
README.md
35
README.md
@@ -1,6 +1,6 @@
|
||||
# Audit Rust dependencies using the RustSec Advisory DB
|
||||
|
||||
Audit your Rust dependencies using [cargo audit] and the [RustSec Advisory DB]. The action creates a summary with all vulnerabilieties. It can create issues for each of the found vulnerabilities.
|
||||
Audit your Rust dependencies using [cargo audit] and the [RustSec Advisory DB]. The action creates a summary with all vulnerabilities. It can create issues for each of the found vulnerabilities.
|
||||
|
||||
Execution Summary:
|
||||
|
||||
@@ -26,15 +26,14 @@ on:
|
||||
# Run manually
|
||||
workflow_dispatch:
|
||||
|
||||
permissions: read-all
|
||||
|
||||
jobs:
|
||||
audit:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
issues: write
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions-rust-lang/audit@v1
|
||||
name: Audit Rust Dependencies
|
||||
with:
|
||||
@@ -45,17 +44,31 @@ jobs:
|
||||
## Inputs
|
||||
|
||||
All inputs are optional.
|
||||
Consider adding a [`audit.toml` configuration file] to your repository for further configurations.
|
||||
Consider adding an [`audit.toml` configuration file] to your repository for further configurations.
|
||||
cargo audit supports multiple warning types, such as unsound code or yanked crates.
|
||||
Configuration is only possible via the `informational_warnings` parameter in the configuration file ([#318](https://github.com/rustsec/rustsec/issues/318)).
|
||||
Setting `denyWarnings` to true will also enable these warnings, but each warning is upgraded to an error.
|
||||
|
||||
| Name | Description | Default |
|
||||
| -------------- | ------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------ |
|
||||
| `TOKEN` | The GitHub access token to allow us to retrieve, create and update issues (automatically set). | `github.token` |
|
||||
| `denyWarnings` | Any warnings generated will be treated as an error and fail the action. | false |
|
||||
| `ignore` | A comma separated list of Rustsec IDs to ignore. | |
|
||||
| `createIssues` | Create/Update issues for each found vulnerability. By default only on `main` or `master` branch. | `github.ref == 'refs/heads/master' \|\| github.ref == 'refs/heads/main'` |
|
||||
| Name | Description | Default |
|
||||
| ------------------ | ------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------ |
|
||||
| `TOKEN` | The GitHub access token to allow us to retrieve, create and update issues (automatically set). | `github.token` |
|
||||
| `denyWarnings` | Any warnings generated will be treated as an error and fail the action. | false |
|
||||
| `file` | The path to the Cargo.lock file to inspect file. | |
|
||||
| `ignore` | A comma separated list of Rustsec IDs to ignore. | |
|
||||
| `createIssues` | Create/Update issues for each found vulnerability. By default only on `main` or `master` branch. | `github.ref == 'refs/heads/master' \|\| github.ref == 'refs/heads/main'` |
|
||||
| `workingDirectory` | Run `cargo audit` from the given working directory | |
|
||||
|
||||
## Dependencies
|
||||
|
||||
The action works best on the GitHub-hosted runners, but can work on self-hosted ones too, provided the necessary dependencies are available.
|
||||
PRs to add support for more environments are welcome.
|
||||
|
||||
* bash
|
||||
* Python 3.9+
|
||||
* requests
|
||||
* Rust stable
|
||||
* cargo
|
||||
* use node actions
|
||||
|
||||
## License
|
||||
|
||||
|
||||
26
action.yml
26
action.yml
@@ -14,6 +14,10 @@ inputs:
|
||||
description: "Any warnings generated will be treated as an error and fail the action"
|
||||
required: false
|
||||
default: "false"
|
||||
file:
|
||||
description: "The path to the Cargo.lock file to inspect"
|
||||
required: false
|
||||
default: ""
|
||||
ignore:
|
||||
description: "A comma separated list of Rustsec IDs to ignore"
|
||||
required: false
|
||||
@@ -22,23 +26,31 @@ inputs:
|
||||
description: Create/Update issues for each found vulnerability.
|
||||
required: false
|
||||
default: "${{ github.ref == 'refs/heads/master' || github.ref == 'refs/heads/main' }}"
|
||||
workingDirectory:
|
||||
description: "Run `cargo audit` from the given working directory"
|
||||
required: false
|
||||
default: ""
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- uses: actions/cache@v3
|
||||
- name: Identify cargo installation directory
|
||||
run: echo "cargohome=${CARGO_HOME:-$HOME/.cargo}" >> $GITHUB_OUTPUT
|
||||
shell: bash
|
||||
id: cargo-home
|
||||
- uses: actions/cache@v4
|
||||
id: cache
|
||||
with:
|
||||
path: |
|
||||
${{ env.CARGO_HOME }}/.cargo/bin/cargo-audit*
|
||||
${{ env.CARGO_HOME }}/.cargo/.crates.toml
|
||||
${{ env.CARGO_HOME }}/.cargo/.crates2.json
|
||||
key: cargo-audit-v0.17.4
|
||||
${{ steps.cargo-home.outputs.cargohome }}/bin/cargo-audit*
|
||||
${{ steps.cargo-home.outputs.cargohome }}/.crates.toml
|
||||
${{ steps.cargo-home.outputs.cargohome }}/.crates2.json
|
||||
key: cargo-audit-v0.21.0
|
||||
|
||||
- name: Install cargo-audit
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
# Update both this version number and the cache key
|
||||
run: cargo install cargo-audit --vers 0.17.4 --no-default-features
|
||||
run: cargo install cargo-audit --vers 0.21.0 --no-default-features
|
||||
shell: bash
|
||||
|
||||
- run: |
|
||||
@@ -48,7 +60,9 @@ runs:
|
||||
env:
|
||||
INPUT_CREATE_ISSUES: ${{ inputs.createIssues }}
|
||||
INPUT_DENY_WARNINGS: ${{ inputs.denyWarnings }}
|
||||
INPUT_FILE: ${{ inputs.file }}
|
||||
INPUT_IGNORE: ${{ inputs.ignore }}
|
||||
INPUT_TOKEN: ${{ inputs.TOKEN }}
|
||||
INPUT_WORKING_DIRECTORY: ${{ inputs.workingDirectory }}
|
||||
PYTHONPATH: ${{ github.action_path }}
|
||||
REPO: ${{ github.repository }}
|
||||
|
||||
237
audit.py
237
audit.py
@@ -11,6 +11,15 @@ import requests
|
||||
# https://github.com/alstr/todo-to-issue-action/blob/25c80e9c4999d107bec208af49974d329da26370/main.py
|
||||
# Originally licensed under MIT license
|
||||
|
||||
# Timeout in seconds for requests methods
|
||||
TIMEOUT = 30
|
||||
|
||||
|
||||
def debug(message: str) -> None:
|
||||
"""Print a debug message to the GitHub Action log"""
|
||||
newline = "\n"
|
||||
print(f"""::debug::{message.replace(newline, " ")}""")
|
||||
|
||||
|
||||
class Issue:
|
||||
"""Basic Issue model for collecting the necessary info to send to GitHub."""
|
||||
@@ -21,7 +30,7 @@ class Issue:
|
||||
labels: List[str],
|
||||
assignees: List[str],
|
||||
body: str,
|
||||
rustsec_id: str,
|
||||
rustsec_id: str, # Should be the start of the title
|
||||
) -> None:
|
||||
self.title = title
|
||||
self.labels = labels
|
||||
@@ -59,62 +68,91 @@ class Entry:
|
||||
self.entry_type = entry_type
|
||||
self.warning_type = warning_type
|
||||
|
||||
def id(self) -> str:
|
||||
"""
|
||||
Return the ID of the entry.
|
||||
"""
|
||||
|
||||
# IMPORTANT: Coordinate this value with the `_get_existing_issues` method below.
|
||||
# Any value returned here must also be present in the filtering there, since the id will be used in the issue title.
|
||||
|
||||
advisory = self.entry.get("advisory", None)
|
||||
if advisory:
|
||||
return advisory["id"]
|
||||
else:
|
||||
return f"Crate {self.entry['package']['name']} {self.entry['package']['version']}"
|
||||
|
||||
def _entry_table(self) -> str:
|
||||
advisory = self.entry["advisory"]
|
||||
advisory = self.entry.get("advisory", None)
|
||||
|
||||
table = []
|
||||
table.append(("Details", ""))
|
||||
table.append(("---", "---"))
|
||||
table.append(("Package", f"`{advisory['package']}`"))
|
||||
table.append(("Version", f"`{self.entry['package']['version']}`"))
|
||||
if self.warning_type is not None:
|
||||
table.append(("Warning", str(self.warning_type)))
|
||||
table.append(("URL", advisory["url"]))
|
||||
table.append(
|
||||
(
|
||||
"Patched Versions",
|
||||
" OR ".join(self.entry["versions"]["patched"])
|
||||
if len(self.entry["versions"]["patched"]) > 0
|
||||
else "n/a",
|
||||
)
|
||||
)
|
||||
if len(self.entry["versions"]["unaffected"]) > 0:
|
||||
if advisory:
|
||||
table = []
|
||||
table.append(("Details", ""))
|
||||
table.append(("---", "---"))
|
||||
table.append(("Package", f"`{advisory['package']}`"))
|
||||
table.append(("Version", f"`{self.entry['package']['version']}`"))
|
||||
if self.warning_type is not None:
|
||||
table.append(("Warning", str(self.warning_type)))
|
||||
table.append(("URL", advisory["url"]))
|
||||
table.append(
|
||||
(
|
||||
"Unaffected Versions",
|
||||
" OR ".join(self.entry["versions"]["unaffected"]),
|
||||
)
|
||||
)
|
||||
if len(advisory["aliases"]) > 0:
|
||||
table.append(
|
||||
(
|
||||
"Aliases",
|
||||
", ".join(
|
||||
Entry._md_autolink_advisory_id(advisory_id)
|
||||
for advisory_id in advisory["aliases"]
|
||||
"Patched Versions",
|
||||
(
|
||||
" OR ".join(self.entry["versions"]["patched"])
|
||||
if len(self.entry["versions"]["patched"]) > 0
|
||||
else "n/a"
|
||||
),
|
||||
)
|
||||
)
|
||||
if len(advisory["related"]) > 0:
|
||||
table.append(
|
||||
(
|
||||
"Related Advisories",
|
||||
", ".join(
|
||||
Entry._md_autolink_advisory_id(advisory_id)
|
||||
for advisory_id in advisory["related"]
|
||||
),
|
||||
if len(self.entry["versions"]["unaffected"]) > 0:
|
||||
table.append(
|
||||
(
|
||||
"Unaffected Versions",
|
||||
" OR ".join(self.entry["versions"]["unaffected"]),
|
||||
)
|
||||
)
|
||||
if len(advisory["aliases"]) > 0:
|
||||
table.append(
|
||||
(
|
||||
"Aliases",
|
||||
", ".join(
|
||||
Entry._md_autolink_advisory_id(advisory_id)
|
||||
for advisory_id in advisory["aliases"]
|
||||
),
|
||||
)
|
||||
)
|
||||
if len(advisory["related"]) > 0:
|
||||
table.append(
|
||||
(
|
||||
"Related Advisories",
|
||||
", ".join(
|
||||
Entry._md_autolink_advisory_id(advisory_id)
|
||||
for advisory_id in advisory["related"]
|
||||
),
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
table_parts = []
|
||||
for row in table:
|
||||
table_parts.append("| ")
|
||||
table_parts.append(row[0])
|
||||
table_parts.append(" | ")
|
||||
table_parts.append(row[1])
|
||||
table_parts.append(" |\n")
|
||||
table_parts = []
|
||||
for row in table:
|
||||
table_parts.append("| ")
|
||||
if row[0] is not None:
|
||||
table_parts.append(row[0])
|
||||
table_parts.append(" | ")
|
||||
if row[1] is not None:
|
||||
table_parts.append(row[1])
|
||||
else:
|
||||
table_parts.append("n/a")
|
||||
table_parts.append(" |\n")
|
||||
|
||||
return "".join(table_parts)
|
||||
return "".join(table_parts)
|
||||
else:
|
||||
# There is no advisory.
|
||||
# This occurs when a yanked version is detected.
|
||||
|
||||
name = self.entry["package"]["name"]
|
||||
return f"""{self.id()} is yanked.
|
||||
Switch to a different version of `{name}` to resolve this issue.
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def _md_autolink_advisory_id(cls, advisory_id: str) -> str:
|
||||
@@ -132,37 +170,64 @@ class Entry:
|
||||
return advisory_id
|
||||
|
||||
def format_as_markdown(self) -> str:
|
||||
advisory = self.entry["advisory"]
|
||||
advisory = self.entry.get("advisory", None)
|
||||
|
||||
entry_table = self._entry_table()
|
||||
# Replace the @ with a ZWJ to avoid triggering markdown autolinks
|
||||
# Otherwise GitHub will interpret the @ as a mention
|
||||
description = advisory["description"].replace("@", "@\u200d")
|
||||
if advisory:
|
||||
entry_table = self._entry_table()
|
||||
# Replace the @ with a ZWJ to avoid triggering markdown autolinks
|
||||
# Otherwise GitHub will interpret the @ as a mention
|
||||
description = advisory["description"].replace("@", "@\u200d")
|
||||
|
||||
md = f"""## {self.entry_type.icon()} {advisory['id']}: {advisory['title']}
|
||||
md = f"""## {self.entry_type.icon()} {advisory['id']}: {advisory['title']}
|
||||
|
||||
{entry_table}
|
||||
|
||||
{description}
|
||||
"""
|
||||
return md
|
||||
return md
|
||||
else:
|
||||
# There is no advisory.
|
||||
# This occurs when a yanked version is detected.
|
||||
|
||||
name = self.entry["package"]["name"]
|
||||
return f"""## {self.entry_type.icon()} {self.id()} is yanked.
|
||||
|
||||
Switch to a different version of `{name}` to resolve this issue.
|
||||
"""
|
||||
|
||||
def format_as_issue(self, labels: List[str], assignees: List[str]) -> Issue:
|
||||
advisory = self.entry["advisory"]
|
||||
advisory = self.entry.get("advisory", None)
|
||||
|
||||
entry_table = self._entry_table()
|
||||
if advisory:
|
||||
entry_table = self._entry_table()
|
||||
|
||||
title = f"{advisory['id']}: {advisory['title']}"
|
||||
body = f"""{entry_table}
|
||||
title = f"{self.id()}: {advisory['title']}"
|
||||
body = f"""{entry_table}
|
||||
|
||||
{advisory['description']}"""
|
||||
return Issue(
|
||||
title=title,
|
||||
labels=labels,
|
||||
assignees=assignees,
|
||||
body=body,
|
||||
rustsec_id=advisory["id"],
|
||||
)
|
||||
return Issue(
|
||||
title=title,
|
||||
labels=labels,
|
||||
assignees=assignees,
|
||||
body=body,
|
||||
rustsec_id=self.id(),
|
||||
)
|
||||
else:
|
||||
# There is no advisory.
|
||||
# This occurs when a yanked version is detected.
|
||||
|
||||
name = self.entry["package"]["name"]
|
||||
title = f"{self.id()} is yanked"
|
||||
body = (
|
||||
f"""Switch to a different version of `{name}` to resolve this issue."""
|
||||
)
|
||||
return Issue(
|
||||
title=title,
|
||||
labels=labels,
|
||||
assignees=assignees,
|
||||
body=body,
|
||||
rustsec_id=self.id(),
|
||||
)
|
||||
|
||||
|
||||
class GitHubClient:
|
||||
@@ -183,6 +248,10 @@ class GitHubClient:
|
||||
# Retrieve the existing repo issues now so we can easily check them later.
|
||||
self._get_existing_issues()
|
||||
|
||||
debug("Existing issues:")
|
||||
for issue in self.existing_issues:
|
||||
debug(f"* {issue['title']}")
|
||||
|
||||
def _get_existing_issues(self, page: int = 1) -> None:
|
||||
"""Populate the existing issues list."""
|
||||
params: Dict[str, Union[str, int]] = {
|
||||
@@ -190,8 +259,9 @@ class GitHubClient:
|
||||
"page": page,
|
||||
"state": "open",
|
||||
}
|
||||
debug(f"Fetching existing issues from GitHub: {page=}")
|
||||
list_issues_request = requests.get(
|
||||
self.issues_url, headers=self.issue_headers, params=params
|
||||
self.issues_url, headers=self.issue_headers, params=params, timeout=TIMEOUT
|
||||
)
|
||||
if list_issues_request.status_code == 200:
|
||||
self.existing_issues.extend(
|
||||
@@ -199,6 +269,7 @@ class GitHubClient:
|
||||
issue
|
||||
for issue in list_issues_request.json()
|
||||
if issue["title"].startswith("RUSTSEC-")
|
||||
or issue["title"].startswith("Crate ")
|
||||
]
|
||||
)
|
||||
links = list_issues_request.links
|
||||
@@ -208,6 +279,7 @@ class GitHubClient:
|
||||
def create_issue(self, issue: Issue) -> Optional[int]:
|
||||
"""Create a dict containing the issue details and send it to GitHub."""
|
||||
title = issue.title
|
||||
debug(f"Creating issue: {title=}")
|
||||
|
||||
# Check if the current issue already exists - if so, skip it.
|
||||
# The below is a simple and imperfect check based on the issue title.
|
||||
@@ -226,9 +298,14 @@ class GitHubClient:
|
||||
existing_issue["url"],
|
||||
headers=self.issue_headers,
|
||||
data=json.dumps(body),
|
||||
timeout=TIMEOUT,
|
||||
)
|
||||
return update_request.status_code
|
||||
|
||||
debug(
|
||||
f"""No existing issue found for "{issue.rustsec_id}". Creating new issue."""
|
||||
)
|
||||
|
||||
new_issue_body = {"title": title, "body": issue.body, "labels": issue.labels}
|
||||
|
||||
# We need to check if any assignees/milestone specified exist, otherwise issue creation will fail.
|
||||
@@ -236,7 +313,9 @@ class GitHubClient:
|
||||
for assignee in issue.assignees:
|
||||
assignee_url = f"{self.repos_url}{self.repo}/assignees/{assignee}"
|
||||
assignee_request = requests.get(
|
||||
url=assignee_url, headers=self.issue_headers
|
||||
url=assignee_url,
|
||||
headers=self.issue_headers,
|
||||
timeout=TIMEOUT,
|
||||
)
|
||||
if assignee_request.status_code == 204:
|
||||
valid_assignees.append(assignee)
|
||||
@@ -248,6 +327,7 @@ class GitHubClient:
|
||||
url=self.issues_url,
|
||||
headers=self.issue_headers,
|
||||
data=json.dumps(new_issue_body),
|
||||
timeout=TIMEOUT,
|
||||
)
|
||||
|
||||
return new_issue_request.status_code
|
||||
@@ -255,7 +335,10 @@ class GitHubClient:
|
||||
def close_issue(self, issue: Dict[str, Any]) -> int:
|
||||
body = {"state": "closed"}
|
||||
close_request = requests.patch(
|
||||
issue["url"], headers=self.issue_headers, data=json.dumps(body)
|
||||
issue["url"],
|
||||
headers=self.issue_headers,
|
||||
data=json.dumps(body),
|
||||
timeout=TIMEOUT,
|
||||
)
|
||||
return close_request.status_code
|
||||
|
||||
@@ -317,12 +400,26 @@ def run() -> None:
|
||||
extra_args.append("--deny")
|
||||
extra_args.append("warnings")
|
||||
|
||||
if os.environ["INPUT_FILE"] != "":
|
||||
extra_args.append("--file")
|
||||
extra_args.append(os.environ["INPUT_FILE"])
|
||||
|
||||
working_directory = None
|
||||
if os.environ["INPUT_WORKING_DIRECTORY"] != "":
|
||||
working_directory = os.environ["INPUT_WORKING_DIRECTORY"]
|
||||
|
||||
audit_cmd = ["cargo", "audit", "--json"] + extra_args + ignore_args
|
||||
debug(f"Running command: {audit_cmd}")
|
||||
completed = subprocess.run(
|
||||
["cargo", "audit", "--json"] + extra_args + ignore_args,
|
||||
audit_cmd,
|
||||
cwd=working_directory,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
check=False,
|
||||
)
|
||||
debug(f"Command return code: {completed.returncode}")
|
||||
debug(f"Command output: {completed.stdout}")
|
||||
debug(f"Command error: {completed.stderr}")
|
||||
data = json.loads(completed.stdout)
|
||||
|
||||
summary = create_summary(data)
|
||||
@@ -356,7 +453,7 @@ def run() -> None:
|
||||
num_existing_issues = len(gh_client.existing_issues)
|
||||
for entry in entries:
|
||||
for ex_issue in gh_client.existing_issues:
|
||||
if ex_issue["title"].startswith(entry.entry["advisory"]["id"]):
|
||||
if ex_issue["title"].startswith(entry.id()):
|
||||
gh_client.existing_issues.remove(ex_issue)
|
||||
num_old_issues = len(gh_client.existing_issues)
|
||||
print(
|
||||
|
||||
Reference in New Issue
Block a user