Authored Devin / Cognition rule

This commit is contained in:
Mick Grove 2026-05-27 17:55:32 -07:00
commit 0552d67df7
7 changed files with 214 additions and 2 deletions

1
.gitignore vendored
View file

@ -239,5 +239,6 @@ rust-project.json
# MkDocs build output # MkDocs build output
docs-site/site/ docs-site/site/
.codegraph/
# Created by https://www.toptal.com/developers/gitignore/api/python # Created by https://www.toptal.com/developers/gitignore/api/python
# Edit at https://www.toptal.com/developers/gitignore?templates=python # Edit at https://www.toptal.com/developers/gitignore?templates=python

View file

@ -2,6 +2,9 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
## [v1.102.0]
- Added 3 detection and validation rules for Cognition Devin API credentials: `kingfisher.devin.1` (legacy personal keys, `apk_user_` prefix), `kingfisher.devin.2` (legacy service keys, `apk_` prefix), and `kingfisher.devin.3` (v3 service-user tokens, `cog_` prefix / RFC 4648 base32). Live validation uses `GET /v1/sessions` for `apk_*` keys and `GET /v3/self` for `cog_` tokens.
## [v1.101.0] ## [v1.101.0]
- Fixed asymmetric JWT validation panics by using a single `jsonwebtoken` crypto backend and adding RS256 regression coverage. Thanks @AgentEnder. [#386](https://github.com/mongodb/kingfisher/pull/386) - Fixed asymmetric JWT validation panics by using a single `jsonwebtoken` crypto backend and adding RS256 regression coverage. Thanks @AgentEnder. [#386](https://github.com/mongodb/kingfisher/pull/386)
- Validator panics now fail that validation result instead of crashing the scan, with panic payloads kept out of cached and user-visible validation responses. Thanks @AgentEnder. [#387](https://github.com/mongodb/kingfisher/pull/387) - Validator panics now fail that validation result instead of crashing the scan, with panic payloads kept out of cached and user-visible validation responses. Thanks @AgentEnder. [#387](https://github.com/mongodb/kingfisher/pull/387)

2
Cargo.lock generated
View file

@ -4958,7 +4958,7 @@ dependencies = [
[[package]] [[package]]
name = "kingfisher" name = "kingfisher"
version = "1.101.0" version = "1.102.0"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"asar", "asar",

View file

@ -48,7 +48,7 @@ http = "1.4"
[package] [package]
name = "kingfisher" name = "kingfisher"
version = "1.101.0" version = "1.102.0"
description = "MongoDB's blazingly fast and accurate secret scanning and validation tool" description = "MongoDB's blazingly fast and accurate secret scanning and validation tool"
edition.workspace = true edition.workspace = true
rust-version.workspace = true rust-version.workspace = true

View file

@ -0,0 +1,153 @@
rules:
- name: Cognition Devin Personal API Key
id: kingfisher.devin.1
# Personal/user API keys are emitted as:
# apk_user_<base64( "user-<32hex>_org-<32hex>:<32hex>" )>
# The encoded body is ~144 base64 chars and may end with `=` padding.
pattern: |
(?x)
\b
(
apk_user_[A-Za-z0-9+/]{120,180}={0,2}
)
pattern_requirements:
min_digits: 2
min_lowercase: 1
min_uppercase: 1
ignore_if_contains:
- "YOUR_"
- "REPLACE_"
- "EXAMPLE"
min_entropy: 4.0
confidence: medium
examples:
- apk_user_dXNlci0yMDc5ZjllYTUyZDA0OWE0OTVlOWUwNDc2OTJiNWZhYl9vcmctZmE4NzllMzdjYWRmNGI2YmJmMmE3YWYzMTgxZGVjMTM6MjUwZjRhNzc2ZDEyNGVlMTk0NDk5OGNhNmRmNjBiY2I=
- "DEVIN_API_KEY=apk_user_dXNlci0yMDc5ZjllYTUyZDA0OWE0OTVlOWUwNDc2OTJiNWZhYl9vcmctZmE4NzllMzdjYWRmNGI2YmJmMmE3YWYzMTgxZGVjMTM6YTYzNWU0MTA3M2VkNDU3OGFmZDFhMjAxZDhkMjNkODg="
- "Authorization: Bearer apk_user_dXNlci0yMDc5ZjllYTUyZDA0OWE0OTVlOWUwNDc2OTJiNWZhYl9vcmctZmE4NzllMzdjYWRmNGI2YmJmMmE3YWYzMTgxZGVjMTM6NDMxYWFhYjBmN2VmNGRmMTlmZjkwNTBiNDhlYmE3NjM="
references:
- https://docs.devin.ai/api-reference/overview
- https://docs.devin.ai/api-reference/v1/sessions
validation:
type: Http
content:
request:
method: GET
url: https://api.devin.ai/v1/sessions?limit=1
headers:
Authorization: "Bearer {{ TOKEN }}"
Accept: application/json
response_matcher:
- report_response: true
- type: StatusMatch
status: [200]
- type: JsonValid
- type: WordMatch
words:
- '"sessions"'
match_all_words: true
# Revocation: no documented self-service revocation endpoint exists for
# legacy apk_user_* keys; users must rotate them via the Devin web UI.
- name: Cognition Devin Service API Key
id: kingfisher.devin.2
# Legacy service API keys are emitted as:
# apk_<base64( "org-<32hex>:<32hex>" )>
# The encoded body is ~92 base64 chars. The base64 charset contains no
# underscore, so apk_user_* tokens (which contain an underscore after
# "user") cannot be matched by this rule.
pattern: |
(?x)
\b
(
apk_[A-Za-z0-9+/]{80,100}={0,2}
)
\b
pattern_requirements:
min_digits: 2
min_lowercase: 1
min_uppercase: 1
ignore_if_contains:
- "apk_user_"
- "YOUR_"
- "REPLACE_"
- "EXAMPLE"
min_entropy: 4.0
confidence: medium
examples:
- apk_b3JnLWZhODc5ZTM3Y2FkZjRiNmJiZjJhN2FmMzE4MWRlYzEzOjM0MTU3ZWU4NTZiMjRkMjI5MDYwNzAxOGJmMGEyYzU0
- "DEVIN_API_KEY=apk_b3JnLWZhODc5ZTM3Y2FkZjRiNmJiZjJhN2FmMzE4MWRlYzEzOmFjMWE2YWEwZjhjYzQ0OGNiY2Q5ZDJlOTI5MGEyN2Jh"
- "Authorization: Bearer apk_b3JnLWZhODc5ZTM3Y2FkZjRiNmJiZjJhN2FmMzE4MWRlYzEzOjU2NTNiMWJhNTMyMDRmMmFhNjg5Y2E5OGE2OTM4Yzc2"
references:
- https://docs.devin.ai/api-reference/overview
- https://docs.devin.ai/api-reference/v1/sessions
validation:
type: Http
content:
request:
method: GET
url: https://api.devin.ai/v1/sessions?limit=1
headers:
Authorization: "Bearer {{ TOKEN }}"
Accept: application/json
response_matcher:
- report_response: true
- type: StatusMatch
status: [200]
- type: JsonValid
- type: WordMatch
words:
- '"sessions"'
match_all_words: true
# Revocation: no documented self-service revocation endpoint exists for
# legacy apk_* service keys; users must rotate them via the Devin web UI.
- name: Cognition Devin Service User Token
id: kingfisher.devin.3
# v3 service-user credentials issued via the Devin UI. Format:
# cog_<52 chars from RFC 4648 base32 lowercase alphabet [a-z2-7]>
pattern: |
(?x)
\b
(
cog_[a-z2-7]{52}
)
\b
pattern_requirements:
min_lowercase: 10
ignore_if_contains:
- "YOUR_"
- "REPLACE_"
- "EXAMPLE"
min_entropy: 4.0
confidence: medium
examples:
- cog_l5osrifmypvazi4j3yko52gj6jfj7qprsmy4lrcf27jas4szffha
- "DEVIN_API_KEY=cog_uv23fh6fc5kpaxdqif7hyvmzslnbmwriqita7cqkbb4rpaixnleq"
- "Authorization: Bearer cog_nxcgv6nuzdvwpgla5wcqsf6dhqrvjmi63j6f6say2au72ihjlxua"
references:
- https://docs.devin.ai/api-reference/overview
- https://docs.devin.ai/api-reference/v3/self
validation:
type: Http
content:
request:
method: GET
url: https://api.devin.ai/v3/self
headers:
Authorization: "Bearer {{ TOKEN }}"
Accept: application/json
response_matcher:
- report_response: true
- type: StatusMatch
status: [200]
- type: JsonValid
- type: WordMatch
words:
- '"principal_type"'
- '"service_user_id"'
match_all_words: false
# Revocation: DELETE /v3beta1/enterprise/service-users/{service_user_id}/api-keys/{api_key_id}
# is not implemented here because (1) it requires a separate admin service user with the
# `ManageAccountServiceUsers` permission (no self-revoke) and (2) the corresponding
# list-api-keys endpoint returns only metadata (no key value/hash), so a leaked token
# cannot be matched to its api_key_id from the token alone. Rotate via the Devin web UI.

View file

@ -6,6 +6,10 @@ description: "Kingfisher release history: new features, rules, bug fixes, and im
# Changelog # Changelog
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
## [v1.102.0]
- Added 3 detection and validation rules for Cognition Devin API credentials: `kingfisher.devin.1` (legacy personal keys, `apk_user_` prefix), `kingfisher.devin.2` (legacy service keys, `apk_` prefix), and `kingfisher.devin.3` (v3 service-user tokens, `cog_` prefix / RFC 4648 base32). Live validation uses `GET /v1/sessions` for `apk_*` keys and `GET /v3/self` for `cog_` tokens.
## [v1.101.0] ## [v1.101.0]
- Fixed asymmetric JWT validation panics by using a single `jsonwebtoken` crypto backend and adding RS256 regression coverage. Thanks @AgentEnder. [#386](https://github.com/mongodb/kingfisher/pull/386) - Fixed asymmetric JWT validation panics by using a single `jsonwebtoken` crypto backend and adding RS256 regression coverage. Thanks @AgentEnder. [#386](https://github.com/mongodb/kingfisher/pull/386)
- Validator panics now fail that validation result instead of crashing the scan, with panic payloads kept out of cached and user-visible validation responses. Thanks @AgentEnder. [#387](https://github.com/mongodb/kingfisher/pull/387) - Validator panics now fail that validation result instead of crashing the scan, with panic payloads kept out of cached and user-visible validation responses. Thanks @AgentEnder. [#387](https://github.com/mongodb/kingfisher/pull/387)

View file

@ -97,6 +97,57 @@ kingfisher scan . --config ./kingfisher.yaml --confidence low
# scan.confidence: high in YAML → CLI flag wins, runs at low confidence # scan.confidence: high in YAML → CLI flag wins, runs at low confidence
``` ```
## Provider endpoint overrides
For self-hosted or private instances of GitHub, GitLab, Gitea, Jira, Confluence,
or Artifactory you can redirect validation and revocation requests away from the
public cloud endpoints.
**Per-run (CLI):**
```bash
# Single provider
kingfisher scan ./repo \
--endpoint github=https://ghe.corp.example.com \
--allow-internal-ips
# Multiple providers at once via a YAML file
kingfisher scan ./repo \
--endpoint-config ./kingfisher-endpoints.yml \
--allow-internal-ips
```
**Persisted in `kingfisher.yaml`** (under `global:`):
```yaml
global:
endpoints:
- github=https://ghe.corp.example.com
- gitlab=https://gitlab.corp.example.com
endpoint_config: ./kingfisher-endpoints.yml # merged with `endpoints` list
allow_internal_ips: true # required for private/localhost URLs
```
`--endpoint-config` / `endpoint_config` points to a YAML file that maps provider
keys to base URLs:
```yaml
endpoints:
github: https://ghe.corp.example.com
gitlab: https://gitlab.corp.example.com
jira: https://jira.corp.example.com
confluence: https://confluence.corp.example.com
artifactory: http://localhost:8071
```
Supported provider keys: `github`, `gitlab`, `gitea`, `jira`, `jira-cloud`,
`confluence`, `artifactory`. For endpoints on private IPs or `localhost`,
always combine with `--allow-internal-ips` (or `global.allow_internal_ips: true`
in `kingfisher.yaml`) — Kingfisher blocks SSRF by default.
See the [GitHub Enterprise section](basic-scanning.md#scan-a-github-enterprise-self-hosted-github-instance)
in the scanning guide for end-to-end examples.
## Webhook URL policy ## Webhook URL policy
`alerts.webhooks[].url` (and `--alert-webhook URL`) **must use `https://`**. `alerts.webhooks[].url` (and `--alert-webhook URL`) **must use `https://`**.