Skip to content

Commit

Permalink
Merge pull request #728 from ninoseki/disable-scanners
Browse files Browse the repository at this point in the history
feat: disable scanners (#713)
  • Loading branch information
ninoseki authored Apr 23, 2023
2 parents b15d673 + 919eac6 commit a56e9e2
Show file tree
Hide file tree
Showing 9 changed files with 148 additions and 62 deletions.
178 changes: 124 additions & 54 deletions src/options/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,17 @@ import "bulma/css/bulma.css";
import { defineComponent, onMounted, ref, watchEffect } from "vue";
import { Scanners } from "../scanner";
import { Searchers } from "../searcher";
import { getOptions, setOptions } from "../storage";
import type { Options, SearchableType, Searcher } from "../types";
import { SEARCHABLE_TYPES } from "../types";
import type {
Options,
ScannableType,
Scanner,
SearchableType,
Searcher,
} from "../types";
import { SCANNABLE_TYPES, SEARCHABLE_TYPES } from "../types";
import { getFaviconURL } from "../utils";
export default defineComponent({
Expand All @@ -25,8 +32,10 @@ export default defineComponent({
const virusTotalAPIKey = ref<string | undefined>(undefined);
const disabledSearcherNames = ref<string[]>([]);
const disabledScannerNames = ref<string[]>([]);
const searchableType = ref<SearchableType | undefined>(undefined);
const scannableType = ref<ScannableType | undefined>(undefined);
onMounted(async () => {
const options = await getOptions();
Expand All @@ -42,6 +51,7 @@ export default defineComponent({
virusTotalAPIKey.value = options.virusTotalAPIKey;
disabledSearcherNames.value = options.disabledSearcherNames;
disabledScannerNames.value = options.disabledScannerNames;
isInitialized.value = true;
});
Expand All @@ -50,6 +60,10 @@ export default defineComponent({
return !disabledSearcherNames.value.includes(name);
};
const isEnabledScanner = (name: string): boolean => {
return !disabledScannerNames.value.includes(name);
};
const disableOrEnableSearcher = (name: string): void => {
if (disabledSearcherNames.value.includes(name)) {
disabledSearcherNames.value = disabledSearcherNames.value.filter(
Expand All @@ -60,6 +74,16 @@ export default defineComponent({
}
};
const disableOrEnableScanner = (name: string): void => {
if (disabledScannerNames.value.includes(name)) {
disabledScannerNames.value = disabledScannerNames.value.filter(
(n) => n !== name
);
} else {
disabledScannerNames.value.push(name);
}
};
const selectSearchableType = (selected: SearchableType): void => {
if (selected == searchableType.value) {
searchableType.value = undefined;
Expand All @@ -68,13 +92,28 @@ export default defineComponent({
}
};
const isSelected = (searcher: Searcher): boolean => {
const selectScannableType = (selected: ScannableType): void => {
if (selected == scannableType.value) {
scannableType.value = undefined;
} else {
scannableType.value = selected;
}
};
const isSelectedSearcher = (searcher: Searcher): boolean => {
if (searchableType.value !== undefined) {
return searcher.supportedTypes.includes(searchableType.value);
}
return true;
};
const isSelectedScanner = (scanner: Scanner): boolean => {
if (scannableType.value !== undefined) {
return scanner.supportedTypes.includes(scannableType.value);
}
return true;
};
watchEffect(async () => {
if (!isInitialized.value) {
// do nothing if it is not initialized
Expand All @@ -88,6 +127,7 @@ export default defineComponent({
enableRefang: enableRefang.value,
preferHrefValue: preferHrefValue.value,
disabledSearcherNames: disabledSearcherNames.value.map((n) => n),
disabledScannerNames: disabledScannerNames.value.map((n) => n),
hybridAnalysisAPIKey: hybridAnalysisAPIKey.value,
urlscanAPIKey: urlscanAPIKey.value,
virusTotalAPIKey: virusTotalAPIKey.value,
Expand All @@ -102,16 +142,23 @@ export default defineComponent({
hybridAnalysisAPIKey,
isInitialized,
preferHrefValue,
SCANNABLE_TYPES,
scannableType,
Scanners,
SEARCHABLE_TYPES,
searchableType,
Searchers,
strictTLD,
searchableType,
urlscanAPIKey,
virusTotalAPIKey,
SEARCHABLE_TYPES,
disableOrEnableScanner,
disableOrEnableSearcher,
getFaviconURL,
isEnabledScanner,
isEnabledSearcher,
isSelected,
isSelectedScanner,
isSelectedSearcher,
selectScannableType,
selectSearchableType,
};
},
Expand All @@ -128,7 +175,7 @@ export default defineComponent({
<div class="content">
<ul>
<li><a href="#general">General</a></li>
<li><a href="#api-keys">API keys</a></li>
<li><a href="#scanners">Scanners</a></li>
<li><a href="#searchers">Searchers</a></li>
</ul>
</div>
Expand Down Expand Up @@ -200,56 +247,79 @@ export default defineComponent({
</div>
</div>

<div class="box" id="api-keys">
<h2 class="title is-2">API key settings</h2>
<div class="field">
<label class="label">
<span class="icon">
<img
src="https://t1.gstatic.com/faviconV2?client=SOCIAL&type=FAVICON&fallback_opts=TYPE,SIZE,URL&url=https://www.hybrid-analysis.com&size=16"
/>
</span>
<span>
<a href="https://www.hybrid-analysis.com">HybridAnalysis</a>
API Key
</span>
</label>
<div class="control">
<input
type="text"
class="input"
v-model="hybridAnalysisAPIKey"
/>
</div>
<div class="box" id="scanners">
<h2 class="title is-2">Scanner settings</h2>
<div class="tags">
<span
class="tag is-info is-light"
@click="selectScannableType(tag)"
v-for="tag in SCANNABLE_TYPES"
:key="tag"
>
{{ tag }}
<span
class="delete is-small"
v-if="scannableType === tag"
></span>
</span>
</div>
<div class="field">
<label class="label">
<span class="icon">
<img
src="https://t1.gstatic.com/faviconV2?client=SOCIAL&type=FAVICON&fallback_opts=TYPE,SIZE,URL&url=https://urlscan.io&size=16"
<div v-for="(scanner, index) in Scanners" :key="index">
<div
class="searcher field has-addons"
v-if="isSelectedScanner(scanner)"
>
<div class="control is-expanded">
<label class="label">
<span class="icon">
<img :src="getFaviconURL(scanner.baseURL)" />
</span>
<span
><a :href="scanner.baseURL" target="_blank">{{
scanner.name
}}</a></span
>
</label>
<p class="tags">
<strong class="mr-1">Supported types:</strong>
<span
class="tag is-info is-light"
v-for="(supportedType, index) in scanner.supportedTypes"
:key="index"
>
{{ supportedType }}
</span>
</p>
</div>
<div class="control">
<input
type="checkbox"
:checked="isEnabledScanner(scanner.name)"
@click="disableOrEnableScanner(scanner.name)"
/>
</span>
<span>
<a href="https://urlscan.io">urlscan.io</a> API Key
</span>
</label>
<div class="control">
<input type="text" class="input" v-model="urlscanAPIKey" />
<label>Enable</label>
</div>
</div>
</div>
<div class="field">
<label class="label">
<span class="icon">
<img
src="https://t1.gstatic.com/faviconV2?client=SOCIAL&type=FAVICON&fallback_opts=TYPE,SIZE,URL&url=https://www.virustotal.com&size=16"
<div class="field">
<div class="control" v-if="scanner.hasAPIKey">
<input
type="text"
class="input"
v-model="virusTotalAPIKey"
v-if="scanner.name === 'VirusTotal'"
/>
</span>
<span>
<a href="https://www.virustotal.com">VirusTotal</a> API Key
</span>
</label>
<div class="control">
<input type="text" class="input" v-model="virusTotalAPIKey" />
<input
type="text"
class="input"
v-model="urlscanAPIKey"
v-if="scanner.name === 'urlscan.io'"
/>
<input
type="text"
class="input"
v-model="hybridAnalysisAPIKey"
v-if="scanner.name === 'HybridAnalysis'"
/>
</div>
</div>
</div>
</div>
Expand All @@ -274,7 +344,7 @@ export default defineComponent({
<div v-for="(searcher, index) in Searchers" :key="index">
<div
class="searcher field has-addons"
v-if="isSelected(searcher)"
v-if="isSelectedSearcher(searcher)"
>
<div class="control is-expanded">
<label class="label">
Expand Down
7 changes: 4 additions & 3 deletions src/scanner/browserling.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ export class Browserling implements Scanner {
public baseURL: string;
public name: string;
public supportedTypes: ScannableType[] = ["url"];
public apiKey: string | undefined = undefined;
public hasAPIKey = false;

public constructor() {
this.baseURL = "https://www.browserling.com";
Expand All @@ -18,8 +20,7 @@ export class Browserling implements Scanner {
);
}

// eslint-disable-next-line @typescript-eslint/no-unused-vars
public setAPIKey(_: string | undefined): void {
return;
public setAPIKey(apiKey: string | undefined): void {
this.apiKey = apiKey;
}
}
3 changes: 2 additions & 1 deletion src/scanner/hybridanalysis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ export class HybridAnalysis implements Scanner {
public baseURL: string;
public name: string;
public supportedTypes: ScannableType[] = ["url"];
protected apiKey: string | undefined;
public apiKey: string | undefined;
public hasAPIKey = true;

public constructor() {
this.baseURL = "https://www.hybrid-analysis.com/api/v2";
Expand Down
3 changes: 2 additions & 1 deletion src/scanner/urlscan.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ export class URLScan implements Scanner {
public baseURL: string;
public name: string;
public supportedTypes: ScannableType[] = ["ip", "domain", "url"];
protected apiKey: string | undefined;
public apiKey: string | undefined;
public hasAPIKey = true;

public constructor() {
this.baseURL = "https://urlscan.io/api/v1";
Expand Down
3 changes: 2 additions & 1 deletion src/scanner/virustotal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ export class VirusTotal implements Scanner {
public baseURL: string;
public name: string;
public supportedTypes: ScannableType[] = ["url"];
protected apiKey: string | undefined;
public apiKey: string | undefined;
public hasAPIKey = true;

public constructor() {
this.baseURL = "https://www.virustotal.com/api/v3";
Expand Down
1 change: 1 addition & 0 deletions src/schemas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export const OptionsSchema = z.object({
enableDebugLog: z.boolean().default(false),
preferHrefValue: z.boolean().default(true),
disabledSearcherNames: z.array(z.string()).default([]),
disabledScannerNames: z.array(z.string()).default([]),
hybridAnalysisAPIKey: z.string().optional(),
urlscanAPIKey: z.string().optional(),
virusTotalAPIKey: z.string().optional(),
Expand Down
7 changes: 6 additions & 1 deletion src/selector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export class Selector {
protected input: string;
protected options: SelectorOptions;

protected scanners: Scanner[] = Scanners;
protected scanners: Scanner[];
protected searchers: Searcher[];

public constructor(
Expand All @@ -44,6 +44,7 @@ export class Selector {
enableRefang: true,
enableDebugLog: true,
disabledSearcherNames: [],
disabledScannerNames: [],
}
) {
this.input = options.enableRefang ? refang(input) : input;
Expand All @@ -52,6 +53,10 @@ export class Selector {
this.searchers = Searchers.filter(
(s) => !this.options.disabledSearcherNames.includes(s.name)
);

this.scanners = Scanners.filter(
(s) => !this.options.disabledScannerNames.includes(s.name)
);
}

public getIP(): string | null {
Expand Down
7 changes: 6 additions & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ export const SEARCHABLE_TYPES: SearchableType[] = [
"url",
];

export const SCANNABLE_TYPES: ScannableType[] = ["domain", "ip", "url"];

export interface Searcher {
baseURL: string;
name: string;
Expand All @@ -50,10 +52,12 @@ export interface Scanner {
baseURL: string;
name: string;
supportedTypes: ScannableType[];
apiKey?: string;
hasAPIKey: boolean;
setAPIKey(apiKey: string | undefined): void;
scanByIP?(query: string): Promise<string>;
scanByDomain?(query: string): Promise<string>;
scanByURL?(query: string): Promise<string> | string;
setAPIKey(apiKey: string | undefined): void;
}

export interface SearchFuncWrapper {
Expand Down Expand Up @@ -107,6 +111,7 @@ export interface SelectorOptions {
enableRefang: boolean;
enableDebugLog: boolean;
disabledSearcherNames: string[];
disabledScannerNames: string[];
}

export interface Options extends SelectorOptions {
Expand Down
Loading

0 comments on commit a56e9e2

Please sign in to comment.