SaiBon99 commited on
Commit
6a346d8
·
1 Parent(s): 1e3001a

Rename configuration and content files for improved project structure

Browse files
{gitpage → docs}/.gitignore RENAMED
File without changes
{gitpage → docs}/_config.yml RENAMED
File without changes
{gitpage → docs}/images/confusion_matrix.png RENAMED
File without changes
{gitpage → docs}/images/feature_drift.png RENAMED
File without changes
{gitpage → docs}/images/performance_over_time.png RENAMED
File without changes
{gitpage → docs}/index.md RENAMED
File without changes
docs/sample_urlscan_result.json DELETED
@@ -1,488 +0,0 @@
1
- {
2
- "data": {
3
- "requests": [
4
- {
5
- "request": {
6
- "requestId": "FE77961E144ADAA2A7D7760E8CE7EB6A",
7
- "loaderId": "FE77961E144ADAA2A7D7760E8CE7EB6A",
8
- "documentURL": "https://example.com/",
9
- "request": {
10
- "url": "https://example.com/",
11
- "method": "GET",
12
- "headers": {
13
- "Upgrade-Insecure-Requests": "1",
14
- "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36"
15
- },
16
- "mixedContentType": "none",
17
- "initialPriority": "VeryHigh",
18
- "referrerPolicy": "strict-origin-when-cross-origin",
19
- "isSameSite": true
20
- },
21
- "timestamp": 34065601.895598,
22
- "wallTime": 1766933427.494116,
23
- "initiator": {
24
- "type": "other"
25
- },
26
- "redirectHasExtraInfo": false,
27
- "type": "Document",
28
- "frameId": "61B9C1B13CBD0AC8E19A4CB13D24DE8E",
29
- "hasUserGesture": false,
30
- "primaryRequest": true
31
- },
32
- "response": {
33
- "encodedDataLength": 536,
34
- "dataLength": 513,
35
- "requestId": "FE77961E144ADAA2A7D7760E8CE7EB6A",
36
- "type": "Document",
37
- "response": {
38
- "url": "https://example.com/",
39
- "status": 200,
40
- "statusText": "",
41
- "headers": {
42
- "age": "13121",
43
- "allow": "GET, HEAD",
44
- "cf-cache-status": "HIT",
45
- "cf-ray": "9b51dec2092c3738-FRA",
46
- "content-encoding": "gzip",
47
- "content-type": "text/html",
48
- "date": "Sun, 28 Dec 2025 14:50:27 GMT",
49
- "last-modified": "Sat, 20 Dec 2025 05:43:40 GMT",
50
- "server": "cloudflare",
51
- "vary": "Accept-Encoding"
52
- },
53
- "mimeType": "text/html",
54
- "charset": "",
55
- "remoteIPAddress": "104.18.27.120",
56
- "remotePort": 443,
57
- "encodedDataLength": 536,
58
- "timing": {
59
- "requestTime": 34065601.895873,
60
- "proxyStart": -1,
61
- "proxyEnd": -1,
62
- "dnsStart": 0,
63
- "dnsEnd": 5.906,
64
- "connectStart": 5.942,
65
- "connectEnd": 25.448,
66
- "sslStart": 11.119,
67
- "sslEnd": 25.442,
68
- "workerStart": -1,
69
- "workerReady": -1,
70
- "workerFetchStart": -1,
71
- "workerRespondWithSettled": -1,
72
- "sendStart": 25.509,
73
- "sendEnd": 25.562,
74
- "pushStart": 0,
75
- "pushEnd": 0,
76
- "receiveHeadersStart": 83.246,
77
- "receiveHeadersEnd": 84.37
78
- },
79
- "responseTime": 1766933427577.645,
80
- "protocol": "h2",
81
- "alternateProtocolUsage": "unspecifiedReason",
82
- "securityState": "secure",
83
- "securityDetails": {
84
- "protocol": "TLS 1.3",
85
- "keyExchange": "",
86
- "keyExchangeGroup": "X25519MLKEM768",
87
- "cipher": "AES_128_GCM",
88
- "certificateId": 0,
89
- "subjectName": "example.com",
90
- "sanList": [
91
- "example.com",
92
- "*.example.com"
93
- ],
94
- "issuer": "Cloudflare TLS Issuing ECC CA 3",
95
- "validFrom": 1765913972,
96
- "validTo": 1773685964,
97
- "signedCertificateTimestampList": [
98
- {
99
- "status": "Verified",
100
- "origin": "Embedded in certificate",
101
- "logDescription": "DigiCert 'Wyvern2026h1'",
102
- "logId": "6411C46CA412ECA7891CA2022E00BCAB4F2807D41E3527ABEAFED503C97DCDF0",
103
- "timestamp": 1765914573355,
104
- "hashAlgorithm": "SHA-256",
105
- "signatureAlgorithm": "ECDSA",
106
- "signatureData": "304502207EAD9214E5E3A94FD2FFFC3AACE657456FE8357607018CE2D8B75E80D14359C5022100F3A4736BB259749EB4EBF22271E5F29F15688F2193F659FC0AE7A3C2A9C4BF41"
107
- },
108
- {
109
- "status": "Verified",
110
- "origin": "Embedded in certificate",
111
- "logDescription": "Cloudflare 'Nimbus2026'",
112
- "logId": "CB38F715897C84A1445F5BC1DDFBC96EF29A59CD470A690585B0CB14C31458E7",
113
- "timestamp": 1765914573388,
114
- "hashAlgorithm": "SHA-256",
115
- "signatureAlgorithm": "ECDSA",
116
- "signatureData": "304402207CB577326AA9CEE312D5B03DE9930181A98958F77CB911850DF269CD39D1A09802201A31F3B9B9AA2A3010320E38E619B3EE5D1F998FED2CAEC05CB9EBFEE5C1C36A"
117
- },
118
- {
119
- "status": "Verified",
120
- "origin": "TLS extension",
121
- "logDescription": "Google 'Xenon2026h1' log",
122
- "logId": "969764BF555897ADF743876837084277E9F03AD5F6A4F3366E46A43F0FCAA9C6",
123
- "timestamp": 1765914576543,
124
- "hashAlgorithm": "SHA-256",
125
- "signatureAlgorithm": "ECDSA",
126
- "signatureData": "304402203CB5BE0CE4168D2F0F81BC896F518D7FF7EFF8B7BA72448C6B7C46DC6056CB15022055BAA26FBD349EADFA9B314204B5BA049E669BDDF386CA4F2B126BE27EDA183A"
127
- },
128
- {
129
- "status": "Verified",
130
- "origin": "TLS extension",
131
- "logDescription": "Google 'Argon2026h1' log",
132
- "logId": "0E5794BCF3AEA93E331B2C9907B3F790DF9BC23D713225DD21A925AC61C54E21",
133
- "timestamp": 1765914576444,
134
- "hashAlgorithm": "SHA-256",
135
- "signatureAlgorithm": "ECDSA",
136
- "signatureData": "3046022100A9914FC1A2559979D8351623D4CD7C8B3D52F29F9C3E816E59E0E7617DF21E9F022100B34E0A80A3547FF2DEEBE9A3A3E33ED211C23255A03A2F415750DCB2B02BC424"
137
- }
138
- ],
139
- "certificateTransparencyCompliance": "compliant",
140
- "serverSignatureAlgorithm": 1027,
141
- "encryptedClientHello": false
142
- },
143
- "isIpProtectionUsed": false
144
- },
145
- "hasExtraInfo": true,
146
- "hash": "6f5635035f36ad500b4fc4bb7816bb72ef5594e1bcae44fa074c5e988fc4c0fe",
147
- "size": 513,
148
- "asn": {
149
- "ip": "104.18.27.120",
150
- "asn": "13335",
151
- "country": "US",
152
- "description": "CLOUDFLARENET, US",
153
- "name": "CLOUDFLARENET",
154
- "route": "104.16.0.0/14"
155
- },
156
- "geoip": {
157
- "country": "",
158
- "region": "",
159
- "timezone": "",
160
- "city": "",
161
- "ll": [
162
- null,
163
- null
164
- ],
165
- "country_name": "Ascension Island"
166
- }
167
- }
168
- }
169
- ],
170
- "cookies": [],
171
- "console": [],
172
- "links": [
173
- {
174
- "href": "https://iana.org/domains/example",
175
- "text": "Learn more",
176
- "frameId": "61B9C1B13CBD0AC8E19A4CB13D24DE8E"
177
- }
178
- ],
179
- "timing": {
180
- "beginNavigation": "2025-12-28T14:50:27.492Z",
181
- "frameStartedLoading": "2025-12-28T14:50:27.493Z",
182
- "frameNavigated": "2025-12-28T14:50:27.581Z",
183
- "domContentEventFired": "2025-12-28T14:50:27.593Z",
184
- "frameStoppedLoading": "2025-12-28T14:50:27.595Z"
185
- },
186
- "globals": []
187
- },
188
- "lists": {
189
- "ips": [
190
- "104.18.27.120"
191
- ],
192
- "countries": [],
193
- "asns": [
194
- "13335"
195
- ],
196
- "domains": [
197
- "example.com"
198
- ],
199
- "servers": [
200
- "cloudflare"
201
- ],
202
- "urls": [
203
- "https://example.com/"
204
- ],
205
- "linkDomains": [
206
- "iana.org"
207
- ],
208
- "certificates": [
209
- {
210
- "subjectName": "example.com",
211
- "issuer": "Cloudflare TLS Issuing ECC CA 3",
212
- "validFrom": 1765913972,
213
- "validTo": 1773685964
214
- }
215
- ],
216
- "hashes": [
217
- "6f5635035f36ad500b4fc4bb7816bb72ef5594e1bcae44fa074c5e988fc4c0fe"
218
- ]
219
- },
220
- "meta": {
221
- "processors": {
222
- "umbrella": {
223
- "data": [
224
- {
225
- "hostname": "example.com",
226
- "rank": 6940
227
- }
228
- ]
229
- },
230
- "geoip": {
231
- "data": [
232
- {
233
- "ip": "104.18.27.120",
234
- "geoip": {
235
- "country": "",
236
- "region": "",
237
- "timezone": "",
238
- "city": "",
239
- "ll": [
240
- null,
241
- null
242
- ],
243
- "country_name": "Ascension Island"
244
- }
245
- }
246
- ]
247
- },
248
- "asn": {
249
- "data": [
250
- {
251
- "ip": "104.18.27.120",
252
- "asn": "13335",
253
- "country": "US",
254
- "description": "CLOUDFLARENET, US",
255
- "name": "CLOUDFLARENET",
256
- "route": "104.16.0.0/14"
257
- }
258
- ]
259
- },
260
- "rdns": {
261
- "data": []
262
- },
263
- "wappa": {
264
- "data": []
265
- }
266
- }
267
- },
268
- "page": {
269
- "asn": "AS13335",
270
- "asnname": "CLOUDFLARENET, US",
271
- "city": "",
272
- "country": "",
273
- "domain": "example.com",
274
- "ip": "104.18.27.120",
275
- "server": "cloudflare",
276
- "url": "https://example.com/",
277
- "apexDomainAgeDays": 4034,
278
- "language": "en",
279
- "mimeType": "text/html",
280
- "title": "Example Domain",
281
- "tlsValidDays": 89,
282
- "tlsAgeDays": 11,
283
- "domainAgeDays": 4034,
284
- "tlsValidFrom": "2025-12-16T19:39:32.000Z",
285
- "umbrellaRank": 6940,
286
- "apexDomain": "example.com",
287
- "tlsIssuer": "Cloudflare TLS Issuing ECC CA 3",
288
- "status": "200"
289
- },
290
- "scanner": {
291
- "country": "de"
292
- },
293
- "stats": {
294
- "IPv6Percentage": 0,
295
- "adBlocked": 0,
296
- "domainStats": [
297
- {
298
- "count": 1,
299
- "ips": [
300
- "104.18.27.120"
301
- ],
302
- "domain": "example.com",
303
- "size": 513,
304
- "encodedSize": 536,
305
- "countries": [],
306
- "index": 0,
307
- "initiators": [],
308
- "redirects": 0
309
- }
310
- ],
311
- "ipStats": [
312
- {
313
- "requests": 1,
314
- "domains": [
315
- "example.com"
316
- ],
317
- "ip": "104.18.27.120",
318
- "asn": {
319
- "ip": "104.18.27.120",
320
- "asn": "13335",
321
- "country": "US",
322
- "description": "CLOUDFLARENET, US",
323
- "name": "CLOUDFLARENET",
324
- "route": "104.16.0.0/14"
325
- },
326
- "dns": {},
327
- "geoip": {
328
- "country": "",
329
- "region": "",
330
- "timezone": "",
331
- "city": "",
332
- "ll": [
333
- null,
334
- null
335
- ],
336
- "country_name": "Ascension Island"
337
- },
338
- "size": 513,
339
- "encodedSize": 536,
340
- "countries": [],
341
- "index": 0,
342
- "ipv6": false,
343
- "redirects": 0,
344
- "count": null
345
- }
346
- ],
347
- "malicious": 0,
348
- "protocolStats": [
349
- {
350
- "count": 1,
351
- "size": 513,
352
- "encodedSize": 536,
353
- "ips": [
354
- "104.18.27.120"
355
- ],
356
- "countries": [],
357
- "securityState": {},
358
- "protocol": "h2"
359
- }
360
- ],
361
- "regDomainStats": [
362
- {
363
- "count": 1,
364
- "ips": [
365
- "104.18.27.120"
366
- ],
367
- "regDomain": "example.com",
368
- "size": 513,
369
- "encodedSize": 536,
370
- "countries": [],
371
- "index": 0,
372
- "subDomains": [
373
- {
374
- "domain": "",
375
- "country": ""
376
- }
377
- ],
378
- "redirects": 0
379
- }
380
- ],
381
- "resourceStats": [
382
- {
383
- "count": 1,
384
- "size": 513,
385
- "encodedSize": 536,
386
- "latency": 0,
387
- "countries": [],
388
- "ips": [
389
- "104.18.27.120"
390
- ],
391
- "type": "Document",
392
- "compression": "1.0",
393
- "percentage": 100
394
- }
395
- ],
396
- "securePercentage": 100,
397
- "secureRequests": 1,
398
- "serverStats": [
399
- {
400
- "count": 1,
401
- "size": 513,
402
- "encodedSize": 536,
403
- "ips": [
404
- "104.18.27.120"
405
- ],
406
- "countries": [],
407
- "server": "cloudflare"
408
- }
409
- ],
410
- "tlsStats": [
411
- {
412
- "count": 1,
413
- "size": 513,
414
- "encodedSize": 536,
415
- "ips": [
416
- "104.18.27.120"
417
- ],
418
- "countries": [],
419
- "protocols": {
420
- "TLS 1.3 / / AES_128_GCM": 1
421
- },
422
- "securityState": "secure"
423
- }
424
- ],
425
- "totalLinks": 1,
426
- "uniqCountries": 1
427
- },
428
- "submitter": {
429
- "country": "SE"
430
- },
431
- "task": {
432
- "method": "api",
433
- "source": "b1c2f290",
434
- "tags": [],
435
- "time": "2025-12-28T14:50:32.844Z",
436
- "url": "https://example.com/",
437
- "uuid": "019b6570-74f7-7269-aa5a-48da029c142c",
438
- "visibility": "public",
439
- "reportURL": "https://urlscan.io/result/019b6570-74f7-7269-aa5a-48da029c142c/",
440
- "screenshotURL": "https://urlscan.io/screenshots/019b6570-74f7-7269-aa5a-48da029c142c.png",
441
- "domURL": "https://urlscan.io/dom/019b6570-74f7-7269-aa5a-48da029c142c/",
442
- "domain": "example.com",
443
- "apexDomain": "example.com"
444
- },
445
- "verdicts": {
446
- "overall": {
447
- "score": 0,
448
- "categories": [],
449
- "brands": [],
450
- "tags": [],
451
- "malicious": false,
452
- "hasVerdicts": true
453
- },
454
- "urlscan": {
455
- "score": 0,
456
- "categories": [],
457
- "brands": [],
458
- "tags": [],
459
- "malicious": false,
460
- "hasVerdicts": false
461
- },
462
- "engines": {
463
- "score": -100,
464
- "malicious": false,
465
- "categories": [],
466
- "enginesTotal": 0,
467
- "maliciousTotal": 0,
468
- "benignTotal": 0,
469
- "maliciousVerdicts": [],
470
- "benignVerdicts": [],
471
- "hasVerdicts": true,
472
- "tags": [
473
- "urlscan-ml",
474
- "urlscan-ml-0.1.0-1-d9114fd"
475
- ]
476
- },
477
- "community": {
478
- "score": 0,
479
- "categories": [],
480
- "brands": [],
481
- "votesTotal": 0,
482
- "votesMalicious": 0,
483
- "votesBenign": 0,
484
- "malicious": false,
485
- "hasVerdicts": false
486
- }
487
- }
488
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
docs/urlscan_api.md DELETED
@@ -1,169 +0,0 @@
1
- # URLScan.io API Integration
2
-
3
- This module provides a Python client for interacting with the URLScan.io API to analyze URLs for phishing detection.
4
-
5
- ## Setup
6
-
7
- 1. **Get an API key:**
8
- - Sign up at https://urlscan.io/user/signup
9
- - Get your API key from your account settings
10
-
11
- 2. **Set environment variable:**
12
- ```bash
13
- export URLSCAN_API_KEY="your_api_key_here"
14
- ```
15
-
16
- Or create a `.env` file:
17
- ```bash
18
- cp .env.example .env
19
- # Edit .env and add your API key
20
- ```
21
-
22
- ## Basic Usage
23
-
24
- ### Initialize Client
25
-
26
- ```python
27
- from phising_detection.api import URLScanClient
28
-
29
- # Using environment variable
30
- client = URLScanClient()
31
-
32
- # Or pass API key directly
33
- client = URLScanClient(api_key="your_api_key")
34
- ```
35
-
36
- ### Submit a URL for Scanning
37
-
38
- ```python
39
- # Submit URL
40
- result = client.submit_url(
41
- url="https://suspicious-site.com",
42
- visibility="public", # or "unlisted" or "private"
43
- tags=["phishing", "test"]
44
- )
45
-
46
- uuid = result["uuid"]
47
- print(f"Scan UUID: {uuid}")
48
- ```
49
-
50
- ### Retrieve Results
51
-
52
- ```python
53
- # Get results by UUID
54
- scan_result = client.get_result(uuid)
55
-
56
- # Access scan data
57
- page_title = scan_result["page"]["title"]
58
- screenshot = scan_result["task"]["screenshotURL"]
59
- ```
60
-
61
- ### Submit and Wait for Results
62
-
63
- ```python
64
- # Submit and automatically wait for completion
65
- result = client.submit_and_wait(
66
- url="https://example.com",
67
- max_wait=60, # seconds
68
- poll_interval=5 # seconds between checks
69
- )
70
- ```
71
-
72
- ### Get Verdict
73
-
74
- ```python
75
- # Get simple verdict (malicious/safe)
76
- verdict = client.get_verdict(uuid)
77
- print(f"Verdict: {verdict}") # "malicious" or "safe"
78
- ```
79
-
80
- ### Search Existing Scans
81
-
82
- ```python
83
- # Search for scans by domain
84
- results = client.search(
85
- query="domain:example.com",
86
- size=10
87
- )
88
-
89
- for scan in results["results"]:
90
- print(scan["task"]["url"])
91
- ```
92
-
93
- ## API Response Examples
94
-
95
- ### Submission Response
96
-
97
- ```json
98
- {
99
- "uuid": "abc123...",
100
- "result": "https://urlscan.io/result/abc123.../",
101
- "api": "https://urlscan.io/api/v1/result/abc123.../"
102
- }
103
- ```
104
-
105
- ### Result Response
106
-
107
- ```json
108
- {
109
- "page": {
110
- "url": "https://example.com",
111
- "title": "Example Domain",
112
- "status": "200"
113
- },
114
- "verdicts": {
115
- "overall": {
116
- "score": 0,
117
- "malicious": false
118
- }
119
- },
120
- "task": {
121
- "uuid": "abc123...",
122
- "time": "2024-01-01T12:00:00.000Z",
123
- "screenshotURL": "https://..."
124
- }
125
- }
126
- ```
127
-
128
- ## Error Handling
129
-
130
- ```python
131
- from phising_detection.api import URLScanClient, URLScanError
132
-
133
- try:
134
- client = URLScanClient()
135
- result = client.submit_url("https://example.com")
136
- except URLScanError as e:
137
- print(f"Error: {e}")
138
- ```
139
-
140
- ## Rate Limits
141
-
142
- - Free tier: 50 submissions per day
143
- - Paid tier: Higher limits available
144
- - The client handles rate limit errors automatically
145
-
146
- ## Integration with Phishing Detection
147
-
148
- ```python
149
- from phising_detection.api import URLScanClient
150
- from phising_detection.data import load_phishing_urls
151
-
152
- # Load your phishing URLs
153
- df = load_phishing_urls()
154
-
155
- # Analyze URLs
156
- client = URLScanClient()
157
-
158
- for idx, row in df.head(10).iterrows(): # Sample first 10
159
- try:
160
- result = client.submit_and_wait(row['url'])
161
- verdict = client.get_verdict(result['task']['uuid'])
162
- print(f"{row['url']}: {verdict}")
163
- except URLScanError as e:
164
- print(f"Error scanning {row['url']}: {e}")
165
- ```
166
-
167
- ## API Documentation
168
-
169
- Full API documentation: https://urlscan.io/docs/api/