secret-formats
Source: crates/lvcs/src/secrets/formats.rs.
/// The characters a token's body may hold, all ASCII.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum Body {
/// `A-Z a-z 0-9`.
Alnum,
/// `A-Z 0-9`.
UpperAlnum,
/// `0-9 a-f`.
LowerHex,
/// `A-Z a-z 0-9 _`.
AlnumUnderscore,
/// `A-Z a-z 0-9 -`.
AlnumDash,
/// `A-Z a-z 0-9 _ -` (base64url).
Base64Url,
/// `A-Z a-z 0-9 /`.
AlnumSlash,
}
/// How many code points a token's body holds.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum Len {
Exactly(usize),
AtLeast(usize),
}
/// How a known token format is recognized. A token starts only where the
/// code point before it is not an ASCII letter, digit, `_`, or `-`, so a
/// prefix inside a longer word (`task_live_`) is not a token.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum Shape {
/// One of `prefixes`, then the longest run of `body` characters, whose
/// length must fit `len`, followed by no ASCII letter or digit. With
/// `mixed`, the run must also hold an uppercase letter, a lowercase
/// letter, and a digit, as a random token does and a word does not.
Prefixed {
prefixes: &'static [&'static str],
body: Body,
len: Len,
mixed: bool,
},
/// A JSON Web Token: three base64url segments of at least
/// [`JWT_SEGMENT_MIN`] code points joined by `.`, the first two
/// starting `eyJ` (a base64url-encoded JSON object).
Jwt,
}
/// A known token format; `rule` names it in `SecretHit::rule` and the
/// API's `SecretData.rule`.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
struct TokenFormat {
rule: &'static str,
shape: Shape,
}
/// The rule of a PEM private key: `-----BEGIN <label>-----` whose label
/// ends in `PRIVATE KEY` or `PRIVATE KEY BLOCK`, through the first
/// `-----END ` after it when that closes the same label, with at least
/// [`PEM_BODY_MIN`] code points between them. A header with no body, as
/// code that parses PEM names it, is not a hit; a body written without
/// its footer is left to the high-entropy heuristic, line by line. A PEM
/// block with any other label (`CERTIFICATE`, `PUBLIC KEY`) is public
/// data: the heuristic skips it.
const PEM_PRIVATE_KEY_RULE: &str = "private-key";
/// Fewest code points between a PEM private key's header and footer.
const PEM_BODY_MIN: usize = 64;
/// Fewest code points in each segment of a JSON Web Token.
const JWT_SEGMENT_MIN: usize = 10;
/// The known token formats, tried in this order at each position: the
/// first that matches names the hit, so a format comes before a more
/// general one sharing its prefix (`anthropic-key` before `sk-key`).
const TOKEN_FORMATS: &[TokenFormat] = &[
TokenFormat {
rule: "aws-access-key-id",
shape: Shape::Prefixed {
prefixes: &["AKIA", "ASIA", "ABIA", "ACCA"],
body: Body::UpperAlnum,
len: Len::Exactly(16),
mixed: false,
},
},
TokenFormat {
rule: "github-token",
shape: Shape::Prefixed {
prefixes: &["ghp_", "gho_", "ghu_", "ghs_", "ghr_"],
body: Body::Alnum,
len: Len::AtLeast(36),
mixed: false,
},
},
TokenFormat {
rule: "github-pat",
shape: Shape::Prefixed {
prefixes: &["github_pat_"],
body: Body::AlnumUnderscore,
len: Len::AtLeast(40),
mixed: false,
},
},
TokenFormat {
rule: "gitlab-token",
shape: Shape::Prefixed {
prefixes: &["glpat-"],
body: Body::Base64Url,
len: Len::AtLeast(20),
mixed: false,
},
},
TokenFormat {
rule: "slack-token",
shape: Shape::Prefixed {
prefixes: &["xoxa-", "xoxb-", "xoxe-", "xoxp-", "xoxr-", "xoxs-"],
body: Body::AlnumDash,
len: Len::AtLeast(10),
mixed: false,
},
},
TokenFormat {
rule: "slack-webhook",
shape: Shape::Prefixed {
prefixes: &["https://hooks.slack.com/services/"],
body: Body::AlnumSlash,
len: Len::AtLeast(20),
mixed: false,
},
},
TokenFormat {
rule: "stripe-key",
shape: Shape::Prefixed {
prefixes: &["sk_live_", "rk_live_", "sk_test_", "rk_test_"],
body: Body::Alnum,
len: Len::AtLeast(16),
mixed: false,
},
},
TokenFormat {
rule: "anthropic-key",
shape: Shape::Prefixed {
prefixes: &["sk-ant-"],
body: Body::Base64Url,
len: Len::AtLeast(32),
mixed: true,
},
},
TokenFormat {
rule: "sk-key",
shape: Shape::Prefixed {
prefixes: &["sk-"],
body: Body::Base64Url,
len: Len::AtLeast(32),
mixed: true,
},
},
TokenFormat {
rule: "google-api-key",
shape: Shape::Prefixed {
prefixes: &["AIza"],
body: Body::Base64Url,
len: Len::Exactly(35),
mixed: false,
},
},
TokenFormat {
rule: "huggingface-token",
shape: Shape::Prefixed {
prefixes: &["hf_"],
body: Body::Alnum,
len: Len::AtLeast(34),
mixed: false,
},
},
TokenFormat {
rule: "npm-token",
shape: Shape::Prefixed {
prefixes: &["npm_"],
body: Body::Alnum,
len: Len::AtLeast(36),
mixed: false,
},
},
TokenFormat {
rule: "pypi-token",
shape: Shape::Prefixed {
prefixes: &["pypi-AgEIcHlwaS5vcmc"],
body: Body::Base64Url,
len: Len::AtLeast(50),
mixed: false,
},
},
TokenFormat {
rule: "digitalocean-token",
shape: Shape::Prefixed {
prefixes: &["dop_v1_", "doo_v1_", "dor_v1_"],
body: Body::LowerHex,
len: Len::Exactly(64),
mixed: false,
},
},
TokenFormat {
rule: "age-secret-key",
shape: Shape::Prefixed {
prefixes: &["AGE-SECRET-KEY-1"],
body: Body::UpperAlnum,
len: Len::Exactly(58),
mixed: false,
},
},
TokenFormat {
rule: "jwt",
shape: Shape::Jwt,
},
];