forked from mirrors/kingfisher
performance improvements and rule improvements
This commit is contained in:
parent
ea19a827a0
commit
eb339505f6
20 changed files with 384 additions and 140 deletions
93
README.md
93
README.md
|
|
@ -17,9 +17,9 @@
|
||||||
|
|
||||||
Kingfisher is an open source secret scanner and **live secret validation** tool built in Rust.
|
Kingfisher is an open source secret scanner and **live secret validation** tool built in Rust.
|
||||||
|
|
||||||
It combines Intel's SIMD-accelerated regex engine (Hyperscan) with language-aware parsing to achieve high accuracy at massive scale, and **ships with 938 built-in rules** (484 with live validation) to detect, **validate**, and triage leaked API keys, tokens, and credentials before they ever reach production.
|
It combines Intel's SIMD-accelerated regex engine (Hyperscan) with language-aware parsing to achieve high accuracy at massive scale, and ships with [938 built-in rules](https://mongodb.github.io/kingfisher/rules/builtin-rules/) to detect, **validate**, and triage leaked API keys, tokens, and credentials before they ever reach production.
|
||||||
|
|
||||||
Kingfisher also ships a **browser-based report viewer** that visualizes and triages findings from Kingfisher **and** from Gitleaks and TruffleHog JSON reports — so you can import scans from other tools and triage them in the same UI. A [hosted, upload-based copy of the viewer](https://mongodb.github.io/kingfisher/viewer/) is published on the Kingfisher docs site.
|
Kingfisher also ships a **browser-based report viewer** that visualizes and triages findings from Kingfisher **and** from Gitleaks and TruffleHog JSON reports — so you can import scans from other tools and triage them in the same UI. A [hosted copy of the viewer](https://mongodb.github.io/kingfisher/viewer/) is published on the Kingfisher docs site.
|
||||||
|
|
||||||
Designed for offensive security engineers and blue-team defenders alike, Kingfisher helps you scan repositories, cloud storage, chat, docs, and CI pipelines to find and verify exposed secrets quickly.
|
Designed for offensive security engineers and blue-team defenders alike, Kingfisher helps you scan repositories, cloud storage, chat, docs, and CI pipelines to find and verify exposed secrets quickly.
|
||||||
|
|
||||||
|
|
@ -82,50 +82,6 @@ kingfisher scan /path/to/scan --view-report
|
||||||
NOTE: Replay has been slowed down for demo
|
NOTE: Replay has been slowed down for demo
|
||||||

|

|
||||||
|
|
||||||
## Report Viewer (local and hosted)
|
|
||||||
|
|
||||||
Kingfisher ships a browser-based **report viewer and triager** for three formats:
|
|
||||||
|
|
||||||
- Kingfisher JSON / JSONL (with full `access_map` blast-radius data when present)
|
|
||||||
- **Gitleaks** JSON
|
|
||||||
- **TruffleHog** JSON / JSONL (verified findings are surfaced as active credentials)
|
|
||||||
|
|
||||||
There are two ways to use it:
|
|
||||||
|
|
||||||
1. **Locally via the CLI** — `kingfisher view ./report.json` (bundled into every Kingfisher binary; no external services)
|
|
||||||
2. **Hosted** — [https://mongodb.github.io/kingfisher/viewer/](https://mongodb.github.io/kingfisher/viewer/) — a static, client-side upload-based copy of the same viewer. Drag in Kingfisher, Gitleaks, or TruffleHog reports and triage in your browser; nothing is uploaded to a server.
|
|
||||||
|
|
||||||
### Why use a visual viewer / triager?
|
|
||||||
|
|
||||||
Raw JSON from Kingfisher, Gitleaks, or TruffleHog is great for machines, but awful for humans making decisions on which findings are real and which need to be rotated first. The viewer lets a security engineer:
|
|
||||||
|
|
||||||
- **Skim hundreds of findings at a glance**, grouped by detector, file, repository, and validation status instead of one line per finding in a terminal.
|
|
||||||
- **Triage across multiple tools in one place** — import a Gitleaks report plus a TruffleHog report plus a Kingfisher scan of the same repo and look at them side-by-side with dedup, instead of eyeballing three different JSON schemas.
|
|
||||||
- **Prioritize real, validated secrets** — validated Kingfisher findings and TruffleHog-verified findings float to the top so you act on live credentials first.
|
|
||||||
- **Drop duplicates** — repeated imports and overlapping scans are deduplicated by fingerprint/secret identity so you don't open the same key five times. Per-tool "duplicates removed" cards on the dashboard show how much noise each tool contributed, and an upload-time **Deduplicate findings** toggle (on by default) lets you inspect raw rows when you need to.
|
|
||||||
- **Cross-tool enrichment** — when a Gitleaks or TruffleHog finding lines up with a Kingfisher finding at the same commit, file, and line, the imported row picks up Kingfisher's validation verdict and validate / revoke commands. This is useful when a team already has a Gitleaks or TruffleHog pipeline in CI and wants to layer Kingfisher's validation and remediation data on top of the reports they already produce, without replacing their existing tooling.
|
|
||||||
- **See blast radius** — for Kingfisher reports generated with `--access-map`, the viewer renders the identity, permissions, and resources a leaked credential can reach, so you can tell a dev token apart from a production admin key.
|
|
||||||
- **Export triage decisions** — filter down to what matters and export a cleaned-up subset for a ticket, a rotation runbook, or an audit reviewer.
|
|
||||||
|
|
||||||
Gitleaks and TruffleHog are both widely used open-source secret scanners with their own strengths; Kingfisher's viewer reads their standard JSON output so teams that already run them can pull those findings into the same triage workflow. Kingfisher is not affiliated with or endorsed by the Gitleaks project or Truffle Security Co.; TruffleHog and Gitleaks are trademarks of their respective owners.
|
|
||||||
|
|
||||||
Note: when you pass `--view-report`, Kingfisher starts a web server on port `7890` (default) and opens it in your default browser. By default it binds to `127.0.0.1` for security. You'll see this near the end of the scan output, and **Kingfisher will keep running** until you stop it.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
INFO kingfisher::cli::commands::view: Starting access-map viewer address=127.0.0.1:7890
|
|
||||||
Serving access-map viewer at http://127.0.0.1:7890 (Ctrl+C to stop)
|
|
||||||
```
|
|
||||||
|
|
||||||
**Usage:**
|
|
||||||
```bash
|
|
||||||
kingfisher scan /path/to/scan --access-map --view-report
|
|
||||||
```
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
**Click to view video**
|
|
||||||
[](https://github.com/user-attachments/assets/d33ee7a6-c60a-4e42-88e0-ac03cb429a46)
|
|
||||||
|
|
||||||
# Table of Contents
|
# Table of Contents
|
||||||
|
|
||||||
- [What Is Kingfisher?](#what-is-kingfisher)
|
- [What Is Kingfisher?](#what-is-kingfisher)
|
||||||
|
|
@ -391,6 +347,51 @@ gh release download <version> --repo mongodb/kingfisher \
|
||||||
gh attestation verify kingfisher-linux-x64.tgz --repo mongodb/kingfisher
|
gh attestation verify kingfisher-linux-x64.tgz --repo mongodb/kingfisher
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Report Viewer (local and hosted)
|
||||||
|
|
||||||
|
Kingfisher ships a browser-based **report viewer and triager** for three formats:
|
||||||
|
|
||||||
|
- Kingfisher JSON / JSONL (with full `access_map` blast-radius data when present)
|
||||||
|
- **Gitleaks** JSON
|
||||||
|
- **TruffleHog** JSON / JSONL (verified findings are surfaced as active credentials)
|
||||||
|
|
||||||
|
There are two ways to use it:
|
||||||
|
|
||||||
|
1. **Locally via the CLI** — `kingfisher view ./report.json` (bundled into every Kingfisher binary; no external services)
|
||||||
|
2. **Hosted** — [https://mongodb.github.io/kingfisher/viewer/](https://mongodb.github.io/kingfisher/viewer/) — a static, client-side upload-based copy of the same viewer. Drag in Kingfisher, Gitleaks, or TruffleHog reports and triage in your browser; nothing is uploaded to a server.
|
||||||
|
|
||||||
|
### Why use a visual viewer / triager?
|
||||||
|
|
||||||
|
Raw JSON from Kingfisher, Gitleaks, or TruffleHog is great for machines, but awful for humans making decisions on which findings are real and which need to be rotated first. The viewer lets a security engineer:
|
||||||
|
|
||||||
|
- **Skim hundreds of findings at a glance**, grouped by detector, file, repository, and validation status instead of one line per finding in a terminal.
|
||||||
|
- **Triage across multiple tools in one place** — import a Gitleaks report plus a TruffleHog report plus a Kingfisher scan of the same repo and look at them side-by-side with dedup, instead of eyeballing three different JSON schemas.
|
||||||
|
- **Prioritize real, validated secrets** — validated Kingfisher findings and TruffleHog-verified findings float to the top so you act on live credentials first.
|
||||||
|
- **Drop duplicates** — repeated imports and overlapping scans are deduplicated by fingerprint/secret identity so you don't open the same key five times. Per-tool "duplicates removed" cards on the dashboard show how much noise each tool contributed, and an upload-time **Deduplicate findings** toggle (on by default) lets you inspect raw rows when you need to.
|
||||||
|
- **Cross-tool enrichment** — when a Gitleaks or TruffleHog finding lines up with a Kingfisher finding at the same commit, file, and line, the imported row picks up Kingfisher's validation verdict and validate / revoke commands. This is useful when a team already has a Gitleaks or TruffleHog pipeline in CI and wants to layer Kingfisher's validation and remediation data on top of the reports they already produce, without replacing their existing tooling.
|
||||||
|
- **See blast radius** — for Kingfisher reports generated with `--access-map`, the viewer renders the identity, permissions, and resources a leaked credential can reach, so you can tell a dev token apart from a production admin key.
|
||||||
|
- **Export triage decisions** — filter down to what matters and export a cleaned-up subset for a ticket, a rotation runbook, or an audit reviewer.
|
||||||
|
|
||||||
|
Gitleaks and TruffleHog are both widely used open-source secret scanners with their own strengths; Kingfisher's viewer reads their standard JSON output so teams that already run them can pull those findings into the same triage workflow. Kingfisher is not affiliated with or endorsed by the Gitleaks project or Truffle Security Co.; TruffleHog and Gitleaks are trademarks of their respective owners.
|
||||||
|
|
||||||
|
Note: when you pass `--view-report`, Kingfisher starts a web server on port `7890` (default) and opens it in your default browser. By default it binds to `127.0.0.1` for security. You'll see this near the end of the scan output, and **Kingfisher will keep running** until you stop it.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
INFO kingfisher::cli::commands::view: Starting access-map viewer address=127.0.0.1:7890
|
||||||
|
Serving access-map viewer at http://127.0.0.1:7890 (Ctrl+C to stop)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Usage:**
|
||||||
|
```bash
|
||||||
|
kingfisher scan /path/to/scan --access-map --view-report
|
||||||
|
```
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
**Click to view video**
|
||||||
|
[](https://github.com/user-attachments/assets/d33ee7a6-c60a-4e42-88e0-ac03cb429a46)
|
||||||
|
|
||||||
# Detection Rules
|
# Detection Rules
|
||||||
|
|
||||||
Kingfisher ships with [938 built-in rules](crates/kingfisher-rules/data/rules/) covering cloud keys, AI tokens, CI/CD secrets, database credentials, and SaaS API keys. Below is an overview — see the full list in [crates/kingfisher-rules/data/rules/](crates/kingfisher-rules/data/rules/):
|
Kingfisher ships with [938 built-in rules](crates/kingfisher-rules/data/rules/) covering cloud keys, AI tokens, CI/CD secrets, database credentials, and SaaS API keys. Below is an overview — see the full list in [crates/kingfisher-rules/data/rules/](crates/kingfisher-rules/data/rules/):
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ rules:
|
||||||
pattern_requirements:
|
pattern_requirements:
|
||||||
min_digits: 4
|
min_digits: 4
|
||||||
min_entropy: 3.0
|
min_entropy: 3.0
|
||||||
confidence: low
|
confidence: medium
|
||||||
visible: false
|
visible: false
|
||||||
examples:
|
examples:
|
||||||
- AGORA_APP_ID=78b8de76d5678a6feb2605721c0aefbe
|
- AGORA_APP_ID=78b8de76d5678a6feb2605721c0aefbe
|
||||||
|
|
|
||||||
|
|
@ -57,4 +57,4 @@ rules:
|
||||||
min_entropy: 1.0
|
min_entropy: 1.0
|
||||||
examples:
|
examples:
|
||||||
- 'CYPRESS_PROJECT_ID=a7bq2k'
|
- 'CYPRESS_PROJECT_ID=a7bq2k'
|
||||||
- 'projectId: "abc123"'
|
- 'CYPRESS_PROJECT_ID: "abc123"'
|
||||||
|
|
|
||||||
|
|
@ -17,8 +17,7 @@ rules:
|
||||||
confidence: medium
|
confidence: medium
|
||||||
categories: [api, key]
|
categories: [api, key]
|
||||||
examples:
|
examples:
|
||||||
- 'HIGHNOTE_API_KEY=sk_live_AbCdEfGhIjKlMnOpQrStUvWxYz1234'
|
- 'HIGHNOTE_API_KEY="sk_live_a2V5XzAxS1BSWE1LTjBEWE1INlpBU0VEWjU2VFE3LFdjOWxFMTNDS29xRkdlYU9uMUpDbUpTZWE"'
|
||||||
- 'highnote_key: rk_test_AbCdEfGhIjKlMnOpQrStUvWxYz1234'
|
|
||||||
validation:
|
validation:
|
||||||
type: Http
|
type: Http
|
||||||
content:
|
content:
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ rules:
|
||||||
pattern_requirements:
|
pattern_requirements:
|
||||||
min_digits: 6
|
min_digits: 6
|
||||||
min_entropy: 2.0
|
min_entropy: 2.0
|
||||||
confidence: low
|
confidence: medium
|
||||||
visible: false
|
visible: false
|
||||||
examples:
|
examples:
|
||||||
- "{ \"Huawei\": { \"ClientId\": \"100809947\", \"ClientSecret\": \"...\" } }"
|
- "{ \"Huawei\": { \"ClientId\": \"100809947\", \"ClientSecret\": \"...\" } }"
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ rules:
|
||||||
(?x)
|
(?x)
|
||||||
\b
|
\b
|
||||||
(
|
(
|
||||||
api_live\.[a-zA-Z0-9_-]{20,80}
|
api_(?:live|sandbox)\.[a-zA-Z0-9_-]{20,80}
|
||||||
)
|
)
|
||||||
\b
|
\b
|
||||||
pattern_requirements:
|
pattern_requirements:
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,6 @@ rules:
|
||||||
categories: [api, key]
|
categories: [api, key]
|
||||||
examples:
|
examples:
|
||||||
- 'PADDLE_API_KEY=pdl_live_apikey_01kps076233qscw38dxz320d0e_Ab3D5fGb7Jk9LmNpQrStUv_X2z'
|
- 'PADDLE_API_KEY=pdl_live_apikey_01kps076233qscw38dxz320d0e_Ab3D5fGb7Jk9LmNpQrStUv_X2z'
|
||||||
- 'paddle_key: pdl_sdbx_apikey_01kps08npwb1rv4ryqxh0jr30c_qwErTyUiObAsDfGhJkLmN2_B7Q'
|
|
||||||
validation:
|
validation:
|
||||||
type: Http
|
type: Http
|
||||||
content:
|
content:
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ rules:
|
||||||
confidence: medium
|
confidence: medium
|
||||||
examples:
|
examples:
|
||||||
- stripe_secret_key = sk_live_f01c79xuuug7yodgzj5ws0h1x2kyvho3
|
- stripe_secret_key = sk_live_f01c79xuuug7yodgzj5ws0h1x2kyvho3
|
||||||
- stripe_secret_key = pk_live_51O4GlNLQpd8Ph8H3or6Sv8fhuSPIQncX0dY318y8Hc9SYRyS4aeyrTN19ztOmAsuVZSTKNfI7RZoSOwNkLa0cwm010oLA68VFA
|
- stripe_secret_key = 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
|
||||||
- "strp_sec_key: rk_live_4haG9YwGkL2hXqTj5pSzo8FzB3uCwE7n"
|
- "strp_sec_key: rk_live_4haG9YwGkL2hXqTj5pSzo8FzB3uCwE7n"
|
||||||
validation:
|
validation:
|
||||||
type: Http
|
type: Http
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,6 @@ rules:
|
||||||
min_entropy: 3.0
|
min_entropy: 3.0
|
||||||
confidence: medium
|
confidence: medium
|
||||||
examples:
|
examples:
|
||||||
- 'VOLCENGINE_ACCESS_KEY=AKLTY2IwOGJIMTdiZmI5NGU1MWFiNWE3MWJkNWY2MDdmOGU'
|
- 'VOLCENGINE_ACCESS_KEY=AKLTY2IwOGJIMTdiZmI5NGU1MWFiNWE3MWJkNWY2MDdmOGUxYz'
|
||||||
references:
|
references:
|
||||||
- https://www.volcengine.com/docs/6291/65568
|
- https://www.volcengine.com/docs/6291/65568
|
||||||
|
|
@ -17,7 +17,7 @@ rules:
|
||||||
pattern_requirements:
|
pattern_requirements:
|
||||||
min_digits: 4
|
min_digits: 4
|
||||||
min_entropy: 3.5
|
min_entropy: 3.5
|
||||||
confidence: low
|
confidence: medium
|
||||||
visible: false
|
visible: false
|
||||||
examples:
|
examples:
|
||||||
- "webex_client = Ac0769801df88a3535b4b018ef570b499002bda401b3b8789259a937f22d66095"
|
- "webex_client = Ac0769801df88a3535b4b018ef570b499002bda401b3b8789259a937f22d66095"
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,6 @@ rules:
|
||||||
confidence: medium
|
confidence: medium
|
||||||
examples:
|
examples:
|
||||||
- 'WORKOS_API_KEY="sk_live_a2V5XzAxS1BSWE1LTjBEWE1INlpBU0VEWjU2VFE3LFdjOWxFMTNDS29xRkdlYU9uMUpDbUpTZWE"'
|
- 'WORKOS_API_KEY="sk_live_a2V5XzAxS1BSWE1LTjBEWE1INlpBU0VEWjU2VFE3LFdjOWxFMTNDS29xRkdlYU9uMUpDbUpTZWE"'
|
||||||
- 'workos apiKey: "sk_test_a2V5XzAxS1BSWE1LTjBEWE1INlpBU0VEWjU2VFE3LFdjOWxFMTNDS29xRkdlYU9uMUpDbUpTZWE"'
|
|
||||||
references:
|
references:
|
||||||
- https://workos.com/docs/reference/api-keys
|
- https://workos.com/docs/reference/api-keys
|
||||||
- https://workos.com/docs/authkit/api-keys
|
- https://workos.com/docs/authkit/api-keys
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,8 @@ rules:
|
||||||
Accept: application/json
|
Accept: application/json
|
||||||
response_matcher:
|
response_matcher:
|
||||||
- report_response: true
|
- report_response: true
|
||||||
|
- type: StatusMatch
|
||||||
|
status: [200]
|
||||||
- type: JsonValid
|
- type: JsonValid
|
||||||
- type: WordMatch
|
- type: WordMatch
|
||||||
words:
|
words:
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,19 @@
|
||||||
// Client-side search/filter for the built-in rules table
|
// Client-side search/filter for the built-in rules table.
|
||||||
document.addEventListener("DOMContentLoaded", function () {
|
// Material's `navigation.instant` feature swaps page bodies without firing
|
||||||
const input = document.querySelector(".rules-search");
|
// DOMContentLoaded, so we subscribe to the `document$` observable it exposes
|
||||||
if (!input) return;
|
// and re-wire the handler every time a new page is rendered.
|
||||||
|
function initRulesFilter() {
|
||||||
const table = document.querySelector(".rules-table");
|
const table = document.querySelector(".rules-table");
|
||||||
if (!table) return;
|
if (!table) return;
|
||||||
|
|
||||||
const rows = Array.from(table.querySelectorAll("tbody tr"));
|
const input = document.querySelector(".rules-search");
|
||||||
const countEl = document.querySelector(".rules-count");
|
const countEl = document.querySelector(".rules-count");
|
||||||
|
const tbody = table.querySelector("tbody");
|
||||||
|
|
||||||
|
if (table.dataset.rulesFilterBound === "1") return;
|
||||||
|
table.dataset.rulesFilterBound = "1";
|
||||||
|
|
||||||
|
const rows = Array.from(tbody.querySelectorAll("tr"));
|
||||||
const total = rows.length;
|
const total = rows.length;
|
||||||
|
|
||||||
function updateCount(visible) {
|
function updateCount(visible) {
|
||||||
|
|
@ -16,23 +22,98 @@ document.addEventListener("DOMContentLoaded", function () {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let debounceTimer;
|
function applyFilter() {
|
||||||
input.addEventListener("input", function () {
|
if (!input) {
|
||||||
clearTimeout(debounceTimer);
|
updateCount(total);
|
||||||
debounceTimer = setTimeout(function () {
|
return;
|
||||||
const query = input.value.toLowerCase().trim();
|
}
|
||||||
let visible = 0;
|
const query = input.value.toLowerCase().trim();
|
||||||
|
let visible = 0;
|
||||||
|
rows.forEach(function (row) {
|
||||||
|
const text = row.textContent.toLowerCase();
|
||||||
|
const match = !query || text.indexOf(query) !== -1;
|
||||||
|
row.style.display = match ? "" : "none";
|
||||||
|
if (match) visible++;
|
||||||
|
});
|
||||||
|
updateCount(visible);
|
||||||
|
}
|
||||||
|
|
||||||
rows.forEach(function (row) {
|
if (input) {
|
||||||
const text = row.textContent.toLowerCase();
|
let debounceTimer;
|
||||||
const match = !query || text.indexOf(query) !== -1;
|
input.addEventListener("input", function () {
|
||||||
row.style.display = match ? "" : "none";
|
clearTimeout(debounceTimer);
|
||||||
if (match) visible++;
|
debounceTimer = setTimeout(applyFilter, 80);
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
updateCount(visible);
|
// --- Sortable columns ---
|
||||||
}, 150);
|
const headers = Array.from(table.querySelectorAll("thead th"));
|
||||||
|
const confidenceOrder = { "high": 3, "medium": 2, "low": 1 };
|
||||||
|
let sortState = { index: -1, dir: 1 };
|
||||||
|
|
||||||
|
function cellKey(row, index) {
|
||||||
|
const cell = row.children[index];
|
||||||
|
if (!cell) return "";
|
||||||
|
return cell.textContent.trim().toLowerCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
function compare(a, b, index) {
|
||||||
|
const av = cellKey(a, index);
|
||||||
|
const bv = cellKey(b, index);
|
||||||
|
// Confidence column — ordered by severity
|
||||||
|
if (headers[index] && headers[index].textContent.trim().toLowerCase() === "confidence") {
|
||||||
|
return (confidenceOrder[av] || 0) - (confidenceOrder[bv] || 0);
|
||||||
|
}
|
||||||
|
// Yes/empty columns — Yes first
|
||||||
|
const aYes = av === "yes" ? 1 : 0;
|
||||||
|
const bYes = bv === "yes" ? 1 : 0;
|
||||||
|
if (aYes !== bYes) return bYes - aYes;
|
||||||
|
return av.localeCompare(bv, undefined, { numeric: true, sensitivity: "base" });
|
||||||
|
}
|
||||||
|
|
||||||
|
function sortBy(index) {
|
||||||
|
if (sortState.index === index) {
|
||||||
|
sortState.dir = -sortState.dir;
|
||||||
|
} else {
|
||||||
|
sortState.index = index;
|
||||||
|
sortState.dir = 1;
|
||||||
|
}
|
||||||
|
const dir = sortState.dir;
|
||||||
|
const sorted = rows.slice().sort(function (a, b) {
|
||||||
|
return dir * compare(a, b, index);
|
||||||
|
});
|
||||||
|
const frag = document.createDocumentFragment();
|
||||||
|
sorted.forEach(function (row) { frag.appendChild(row); });
|
||||||
|
tbody.appendChild(frag);
|
||||||
|
|
||||||
|
headers.forEach(function (h, i) {
|
||||||
|
h.classList.remove("is-sorted-asc", "is-sorted-desc");
|
||||||
|
if (i === index) {
|
||||||
|
h.classList.add(dir === 1 ? "is-sorted-asc" : "is-sorted-desc");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
headers.forEach(function (th, i) {
|
||||||
|
th.classList.add("is-sortable");
|
||||||
|
th.setAttribute("role", "button");
|
||||||
|
th.setAttribute("tabindex", "0");
|
||||||
|
th.addEventListener("click", function () { sortBy(i); });
|
||||||
|
th.addEventListener("keydown", function (e) {
|
||||||
|
if (e.key === "Enter" || e.key === " ") {
|
||||||
|
e.preventDefault();
|
||||||
|
sortBy(i);
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
updateCount(total);
|
updateCount(total);
|
||||||
});
|
}
|
||||||
|
|
||||||
|
if (typeof document$ !== "undefined" && document$.subscribe) {
|
||||||
|
document$.subscribe(initRulesFilter);
|
||||||
|
} else if (document.readyState === "loading") {
|
||||||
|
document.addEventListener("DOMContentLoaded", initRulesFilter);
|
||||||
|
} else {
|
||||||
|
initRulesFilter();
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -265,6 +265,161 @@
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.md-typeset table.rules-table,
|
||||||
|
table.rules-table {
|
||||||
|
display: table;
|
||||||
|
width: 100%;
|
||||||
|
table-layout: auto;
|
||||||
|
border-collapse: separate;
|
||||||
|
border-spacing: 0;
|
||||||
|
margin: 1rem 0 2rem;
|
||||||
|
font-size: 0.72rem;
|
||||||
|
line-height: 1.35;
|
||||||
|
border: 1px solid var(--md-default-fg-color--lightest);
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
overflow: hidden;
|
||||||
|
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.04);
|
||||||
|
}
|
||||||
|
|
||||||
|
.md-typeset table.rules-table thead,
|
||||||
|
table.rules-table thead {
|
||||||
|
background: var(--md-primary-fg-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.md-typeset table.rules-table thead th,
|
||||||
|
table.rules-table thead th {
|
||||||
|
color: #fff;
|
||||||
|
font-weight: 600;
|
||||||
|
text-align: left;
|
||||||
|
padding: 0.55rem 0.7rem;
|
||||||
|
border: none;
|
||||||
|
font-size: 0.7rem;
|
||||||
|
letter-spacing: 0.02em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
white-space: nowrap;
|
||||||
|
position: sticky;
|
||||||
|
top: 0;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.md-typeset table.rules-table thead th.is-sortable,
|
||||||
|
table.rules-table thead th.is-sortable {
|
||||||
|
cursor: pointer;
|
||||||
|
user-select: none;
|
||||||
|
padding-right: 1.75rem;
|
||||||
|
position: sticky;
|
||||||
|
}
|
||||||
|
|
||||||
|
.md-typeset table.rules-table thead th.is-sortable::after,
|
||||||
|
table.rules-table thead th.is-sortable::after {
|
||||||
|
content: "";
|
||||||
|
display: inline-block;
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
margin-left: 0.5rem;
|
||||||
|
vertical-align: middle;
|
||||||
|
border-left: 4px solid transparent;
|
||||||
|
border-right: 4px solid transparent;
|
||||||
|
border-top: 5px solid rgba(255, 255, 255, 0.35);
|
||||||
|
border-bottom: 5px solid rgba(255, 255, 255, 0.35);
|
||||||
|
opacity: 0.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.md-typeset table.rules-table thead th.is-sortable:hover,
|
||||||
|
table.rules-table thead th.is-sortable:hover {
|
||||||
|
background: rgba(255, 255, 255, 0.08);
|
||||||
|
}
|
||||||
|
|
||||||
|
.md-typeset table.rules-table thead th.is-sorted-asc::after,
|
||||||
|
table.rules-table thead th.is-sorted-asc::after {
|
||||||
|
border-top: 0;
|
||||||
|
border-bottom: 5px solid #fff;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.md-typeset table.rules-table thead th.is-sorted-desc::after,
|
||||||
|
table.rules-table thead th.is-sorted-desc::after {
|
||||||
|
border-bottom: 0;
|
||||||
|
border-top: 5px solid #fff;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.md-typeset table.rules-table tbody td,
|
||||||
|
table.rules-table tbody td {
|
||||||
|
padding: 0.4rem 0.7rem;
|
||||||
|
border: none;
|
||||||
|
border-bottom: 1px solid var(--md-default-fg-color--lightest);
|
||||||
|
vertical-align: middle;
|
||||||
|
background: var(--md-default-bg-color);
|
||||||
|
word-break: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
.md-typeset table.rules-table tbody tr:nth-child(even) td,
|
||||||
|
table.rules-table tbody tr:nth-child(even) td {
|
||||||
|
background: var(--md-code-bg-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.md-typeset table.rules-table tbody tr:hover td,
|
||||||
|
table.rules-table tbody tr:hover td {
|
||||||
|
background: var(--md-accent-fg-color--transparent);
|
||||||
|
}
|
||||||
|
|
||||||
|
.md-typeset table.rules-table tbody tr:last-child td,
|
||||||
|
table.rules-table tbody tr:last-child td {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.md-typeset table.rules-table td code,
|
||||||
|
table.rules-table td code {
|
||||||
|
background: var(--md-code-bg-color);
|
||||||
|
color: var(--md-code-fg-color);
|
||||||
|
padding: 0.1rem 0.35rem;
|
||||||
|
border-radius: 0.25rem;
|
||||||
|
font-size: 0.68rem;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.md-typeset table.rules-table tbody tr:nth-child(even) td code,
|
||||||
|
table.rules-table tbody tr:nth-child(even) td code {
|
||||||
|
background: var(--md-default-bg-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* First column (Provider) — emphasized */
|
||||||
|
.md-typeset table.rules-table tbody td:first-child,
|
||||||
|
table.rules-table tbody td:first-child {
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--md-primary-fg-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Confidence badges */
|
||||||
|
.md-typeset table.rules-table td:nth-child(4),
|
||||||
|
table.rules-table td:nth-child(4) {
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Validates / Revokes columns — center */
|
||||||
|
.md-typeset table.rules-table td:nth-child(5),
|
||||||
|
.md-typeset table.rules-table td:nth-child(6),
|
||||||
|
.md-typeset table.rules-table th:nth-child(5),
|
||||||
|
.md-typeset table.rules-table th:nth-child(6),
|
||||||
|
table.rules-table td:nth-child(5),
|
||||||
|
table.rules-table td:nth-child(6),
|
||||||
|
table.rules-table th:nth-child(5),
|
||||||
|
table.rules-table th:nth-child(6) {
|
||||||
|
text-align: center;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Responsive wrapper */
|
||||||
|
@media screen and (max-width: 960px) {
|
||||||
|
.md-typeset table.rules-table,
|
||||||
|
table.rules-table {
|
||||||
|
display: block;
|
||||||
|
overflow-x: auto;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Responsive */
|
/* Responsive */
|
||||||
@media screen and (max-width: 768px) {
|
@media screen and (max-width: 768px) {
|
||||||
.kf-hero__title {
|
.kf-hero__title {
|
||||||
|
|
|
||||||
|
|
@ -82,7 +82,7 @@ Drag a Kingfisher, Gitleaks, or TruffleHog JSON report into the page (or use the
|
||||||
|
|
||||||
You can test the hosted page with a bundled sample report:
|
You can test the hosted page with a bundled sample report:
|
||||||
|
|
||||||
- [Open sample report JSON](../viewer/sample-report.json) | No |
|
- [Open sample report JSON](../viewer/sample-report.json)
|
||||||
|
|
||||||
## Caveats for imported Gitleaks / TruffleHog reports
|
## Caveats for imported Gitleaks / TruffleHog reports
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,7 @@ Of these, **605** include live validation and **57** support direct revocation.
|
||||||
<td>Adobe</td>
|
<td>Adobe</td>
|
||||||
<td>Adobe Stock API Key</td>
|
<td>Adobe Stock API Key</td>
|
||||||
<td><code>kingfisher.adobe.1</code></td>
|
<td><code>kingfisher.adobe.1</code></td>
|
||||||
<td>Unknown</td>
|
<td>Medium</td>
|
||||||
<td>Yes</td>
|
<td>Yes</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
@ -71,7 +71,7 @@ Of these, **605** include live validation and **57** support direct revocation.
|
||||||
<td>Adobe</td>
|
<td>Adobe</td>
|
||||||
<td>Adobe IO Product ID</td>
|
<td>Adobe IO Product ID</td>
|
||||||
<td><code>kingfisher.adobe.2</code></td>
|
<td><code>kingfisher.adobe.2</code></td>
|
||||||
<td>Unknown</td>
|
<td>Medium</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
@ -79,7 +79,7 @@ Of these, **605** include live validation and **57** support direct revocation.
|
||||||
<td>Adobe</td>
|
<td>Adobe</td>
|
||||||
<td>Adobe OAuth Client Secret</td>
|
<td>Adobe OAuth Client Secret</td>
|
||||||
<td><code>kingfisher.adobe.3</code></td>
|
<td><code>kingfisher.adobe.3</code></td>
|
||||||
<td>Unknown</td>
|
<td>Medium</td>
|
||||||
<td>Yes</td>
|
<td>Yes</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
@ -87,7 +87,7 @@ Of these, **605** include live validation and **57** support direct revocation.
|
||||||
<td>Adobe</td>
|
<td>Adobe</td>
|
||||||
<td>Adobe OAuth Client ID</td>
|
<td>Adobe OAuth Client ID</td>
|
||||||
<td><code>kingfisher.adobe.4</code></td>
|
<td><code>kingfisher.adobe.4</code></td>
|
||||||
<td>Unknown</td>
|
<td>Medium</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
@ -1511,7 +1511,7 @@ Of these, **605** include live validation and **57** support direct revocation.
|
||||||
<td>Coinbase</td>
|
<td>Coinbase</td>
|
||||||
<td>Coinbase Access Token</td>
|
<td>Coinbase Access Token</td>
|
||||||
<td><code>kingfisher.coinbase.1</code></td>
|
<td><code>kingfisher.coinbase.1</code></td>
|
||||||
<td>Unknown</td>
|
<td>Medium</td>
|
||||||
<td>Yes</td>
|
<td>Yes</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
@ -1519,7 +1519,7 @@ Of these, **605** include live validation and **57** support direct revocation.
|
||||||
<td>Coinbase</td>
|
<td>Coinbase</td>
|
||||||
<td>Coinbase CDP API Key (ECDSA)</td>
|
<td>Coinbase CDP API Key (ECDSA)</td>
|
||||||
<td><code>kingfisher.coinbase.2</code></td>
|
<td><code>kingfisher.coinbase.2</code></td>
|
||||||
<td>Unknown</td>
|
<td>Medium</td>
|
||||||
<td>Yes</td>
|
<td>Yes</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
@ -1527,7 +1527,7 @@ Of these, **605** include live validation and **57** support direct revocation.
|
||||||
<td>Coinbase</td>
|
<td>Coinbase</td>
|
||||||
<td>Coinbase CDP API Key (Ed25519)</td>
|
<td>Coinbase CDP API Key (Ed25519)</td>
|
||||||
<td><code>kingfisher.coinbase.3</code></td>
|
<td><code>kingfisher.coinbase.3</code></td>
|
||||||
<td>Unknown</td>
|
<td>Medium</td>
|
||||||
<td>Yes</td>
|
<td>Yes</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
@ -1975,7 +1975,7 @@ Of these, **605** include live validation and **57** support direct revocation.
|
||||||
<td>Diffbot</td>
|
<td>Diffbot</td>
|
||||||
<td>Diffbot API Key</td>
|
<td>Diffbot API Key</td>
|
||||||
<td><code>kingfisher.diffbot.1</code></td>
|
<td><code>kingfisher.diffbot.1</code></td>
|
||||||
<td>Unknown</td>
|
<td>Medium</td>
|
||||||
<td>Yes</td>
|
<td>Yes</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
@ -2415,7 +2415,7 @@ Of these, **605** include live validation and **57** support direct revocation.
|
||||||
<td>Facebook</td>
|
<td>Facebook</td>
|
||||||
<td>Facebook Secret Key</td>
|
<td>Facebook Secret Key</td>
|
||||||
<td><code>kingfisher.facebook.2</code></td>
|
<td><code>kingfisher.facebook.2</code></td>
|
||||||
<td>Unknown</td>
|
<td>Medium</td>
|
||||||
<td>Yes</td>
|
<td>Yes</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
@ -2463,7 +2463,7 @@ Of these, **605** include live validation and **57** support direct revocation.
|
||||||
<td>Figma</td>
|
<td>Figma</td>
|
||||||
<td>Figma Personal Access Header Token</td>
|
<td>Figma Personal Access Header Token</td>
|
||||||
<td><code>kingfisher.figma.2</code></td>
|
<td><code>kingfisher.figma.2</code></td>
|
||||||
<td>Unknown</td>
|
<td>Medium</td>
|
||||||
<td>Yes</td>
|
<td>Yes</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
@ -2879,7 +2879,7 @@ Of these, **605** include live validation and **57** support direct revocation.
|
||||||
<td>Github</td>
|
<td>Github</td>
|
||||||
<td>GitHub Personal Access Token - fine-grained permissions</td>
|
<td>GitHub Personal Access Token - fine-grained permissions</td>
|
||||||
<td><code>kingfisher.github.1</code></td>
|
<td><code>kingfisher.github.1</code></td>
|
||||||
<td>Unknown</td>
|
<td>Medium</td>
|
||||||
<td>Yes</td>
|
<td>Yes</td>
|
||||||
<td>Yes</td>
|
<td>Yes</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
@ -2887,7 +2887,7 @@ Of these, **605** include live validation and **57** support direct revocation.
|
||||||
<td>Github</td>
|
<td>Github</td>
|
||||||
<td>GitHub Personal Access Token</td>
|
<td>GitHub Personal Access Token</td>
|
||||||
<td><code>kingfisher.github.2</code></td>
|
<td><code>kingfisher.github.2</code></td>
|
||||||
<td>Unknown</td>
|
<td>Medium</td>
|
||||||
<td>Yes</td>
|
<td>Yes</td>
|
||||||
<td>Yes</td>
|
<td>Yes</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
@ -2903,7 +2903,7 @@ Of these, **605** include live validation and **57** support direct revocation.
|
||||||
<td>Github</td>
|
<td>Github</td>
|
||||||
<td>GitHub App User-to-Server Token</td>
|
<td>GitHub App User-to-Server Token</td>
|
||||||
<td><code>kingfisher.github.4</code></td>
|
<td><code>kingfisher.github.4</code></td>
|
||||||
<td>Unknown</td>
|
<td>Medium</td>
|
||||||
<td>Yes</td>
|
<td>Yes</td>
|
||||||
<td>Yes</td>
|
<td>Yes</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
@ -2911,7 +2911,7 @@ Of these, **605** include live validation and **57** support direct revocation.
|
||||||
<td>Github</td>
|
<td>Github</td>
|
||||||
<td>GitHub App Server-to-Server Token</td>
|
<td>GitHub App Server-to-Server Token</td>
|
||||||
<td><code>kingfisher.github.5</code></td>
|
<td><code>kingfisher.github.5</code></td>
|
||||||
<td>Unknown</td>
|
<td>Medium</td>
|
||||||
<td>Yes</td>
|
<td>Yes</td>
|
||||||
<td>Yes</td>
|
<td>Yes</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
@ -2919,7 +2919,7 @@ Of these, **605** include live validation and **57** support direct revocation.
|
||||||
<td>Github</td>
|
<td>Github</td>
|
||||||
<td>GitHub Refresh Token</td>
|
<td>GitHub Refresh Token</td>
|
||||||
<td><code>kingfisher.github.6</code></td>
|
<td><code>kingfisher.github.6</code></td>
|
||||||
<td>Unknown</td>
|
<td>Medium</td>
|
||||||
<td>Yes</td>
|
<td>Yes</td>
|
||||||
<td>Yes</td>
|
<td>Yes</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
@ -2927,7 +2927,7 @@ Of these, **605** include live validation and **57** support direct revocation.
|
||||||
<td>Github</td>
|
<td>Github</td>
|
||||||
<td>GitHub Client ID</td>
|
<td>GitHub Client ID</td>
|
||||||
<td><code>kingfisher.github.7</code></td>
|
<td><code>kingfisher.github.7</code></td>
|
||||||
<td>Unknown</td>
|
<td>Medium</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
@ -2935,7 +2935,7 @@ Of these, **605** include live validation and **57** support direct revocation.
|
||||||
<td>Github</td>
|
<td>Github</td>
|
||||||
<td>GitHub Legacy Secret Key</td>
|
<td>GitHub Legacy Secret Key</td>
|
||||||
<td><code>kingfisher.github.8</code></td>
|
<td><code>kingfisher.github.8</code></td>
|
||||||
<td>Unknown</td>
|
<td>Medium</td>
|
||||||
<td>Yes</td>
|
<td>Yes</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
@ -2999,7 +2999,7 @@ Of these, **605** include live validation and **57** support direct revocation.
|
||||||
<td>Gitlab</td>
|
<td>Gitlab</td>
|
||||||
<td>GitLab Runner Registration Token</td>
|
<td>GitLab Runner Registration Token</td>
|
||||||
<td><code>kingfisher.gitlab.2</code></td>
|
<td><code>kingfisher.gitlab.2</code></td>
|
||||||
<td>Unknown</td>
|
<td>Medium</td>
|
||||||
<td>Yes</td>
|
<td>Yes</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
@ -3007,7 +3007,7 @@ Of these, **605** include live validation and **57** support direct revocation.
|
||||||
<td>Gitlab</td>
|
<td>Gitlab</td>
|
||||||
<td>GitLab Pipeline Trigger Token</td>
|
<td>GitLab Pipeline Trigger Token</td>
|
||||||
<td><code>kingfisher.gitlab.3</code></td>
|
<td><code>kingfisher.gitlab.3</code></td>
|
||||||
<td>Unknown</td>
|
<td>Medium</td>
|
||||||
<td>Yes</td>
|
<td>Yes</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
@ -3887,7 +3887,7 @@ Of these, **605** include live validation and **57** support direct revocation.
|
||||||
<td>Langchain</td>
|
<td>Langchain</td>
|
||||||
<td>LangSmith Personal Access Token</td>
|
<td>LangSmith Personal Access Token</td>
|
||||||
<td><code>kingfisher.langchain.1</code></td>
|
<td><code>kingfisher.langchain.1</code></td>
|
||||||
<td>Unknown</td>
|
<td>Medium</td>
|
||||||
<td>Yes</td>
|
<td>Yes</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
@ -3895,7 +3895,7 @@ Of these, **605** include live validation and **57** support direct revocation.
|
||||||
<td>Langchain</td>
|
<td>Langchain</td>
|
||||||
<td>LangSmith Service Key</td>
|
<td>LangSmith Service Key</td>
|
||||||
<td><code>kingfisher.langchain.2</code></td>
|
<td><code>kingfisher.langchain.2</code></td>
|
||||||
<td>Unknown</td>
|
<td>Medium</td>
|
||||||
<td>Yes</td>
|
<td>Yes</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
@ -4463,7 +4463,7 @@ Of these, **605** include live validation and **57** support direct revocation.
|
||||||
<td>Mongodb</td>
|
<td>Mongodb</td>
|
||||||
<td>MongoDB API Private Key</td>
|
<td>MongoDB API Private Key</td>
|
||||||
<td><code>kingfisher.mongodb.1</code></td>
|
<td><code>kingfisher.mongodb.1</code></td>
|
||||||
<td>Unknown</td>
|
<td>Medium</td>
|
||||||
<td>Yes</td>
|
<td>Yes</td>
|
||||||
<td>Yes</td>
|
<td>Yes</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
@ -4479,7 +4479,7 @@ Of these, **605** include live validation and **57** support direct revocation.
|
||||||
<td>Mongodb</td>
|
<td>Mongodb</td>
|
||||||
<td>MongoDB URI Connection String</td>
|
<td>MongoDB URI Connection String</td>
|
||||||
<td><code>kingfisher.mongodb.3</code></td>
|
<td><code>kingfisher.mongodb.3</code></td>
|
||||||
<td>Unknown</td>
|
<td>Medium</td>
|
||||||
<td>Yes</td>
|
<td>Yes</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
@ -4487,7 +4487,7 @@ Of these, **605** include live validation and **57** support direct revocation.
|
||||||
<td>Mongodb</td>
|
<td>Mongodb</td>
|
||||||
<td>MongoDB Atlas Service Account Token</td>
|
<td>MongoDB Atlas Service Account Token</td>
|
||||||
<td><code>kingfisher.mongodb.4</code></td>
|
<td><code>kingfisher.mongodb.4</code></td>
|
||||||
<td>Unknown</td>
|
<td>Medium</td>
|
||||||
<td>Yes</td>
|
<td>Yes</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
@ -4535,7 +4535,7 @@ Of these, **605** include live validation and **57** support direct revocation.
|
||||||
<td>Nasa</td>
|
<td>Nasa</td>
|
||||||
<td>NASA API Key</td>
|
<td>NASA API Key</td>
|
||||||
<td><code>kingfisher.nasa.1</code></td>
|
<td><code>kingfisher.nasa.1</code></td>
|
||||||
<td>Unknown</td>
|
<td>Medium</td>
|
||||||
<td>Yes</td>
|
<td>Yes</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
@ -4567,7 +4567,7 @@ Of these, **605** include live validation and **57** support direct revocation.
|
||||||
<td>Netlify</td>
|
<td>Netlify</td>
|
||||||
<td>Netlify API Key</td>
|
<td>Netlify API Key</td>
|
||||||
<td><code>kingfisher.netlify.1</code></td>
|
<td><code>kingfisher.netlify.1</code></td>
|
||||||
<td>Unknown</td>
|
<td>Medium</td>
|
||||||
<td>Yes</td>
|
<td>Yes</td>
|
||||||
<td>Yes</td>
|
<td>Yes</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
@ -4615,7 +4615,7 @@ Of these, **605** include live validation and **57** support direct revocation.
|
||||||
<td>Ngrok</td>
|
<td>Ngrok</td>
|
||||||
<td>Ngrok API Key</td>
|
<td>Ngrok API Key</td>
|
||||||
<td><code>kingfisher.ngrok.1</code></td>
|
<td><code>kingfisher.ngrok.1</code></td>
|
||||||
<td>Unknown</td>
|
<td>Medium</td>
|
||||||
<td>Yes</td>
|
<td>Yes</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
@ -4759,7 +4759,7 @@ Of these, **605** include live validation and **57** support direct revocation.
|
||||||
<td>Okta</td>
|
<td>Okta</td>
|
||||||
<td>Okta API Token</td>
|
<td>Okta API Token</td>
|
||||||
<td><code>kingfisher.okta.1</code></td>
|
<td><code>kingfisher.okta.1</code></td>
|
||||||
<td>Unknown</td>
|
<td>Medium</td>
|
||||||
<td>Yes</td>
|
<td>Yes</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
@ -4767,7 +4767,7 @@ Of these, **605** include live validation and **57** support direct revocation.
|
||||||
<td>Okta</td>
|
<td>Okta</td>
|
||||||
<td>Okta Domain</td>
|
<td>Okta Domain</td>
|
||||||
<td><code>kingfisher.okta.2</code></td>
|
<td><code>kingfisher.okta.2</code></td>
|
||||||
<td>Unknown</td>
|
<td>Medium</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
@ -4879,7 +4879,7 @@ Of these, **605** include live validation and **57** support direct revocation.
|
||||||
<td>Opsgenie</td>
|
<td>Opsgenie</td>
|
||||||
<td>OpsGenie API Key</td>
|
<td>OpsGenie API Key</td>
|
||||||
<td><code>kingfisher.opsgenie.1</code></td>
|
<td><code>kingfisher.opsgenie.1</code></td>
|
||||||
<td>Unknown</td>
|
<td>Medium</td>
|
||||||
<td>Yes</td>
|
<td>Yes</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
@ -5015,7 +5015,7 @@ Of these, **605** include live validation and **57** support direct revocation.
|
||||||
<td>Paypal</td>
|
<td>Paypal</td>
|
||||||
<td>PayPal OAuth Client ID</td>
|
<td>PayPal OAuth Client ID</td>
|
||||||
<td><code>kingfisher.paypal.1</code></td>
|
<td><code>kingfisher.paypal.1</code></td>
|
||||||
<td>Unknown</td>
|
<td>Medium</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
@ -5023,7 +5023,7 @@ Of these, **605** include live validation and **57** support direct revocation.
|
||||||
<td>Paypal</td>
|
<td>Paypal</td>
|
||||||
<td>PayPal OAuth Secret</td>
|
<td>PayPal OAuth Secret</td>
|
||||||
<td><code>kingfisher.paypal.2</code></td>
|
<td><code>kingfisher.paypal.2</code></td>
|
||||||
<td>Unknown</td>
|
<td>Medium</td>
|
||||||
<td>Yes</td>
|
<td>Yes</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
@ -5239,7 +5239,7 @@ Of these, **605** include live validation and **57** support direct revocation.
|
||||||
<td>Planetscale</td>
|
<td>Planetscale</td>
|
||||||
<td>PlanetScale API Token</td>
|
<td>PlanetScale API Token</td>
|
||||||
<td><code>kingfisher.planetscale.1</code></td>
|
<td><code>kingfisher.planetscale.1</code></td>
|
||||||
<td>Unknown</td>
|
<td>Medium</td>
|
||||||
<td>Yes</td>
|
<td>Yes</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
@ -5247,7 +5247,7 @@ Of these, **605** include live validation and **57** support direct revocation.
|
||||||
<td>Planetscale</td>
|
<td>Planetscale</td>
|
||||||
<td>PlanetScale Username</td>
|
<td>PlanetScale Username</td>
|
||||||
<td><code>kingfisher.planetscale.2</code></td>
|
<td><code>kingfisher.planetscale.2</code></td>
|
||||||
<td>Unknown</td>
|
<td>Medium</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
@ -5439,7 +5439,7 @@ Of these, **605** include live validation and **57** support direct revocation.
|
||||||
<td>Pubnub</td>
|
<td>Pubnub</td>
|
||||||
<td>PubNub Publish Key</td>
|
<td>PubNub Publish Key</td>
|
||||||
<td><code>kingfisher.pubnub.1</code></td>
|
<td><code>kingfisher.pubnub.1</code></td>
|
||||||
<td>Unknown</td>
|
<td>Medium</td>
|
||||||
<td>Yes</td>
|
<td>Yes</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
@ -5455,7 +5455,7 @@ Of these, **605** include live validation and **57** support direct revocation.
|
||||||
<td>Pulumi</td>
|
<td>Pulumi</td>
|
||||||
<td>Pulumi API Key</td>
|
<td>Pulumi API Key</td>
|
||||||
<td><code>kingfisher.pulumi.1</code></td>
|
<td><code>kingfisher.pulumi.1</code></td>
|
||||||
<td>Unknown</td>
|
<td>Medium</td>
|
||||||
<td>Yes</td>
|
<td>Yes</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
@ -6079,7 +6079,7 @@ Of these, **605** include live validation and **57** support direct revocation.
|
||||||
<td>Shopify</td>
|
<td>Shopify</td>
|
||||||
<td>Shopify access token</td>
|
<td>Shopify access token</td>
|
||||||
<td><code>kingfisher.shopify.1</code></td>
|
<td><code>kingfisher.shopify.1</code></td>
|
||||||
<td>Unknown</td>
|
<td>Medium</td>
|
||||||
<td>Yes</td>
|
<td>Yes</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
@ -6087,7 +6087,7 @@ Of these, **605** include live validation and **57** support direct revocation.
|
||||||
<td>Shopify</td>
|
<td>Shopify</td>
|
||||||
<td>Shopify Domain</td>
|
<td>Shopify Domain</td>
|
||||||
<td><code>kingfisher.shopify.2</code></td>
|
<td><code>kingfisher.shopify.2</code></td>
|
||||||
<td>Unknown</td>
|
<td>Medium</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
@ -6135,7 +6135,7 @@ Of these, **605** include live validation and **57** support direct revocation.
|
||||||
<td>Slack</td>
|
<td>Slack</td>
|
||||||
<td>Slack App Token</td>
|
<td>Slack App Token</td>
|
||||||
<td><code>kingfisher.slack.1</code></td>
|
<td><code>kingfisher.slack.1</code></td>
|
||||||
<td>Unknown</td>
|
<td>Medium</td>
|
||||||
<td>Yes</td>
|
<td>Yes</td>
|
||||||
<td>Yes</td>
|
<td>Yes</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
@ -6143,7 +6143,7 @@ Of these, **605** include live validation and **57** support direct revocation.
|
||||||
<td>Slack</td>
|
<td>Slack</td>
|
||||||
<td>Slack Token</td>
|
<td>Slack Token</td>
|
||||||
<td><code>kingfisher.slack.2</code></td>
|
<td><code>kingfisher.slack.2</code></td>
|
||||||
<td>Unknown</td>
|
<td>Medium</td>
|
||||||
<td>Yes</td>
|
<td>Yes</td>
|
||||||
<td>Yes</td>
|
<td>Yes</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
@ -6151,7 +6151,7 @@ Of these, **605** include live validation and **57** support direct revocation.
|
||||||
<td>Slack</td>
|
<td>Slack</td>
|
||||||
<td>Slack Webhook</td>
|
<td>Slack Webhook</td>
|
||||||
<td><code>kingfisher.slack.4</code></td>
|
<td><code>kingfisher.slack.4</code></td>
|
||||||
<td>Unknown</td>
|
<td>Medium</td>
|
||||||
<td>Yes</td>
|
<td>Yes</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
@ -6199,7 +6199,7 @@ Of these, **605** include live validation and **57** support direct revocation.
|
||||||
<td>Snyk</td>
|
<td>Snyk</td>
|
||||||
<td>Snyk API Key</td>
|
<td>Snyk API Key</td>
|
||||||
<td><code>kingfisher.snyk.1</code></td>
|
<td><code>kingfisher.snyk.1</code></td>
|
||||||
<td>Unknown</td>
|
<td>Medium</td>
|
||||||
<td>Yes</td>
|
<td>Yes</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
@ -6215,7 +6215,7 @@ Of these, **605** include live validation and **57** support direct revocation.
|
||||||
<td>Sonarcloud</td>
|
<td>Sonarcloud</td>
|
||||||
<td>SonarCloud API Token</td>
|
<td>SonarCloud API Token</td>
|
||||||
<td><code>kingfisher.sonarcloud.1</code></td>
|
<td><code>kingfisher.sonarcloud.1</code></td>
|
||||||
<td>Unknown</td>
|
<td>Medium</td>
|
||||||
<td>Yes</td>
|
<td>Yes</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
@ -6223,7 +6223,7 @@ Of these, **605** include live validation and **57** support direct revocation.
|
||||||
<td>Sonarqube</td>
|
<td>Sonarqube</td>
|
||||||
<td>SonarQube API Key</td>
|
<td>SonarQube API Key</td>
|
||||||
<td><code>kingfisher.sonarqube.1</code></td>
|
<td><code>kingfisher.sonarqube.1</code></td>
|
||||||
<td>Unknown</td>
|
<td>Medium</td>
|
||||||
<td>Yes</td>
|
<td>Yes</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
@ -6231,7 +6231,7 @@ Of these, **605** include live validation and **57** support direct revocation.
|
||||||
<td>Sonarqube</td>
|
<td>Sonarqube</td>
|
||||||
<td>SonarQube Host</td>
|
<td>SonarQube Host</td>
|
||||||
<td><code>kingfisher.sonarqube.2</code></td>
|
<td><code>kingfisher.sonarqube.2</code></td>
|
||||||
<td>Unknown</td>
|
<td>Medium</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
@ -6247,7 +6247,7 @@ Of these, **605** include live validation and **57** support direct revocation.
|
||||||
<td>Sourcegraph</td>
|
<td>Sourcegraph</td>
|
||||||
<td>Sourcegraph Access Token</td>
|
<td>Sourcegraph Access Token</td>
|
||||||
<td><code>kingfisher.sourcegraph.1</code></td>
|
<td><code>kingfisher.sourcegraph.1</code></td>
|
||||||
<td>Unknown</td>
|
<td>Medium</td>
|
||||||
<td>Yes</td>
|
<td>Yes</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
@ -6567,7 +6567,7 @@ Of these, **605** include live validation and **57** support direct revocation.
|
||||||
<td>Teamcity</td>
|
<td>Teamcity</td>
|
||||||
<td>TeamCity API Token</td>
|
<td>TeamCity API Token</td>
|
||||||
<td><code>kingfisher.teamcity.1</code></td>
|
<td><code>kingfisher.teamcity.1</code></td>
|
||||||
<td>Unknown</td>
|
<td>Medium</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
@ -6847,7 +6847,7 @@ Of these, **605** include live validation and **57** support direct revocation.
|
||||||
<td>Twilio</td>
|
<td>Twilio</td>
|
||||||
<td>Twilio API ID</td>
|
<td>Twilio API ID</td>
|
||||||
<td><code>kingfisher.twilio.1</code></td>
|
<td><code>kingfisher.twilio.1</code></td>
|
||||||
<td>Unknown</td>
|
<td>Medium</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
@ -6855,7 +6855,7 @@ Of these, **605** include live validation and **57** support direct revocation.
|
||||||
<td>Twilio</td>
|
<td>Twilio</td>
|
||||||
<td>Twilio API Key</td>
|
<td>Twilio API Key</td>
|
||||||
<td><code>kingfisher.twilio.2</code></td>
|
<td><code>kingfisher.twilio.2</code></td>
|
||||||
<td>Unknown</td>
|
<td>Medium</td>
|
||||||
<td>Yes</td>
|
<td>Yes</td>
|
||||||
<td>Yes</td>
|
<td>Yes</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
@ -6879,7 +6879,7 @@ Of these, **605** include live validation and **57** support direct revocation.
|
||||||
<td>Twitter</td>
|
<td>Twitter</td>
|
||||||
<td>Twitter Consumer Key</td>
|
<td>Twitter Consumer Key</td>
|
||||||
<td><code>kingfisher.twitter.2</code></td>
|
<td><code>kingfisher.twitter.2</code></td>
|
||||||
<td>Unknown</td>
|
<td>Medium</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
@ -6887,7 +6887,7 @@ Of these, **605** include live validation and **57** support direct revocation.
|
||||||
<td>Twitter</td>
|
<td>Twitter</td>
|
||||||
<td>X / Twitter Consumer Secret</td>
|
<td>X / Twitter Consumer Secret</td>
|
||||||
<td><code>kingfisher.twitter.3</code></td>
|
<td><code>kingfisher.twitter.3</code></td>
|
||||||
<td>Unknown</td>
|
<td>Medium</td>
|
||||||
<td>Yes</td>
|
<td>Yes</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
@ -7119,7 +7119,7 @@ Of these, **605** include live validation and **57** support direct revocation.
|
||||||
<td>Vmware</td>
|
<td>Vmware</td>
|
||||||
<td>Credentials in Connect-VIServer Invocation</td>
|
<td>Credentials in Connect-VIServer Invocation</td>
|
||||||
<td><code>kingfisher.vmware.1</code></td>
|
<td><code>kingfisher.vmware.1</code></td>
|
||||||
<td>Unknown</td>
|
<td>Medium</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
|
||||||
|
|
@ -91,8 +91,8 @@ nav:
|
||||||
- Finding Fingerprints: features/fingerprints.md
|
- Finding Fingerprints: features/fingerprints.md
|
||||||
- LLM & Agent Integration: features/agents.md
|
- LLM & Agent Integration: features/agents.md
|
||||||
- Rules:
|
- Rules:
|
||||||
- Writing Custom Rules: rules/overview.md
|
|
||||||
- Built-in Rules List: rules/builtin-rules.md
|
- Built-in Rules List: rules/builtin-rules.md
|
||||||
|
- Writing Custom Rules: rules/overview.md
|
||||||
- Reference:
|
- Reference:
|
||||||
- Architecture: reference/architecture.md
|
- Architecture: reference/architecture.md
|
||||||
- Rust Library Crates: reference/library.md
|
- Rust Library Crates: reference/library.md
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,7 @@ def load_rules():
|
||||||
|
|
||||||
name = rule.get("name", "Unknown")
|
name = rule.get("name", "Unknown")
|
||||||
rule_id = rule.get("id", "")
|
rule_id = rule.get("id", "")
|
||||||
confidence = rule.get("confidence", "unknown")
|
confidence = rule.get("confidence") or "medium"
|
||||||
has_validation = "validation" in rule
|
has_validation = "validation" in rule
|
||||||
has_revocation = "revocation" in rule
|
has_revocation = "revocation" in rule
|
||||||
is_dependent = bool(rule.get("depends_on_rule"))
|
is_dependent = bool(rule.get("depends_on_rule"))
|
||||||
|
|
|
||||||
|
|
@ -43,14 +43,19 @@ pub fn load_baseline(path: &Path) -> Result<BaselineFile> {
|
||||||
/// or the 16-char zero-padded hex form previously written by `--manage-baseline`.
|
/// or the 16-char zero-padded hex form previously written by `--manage-baseline`.
|
||||||
/// Detection:
|
/// Detection:
|
||||||
/// 1. A `0x`/`0X` prefix is stripped and the rest parsed as hex.
|
/// 1. A `0x`/`0X` prefix is stripped and the rest parsed as hex.
|
||||||
/// 2. Exactly 16 characters of `[0-9a-fA-F]` are parsed as hex (legacy canonical form).
|
/// 2. Exactly 16 hex chars containing at least one `a-f`/`A-F` letter are parsed as hex
|
||||||
|
/// (legacy canonical form). An all-digit 16-char string is ambiguous and is treated
|
||||||
|
/// as decimal so that decimal fingerprints from scan output round-trip correctly.
|
||||||
/// 3. Otherwise the string is parsed as decimal u64.
|
/// 3. Otherwise the string is parsed as decimal u64.
|
||||||
fn parse_fingerprint(s: &str) -> Option<u64> {
|
fn parse_fingerprint(s: &str) -> Option<u64> {
|
||||||
let trimmed = s.trim();
|
let trimmed = s.trim();
|
||||||
if let Some(rest) = trimmed.strip_prefix("0x").or_else(|| trimmed.strip_prefix("0X")) {
|
if let Some(rest) = trimmed.strip_prefix("0x").or_else(|| trimmed.strip_prefix("0X")) {
|
||||||
return u64::from_str_radix(rest, 16).ok();
|
return u64::from_str_radix(rest, 16).ok();
|
||||||
}
|
}
|
||||||
if trimmed.len() == 16 && trimmed.chars().all(|c| c.is_ascii_hexdigit()) {
|
if trimmed.len() == 16
|
||||||
|
&& trimmed.chars().all(|c| c.is_ascii_hexdigit())
|
||||||
|
&& trimmed.chars().any(|c| c.is_ascii_alphabetic())
|
||||||
|
{
|
||||||
return u64::from_str_radix(trimmed, 16).ok();
|
return u64::from_str_radix(trimmed, 16).ok();
|
||||||
}
|
}
|
||||||
trimmed.parse::<u64>().ok()
|
trimmed.parse::<u64>().ok()
|
||||||
|
|
@ -370,7 +375,10 @@ mod tests {
|
||||||
fs::write(&file_hex, "dummy")?;
|
fs::write(&file_hex, "dummy")?;
|
||||||
fs::write(&file_dec, "dummy")?;
|
fs::write(&file_dec, "dummy")?;
|
||||||
let baseline_path = tmp.path().join("baseline.yaml");
|
let baseline_path = tmp.path().join("baseline.yaml");
|
||||||
let fp_hex = 0x1111_2222_3333_4444_u64;
|
// fp_hex must contain at least one hex letter so its 16-char hex form is
|
||||||
|
// unambiguously hex (an all-digit 16-char string is treated as decimal to
|
||||||
|
// satisfy the roundtrip contract for fingerprints copied from scan output).
|
||||||
|
let fp_hex = 0x1a2b_3c4d_5e6f_7890_u64;
|
||||||
let fp_dec = 0xaaaa_bbbb_cccc_dddd_u64;
|
let fp_dec = 0xaaaa_bbbb_cccc_dddd_u64;
|
||||||
|
|
||||||
let mixed = BaselineFile {
|
let mixed = BaselineFile {
|
||||||
|
|
|
||||||
4
testdata/parsers/scan_findings_baseline.json
vendored
4
testdata/parsers/scan_findings_baseline.json
vendored
|
|
@ -141,7 +141,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"rule_id": "kingfisher.stripe.1",
|
"rule_id": "kingfisher.stripe.1",
|
||||||
"snippet": "pk_live_bu9JFVJtII3FINL1rOKcNpveXD4hSMtSDx7opOWDEFGHIJKLMNOPQRSTUVWX"
|
"snippet": "pk_live_bu9JFVJtII3FINL1rOKcNpveXD4hSMtSDx7opOWDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"rule_id": "kingfisher.stripe.2",
|
"rule_id": "kingfisher.stripe.2",
|
||||||
|
|
@ -149,7 +149,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"rule_id": "kingfisher.stripe.2",
|
"rule_id": "kingfisher.stripe.2",
|
||||||
"snippet": "sk_live_bu9JFVJtII3FINL1rOKcNpveXD4hSMtSDx7opOWDEFGHIJKLMNOPQRST"
|
"snippet": "sk_live_bu9JFVJtII3FINL1rOKcNpveXD4hSMtSDx7opOWDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"rule_id": "kingfisher.twilio.2",
|
"rule_id": "kingfisher.twilio.2",
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue