forked from mirrors/kingfisher
338 lines
11 KiB
YAML
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"
|