Files
keyFinder/js/background.js
moamen b73c2185b0 v2.0.0: Complete rewrite - Manifest V3, enterprise-grade secret detection
- Migrated to Chrome Manifest V3 with service worker architecture
- 80+ secret detection patterns covering AWS, GCP, Azure, GitHub, GitLab,
  Stripe, Slack, Discord, OpenAI, and 30+ other providers
- 10 scanning surfaces: inline scripts, external scripts, meta tags,
  hidden inputs, data attributes, HTML comments, URL params, web storage,
  cookies, and network response interception
- Shannon entropy analysis for detecting undocumented secret formats
- MAIN world interceptor for XHR/fetch response scanning and window globals
- Professional dark-theme UI with filtering, search, and CSV/JSON export
- Zero dependencies - removed jQuery, Bootstrap, font-awesome, popper
- Proper XSS-safe DOM rendering throughout
- Badge counter on extension icon showing finding count
- All frames scanning including iframes
2026-04-07 18:22:42 +02:00

104 lines
3.3 KiB
JavaScript

const KEYWORDS_KEY = "kf_keywords";
const FINDINGS_KEY = "kf_findings";
const DEFAULT_KEYWORDS = [
"key", "api_key", "apikey", "api-key", "secret", "token",
"access_token", "auth", "credential", "password",
"client_id", "client_secret"
];
chrome.runtime.onInstalled.addListener(async (details) => {
if (details.reason === "install") {
await chrome.storage.local.set({
[KEYWORDS_KEY]: DEFAULT_KEYWORDS,
[FINDINGS_KEY]: []
});
}
});
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
if (request.type === "finding") {
saveFinding(request.data).then(() => sendResponse({ ok: true }));
return true;
}
if (request.type === "getKeywords") {
getKeywords().then((keywords) => sendResponse({ keywords }));
return true;
}
if (request.type === "getFindings") {
getFindings().then((findings) => sendResponse({ findings }));
return true;
}
if (request.type === "addKeyword") {
addKeyword(request.keyword).then((result) => sendResponse(result));
return true;
}
if (request.type === "removeKeyword") {
removeKeyword(request.keyword).then(() => sendResponse({ ok: true }));
return true;
}
if (request.type === "removeFinding") {
removeFinding(request.url).then(() => sendResponse({ ok: true }));
return true;
}
if (request.type === "clearFindings") {
clearFindings().then(() => sendResponse({ ok: true }));
return true;
}
if (request.type === "exportFindings") {
getFindings().then((findings) => sendResponse({ findings }));
return true;
}
});
async function getKeywords() {
const result = await chrome.storage.local.get(KEYWORDS_KEY);
return result[KEYWORDS_KEY] || DEFAULT_KEYWORDS;
}
async function addKeyword(keyword) {
const keywords = await getKeywords();
const normalized = keyword.trim().toLowerCase();
if (!normalized) return { ok: false, error: "Keyword cannot be empty." };
if (keywords.includes(normalized)) return { ok: false, error: "Keyword already exists." };
keywords.push(normalized);
await chrome.storage.local.set({ [KEYWORDS_KEY]: keywords });
return { ok: true };
}
async function removeKeyword(keyword) {
const keywords = await getKeywords();
await chrome.storage.local.set({ [KEYWORDS_KEY]: keywords.filter((k) => k !== keyword) });
}
async function getFindings() {
const result = await chrome.storage.local.get(FINDINGS_KEY);
return result[FINDINGS_KEY] || [];
}
async function saveFinding(finding) {
const findings = await getFindings();
const isDuplicate = findings.some(
(f) => f.url === finding.url && f.match === finding.match
);
if (isDuplicate) return;
findings.push(finding);
await chrome.storage.local.set({ [FINDINGS_KEY]: findings });
const badgeCount = findings.length;
chrome.action.setBadgeText({ text: badgeCount > 0 ? String(badgeCount) : "" });
chrome.action.setBadgeBackgroundColor({ color: "#e74c3c" });
}
async function removeFinding(url) {
const findings = await getFindings();
const updated = findings.filter((f) => f.url !== url);
await chrome.storage.local.set({ [FINDINGS_KEY]: updated });
chrome.action.setBadgeText({ text: updated.length > 0 ? String(updated.length) : "" });
}
async function clearFindings() {
await chrome.storage.local.set({ [FINDINGS_KEY]: [] });
chrome.action.setBadgeText({ text: "" });
}