kingfisher/crates/kingfisher-rules/data/rules/vercel.yml
Mick Grove bc1093ca4a v1.90.0
2026-03-15 13:59:07 -07:00

338 lines
11 KiB
YAML

rules:
- name: Vercel API Token (legacy 24-char)
id: kingfisher.vercel.1
pattern: |
(?xi)
\b
vercel
(?:.|[\n\r]){0,32}?
\b
(
[A-Z0-9]{24}
)
\b
pattern_requirements:
min_digits: 3
min_uppercase: 1
min_lowercase: 1
confidence: medium
min_entropy: 3.5
validation:
type: Http
content:
request:
method: GET
url: https://api.vercel.com/v2/user
headers:
Authorization: "Bearer {{TOKEN}}"
response_matcher:
- report_response: true
- type: StatusMatch
status: [200]
- type: WordMatch
words:
- '"user":'
- '"email":'
match_all_words: true
revocation:
type: Http
content:
request:
method: DELETE
url: https://api.vercel.com/v3/user/tokens/current
headers:
Authorization: "Bearer {{TOKEN}}"
response_matcher:
- report_response: true
- type: StatusMatch
status: [200, 204]
references:
- https://vercel.com/kb/guide/how-do-i-use-a-vercel-api-access-token
- https://docs.vercel.com/docs/rest-api/reference/welcome#authentication
- https://vercel.com/docs/rest-api/reference/endpoints/authentication/delete-an-authentication-token
examples:
- "vercel-key = DdZV6ZDZW6Vpl7n7JqtrCE5i"
- "vercel_token = zyMBA1qVEMAf4UNNZtCAbg6u"
- "vercel_api_key = MTg0AW799OY1HmyDdn84or3C"
- "vercel_secret = A7n9Xfp3tBz7D0XpOTMWpiOM"
- name: Vercel Personal Access Token (vcp_)
id: kingfisher.vercel.2
pattern: |
(?x)
\b
(
vcp_(?P<body>[A-Za-z0-9_-]{50})(?P<checksum>[A-Za-z0-9]{6})
)
\b
pattern_requirements:
min_digits: 3
checksum:
actual:
template: "{{ checksum }}"
requires_capture: checksum
# Vercel token checksum format: Base62(CRC32(body)) padded to 6 chars.
# The "body" is the 50-char payload portion after the prefix.
expected: "{{ body | crc32 | base62: 6 }}"
skip_if_missing: true
confidence: medium
min_entropy: 3.5
validation:
type: Http
content:
request:
method: GET
url: https://api.vercel.com/v2/user
headers:
Authorization: "Bearer {{TOKEN}}"
response_matcher:
- report_response: true
- type: StatusMatch
status: [200]
- type: WordMatch
words:
- '"user":'
- '"email":'
match_all_words: true
revocation:
type: Http
content:
request:
method: DELETE
url: https://api.vercel.com/v3/user/tokens/current
headers:
Authorization: "Bearer {{TOKEN}}"
response_matcher:
- report_response: true
- type: StatusMatch
status: [200, 204]
references:
- https://vercel.com/kb/guide/how-do-i-use-a-vercel-api-access-token
- https://docs.vercel.com/docs/rest-api/reference/welcome#authentication
- https://vercel.com/changelog/new-token-formats-and-secret-scanning
- https://vercel.com/docs/rest-api/reference/endpoints/authentication/delete-an-authentication-token
examples:
- "vcp_35UYJwYZDigYATKhxJUAhPqRhit2Xe3dtiG60LsUTHeklEXDQ94Jafpu"
- "vercel_access_token=vcp_4mcjwVDwqtVCVGWCcxRjdzGpkGZ3NkwXZv8ktcoQ0EG0dnjpMP1Rzi71"
- name: Vercel Integration Token (vci_)
id: kingfisher.vercel.3
pattern: |
(?x)
\b
(
vci_(?P<body>[A-Za-z0-9_-]{50})(?P<checksum>[A-Za-z0-9]{6})
)
\b
pattern_requirements:
min_digits: 3
checksum:
actual:
template: "{{ checksum }}"
requires_capture: checksum
expected: "{{ body | crc32 | base62: 6 }}"
skip_if_missing: true
confidence: medium
min_entropy: 3.5
validation:
type: Http
content:
request:
method: GET
url: https://api.vercel.com/v2/user
headers:
Authorization: "Bearer {{TOKEN}}"
response_matcher:
- report_response: true
- type: StatusMatch
status: [200]
- type: WordMatch
words:
- '"user":'
match_all_words: false
revocation:
type: Http
content:
request:
method: DELETE
url: https://api.vercel.com/v3/user/tokens/current
headers:
Authorization: "Bearer {{TOKEN}}"
response_matcher:
- report_response: true
- type: StatusMatch
status: [200, 204]
references:
- https://vercel.com/docs/integrations/vercel-api-integrations#create-an-access-token
- https://vercel.com/changelog/new-token-formats-and-secret-scanning
- https://vercel.com/docs/rest-api/reference/endpoints/authentication/delete-an-authentication-token
examples:
- "Vercel Integration Token: vci_35UYJwYZDigYATKhxJUAhPqRhit2Xe3dtiG60LsUTHeklEXDQ94Jafpu"
- name: Vercel App Access Token (vca_)
id: kingfisher.vercel.4
pattern: |
(?x)
\b
(
vca_(?P<body>[A-Za-z0-9_-]{50})(?P<checksum>[A-Za-z0-9]{6})
)
\b
pattern_requirements:
min_digits: 3
checksum:
actual:
template: "{{ checksum }}"
requires_capture: checksum
expected: "{{ body | crc32 | base62: 6 }}"
skip_if_missing: true
confidence: medium
min_entropy: 3.5
validation:
type: Http
content:
request:
method: POST
url: https://api.vercel.com/login/oauth/userinfo
headers:
Authorization: "Bearer {{TOKEN}}"
response_matcher:
- report_response: true
- type: StatusMatch
status: [200]
- type: JsonValid
- type: WordMatch
words:
- '"sub":'
match_all_words: true
revocation:
type: Http
content:
request:
method: POST
url: https://api.vercel.com/login/oauth/token/revoke
headers:
# Requires the Vercel App's client_id and client_secret (Sign in with Vercel).
# Docs use NEXT_PUBLIC_VERCEL_APP_CLIENT_ID; support both.
Authorization: "Basic {{ NEXT_PUBLIC_VERCEL_APP_CLIENT_ID | default: VERCEL_APP_CLIENT_ID | append: ':' | append: VERCEL_APP_CLIENT_SECRET | b64enc }}"
Content-Type: application/x-www-form-urlencoded
body: "token={{ TOKEN | url_encode }}"
response_matcher:
- report_response: true
- type: StatusMatch
status: [200, 204]
references:
- https://vercel.com/docs/sign-in-with-vercel/tokens#access-token
- https://vercel.com/docs/sign-in-with-vercel/authorization-server-api#user-info-endpoint
- https://vercel.com/docs/sign-in-with-vercel/authorization-server-api#revoke-token-endpoint
- https://vercel.com/changelog/new-token-formats-and-secret-scanning
examples:
- "vca_BQuu9ChDu3n6Pfh6YQnCshpoYkWDSFKogLqmBtQ0tC8NAA5rXt340sjz"
- name: Vercel App Refresh Token (vcr_)
id: kingfisher.vercel.5
pattern: |
(?x)
\b
(
vcr_(?P<body>[A-Za-z0-9_-]{50})(?P<checksum>[A-Za-z0-9]{6})
)
\b
pattern_requirements:
min_digits: 3
checksum:
actual:
template: "{{ checksum }}"
requires_capture: checksum
expected: "{{ body | crc32 | base62: 6 }}"
skip_if_missing: true
confidence: medium
min_entropy: 3.5
validation:
type: Http
content:
request:
method: POST
url: https://api.vercel.com/login/oauth/token/introspect
headers:
Content-Type: application/x-www-form-urlencoded
body: "token={{ TOKEN | url_encode }}"
response_matcher:
- report_response: true
- type: StatusMatch
status: [200]
- type: JsonValid
- type: WordMatch
words:
- '"active":true'
match_all_words: true
revocation:
type: Http
content:
request:
method: POST
url: https://api.vercel.com/login/oauth/token/revoke
headers:
Authorization: "Basic {{ NEXT_PUBLIC_VERCEL_APP_CLIENT_ID | default: VERCEL_APP_CLIENT_ID | append: ':' | append: VERCEL_APP_CLIENT_SECRET | b64enc }}"
Content-Type: application/x-www-form-urlencoded
body: "token={{ TOKEN | url_encode }}"
response_matcher:
- report_response: true
- type: StatusMatch
status: [200, 204]
references:
- https://vercel.com/docs/sign-in-with-vercel/tokens#refresh-token
- https://vercel.com/docs/sign-in-with-vercel/authorization-server-api#token-introspection-endpoint
- https://vercel.com/docs/sign-in-with-vercel/authorization-server-api#revoke-token-endpoint
- https://vercel.com/changelog/new-token-formats-and-secret-scanning
examples:
- "vcr_BQuu9ChDu3n6Pfh6YQnCshpoYkWDSFKogLqmBtQ0tC8NAA5rXt340sjz"
- name: Vercel AI Gateway API Key (vck_)
id: kingfisher.vercel.6
pattern: |
(?x)
\b
(
vck_(?P<body>[A-Za-z0-9_-]{50})(?P<checksum>[A-Za-z0-9]{6})
)
\b
pattern_requirements:
min_digits: 3
checksum:
actual:
template: "{{ checksum }}"
requires_capture: checksum
expected: "{{ body | crc32 | base62: 6 }}"
skip_if_missing: true
confidence: medium
min_entropy: 3.5
# GET /v1/models returns the catalog without verifying the token (always 200).
# Use POST /v1/chat/completions with a minimal request instead; invalid/revoked
# keys return 401.
validation:
type: Http
content:
request:
method: POST
url: https://ai-gateway.vercel.sh/v1/chat/completions
headers:
Authorization: "Bearer {{TOKEN}}"
Content-Type: application/json
body: '{"model":"openai/gpt-3.5-turbo","messages":[{"role":"user","content":"x"}],"max_tokens":1}'
response_matcher:
- report_response: true
- type: StatusMatch
status: [200, 403]
- type: JsonValid
- type: WordMatch
words:
- '"choices"'
- 'valid credit card'
match_all_words: false
references:
- https://vercel.com/docs/ai-gateway/authentication-and-byok/authentication
- https://vercel.com/docs/ai-gateway/openai-compat/rest-api
- https://vercel.com/changelog/new-token-formats-and-secret-scanning
examples:
- "vck_2YkmQj1uHqCVNoUx5a9uvRTe81gmAcln5hoRMPWFBU4tulufUf0OzP2K"