Replace plain String with SecretString for GitHub token (#509)

This commit changed the type of `lychee-lib::ClientBuilder::github_token` from
`String` to `secrecy::SecretString` to fortify the secret management within our
program.

Note that this won't affect TOML configuration of `lychee-bin` because
`serde::Deserialize` is still implemented for `SecretString`.
This commit is contained in:
Lucius Hu 2022-02-13 07:53:46 -05:00 committed by GitHub
parent 47df7780fe
commit 6d56c6b55c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 40 additions and 5 deletions

18
Cargo.lock generated
View file

@ -1818,6 +1818,7 @@ dependencies = [
"regex",
"reqwest",
"ring",
"secrecy",
"serde",
"serde_json",
"structopt",
@ -1860,6 +1861,7 @@ dependencies = [
"regex",
"reqwest",
"ring",
"secrecy",
"serde",
"shellexpand",
"tempfile",
@ -2852,6 +2854,16 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
name = "secrecy"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9bd1c54ea06cfd2f6b63219704de0b9b4f72dcc2b8fdef820be6cd799780e91e"
dependencies = [
"serde",
"zeroize",
]
[[package]]
name = "security-framework"
version = "2.4.2"
@ -3881,3 +3893,9 @@ dependencies = [
"serde_json",
"tokio",
]
[[package]]
name = "zeroize"
version = "1.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c88870063c39ee00ec285a2f8d6a966e5b6fb2becc4e8dac77ed0d370ed6006"

View file

@ -45,6 +45,7 @@ once_cell = "1.9.0"
dashmap = { version = "5.1.0", features = ["serde"] }
csv = "1.1.6"
humantime = "2.1.0"
secrecy = { version = "0.8.0", features = ["serde"] }
[dev-dependencies]
assert_cmd = "2.0.4"

View file

@ -5,6 +5,7 @@ use const_format::{concatcp, formatcp};
use lychee_lib::{
Base, Input, DEFAULT_MAX_REDIRECTS, DEFAULT_MAX_RETRIES, DEFAULT_TIMEOUT, DEFAULT_USER_AGENT,
};
use secrecy::{ExposeSecret, SecretString};
use serde::Deserialize;
use structopt::StructOpt;
@ -284,7 +285,7 @@ pub(crate) struct Config {
/// GitHub API token to use when checking github.com links, to avoid rate limiting
#[structopt(long, env = "GITHUB_TOKEN", hide_env_values = true)]
#[serde(default)]
pub(crate) github_token: Option<String>,
pub(crate) github_token: Option<SecretString>,
/// Skip missing input files (default is to error if they don't exist)
#[structopt(long)]
@ -364,11 +365,24 @@ impl Config {
method: DEFAULT_METHOD;
base: None;
basic_auth: None;
github_token: None;
skip_missing: false;
glob_ignore_case: false;
output: None;
require_https: false;
}
if self
.github_token
.as_ref()
.map(ExposeSecret::expose_secret)
.is_none()
&& toml
.github_token
.as_ref()
.map(ExposeSecret::expose_secret)
.is_some()
{
self.github_token = toml.github_token;
}
}
}

View file

@ -51,6 +51,7 @@ lazy_static = "1.4.0"
html5ever = "0.25.1"
html5gum = "0.4.0"
octocrab = "0.15.4"
secrecy = "0.8.0"
[dependencies.par-stream]
version = "0.10.0"

View file

@ -23,6 +23,7 @@ use http::{
use octocrab::Octocrab;
use regex::RegexSet;
use reqwest::header;
use secrecy::{ExposeSecret, SecretString};
use tokio::time::sleep;
use typed_builder::TypedBuilder;
@ -65,7 +66,7 @@ pub struct ClientBuilder {
///
/// As of Feb 2022, it's 60 per hour without GitHub token v.s.
/// 5000 per hour with token.
github_token: Option<String>,
github_token: Option<SecretString>,
/// Links matching this set of regular expressions are **always** checked.
///
/// This has higher precedence over [`ClientBuilder::excludes`], **but**
@ -240,9 +241,9 @@ impl ClientBuilder {
})
.build()?;
let github_client = match github_token {
let github_client = match github_token.as_ref().map(ExposeSecret::expose_secret) {
Some(token) if !token.is_empty() => {
Some(Octocrab::builder().personal_token(token).build()?)
Some(Octocrab::builder().personal_token(token.clone()).build()?)
}
_ => None,
};