@@ -3,6 +3,7 @@ package apiflash
3
3
import (
4
4
"context"
5
5
"fmt"
6
+ "io"
6
7
"net/http"
7
8
"strings"
8
9
24
25
25
26
// Make sure that your group is surrounded in boundary characters such as below to reduce false positives.
26
27
keyPat = regexp .MustCompile (detectors .PrefixRegex ([]string {"apiflash" }) + `\b([a-z0-9]{32})\b` )
27
- urlPat = regexp .MustCompile (detectors .PrefixRegex ([]string {"apiflash" }) + `\b([a-zA-Z0-9\S]{21,30})\b` )
28
+
29
+ urlToCapture = "http://google.com" // a fix constant url to capture to verify the access key
28
30
)
29
31
30
32
// Keywords are used for efficiently pre-filtering chunks.
@@ -36,43 +38,25 @@ func (s Scanner) Keywords() []string {
36
38
// FromData will find and optionally verify Apiflash secrets in a given set of bytes.
37
39
func (s Scanner ) FromData (ctx context.Context , verify bool , data []byte ) (results []detectors.Result , err error ) {
38
40
dataStr := string (data )
39
- matches := keyPat .FindAllStringSubmatch (dataStr , - 1 )
40
- urlMatches := urlPat .FindAllStringSubmatch (dataStr , - 1 )
41
41
42
- for _ , match := range matches {
43
- if len (match ) != 2 {
44
- continue
42
+ uniqueAPIKeys := make (map [string ]struct {})
43
+ for _ , match := range keyPat .FindAllStringSubmatch (dataStr , - 1 ) {
44
+ uniqueAPIKeys [strings .TrimSpace (match [1 ])] = struct {}{}
45
+ }
46
+
47
+ for key := range uniqueAPIKeys {
48
+ s1 := detectors.Result {
49
+ DetectorType : detectorspb .DetectorType_Apiflash ,
50
+ Raw : []byte (key ),
45
51
}
46
- resMatch := strings .TrimSpace (match [1 ])
47
-
48
- for _ , urlMatch := range urlMatches {
49
- if len (urlMatch ) != 2 {
50
- continue
51
- }
52
-
53
- resUrlMatch := strings .TrimSpace (urlMatch [1 ])
54
- s1 := detectors.Result {
55
- DetectorType : detectorspb .DetectorType_Apiflash ,
56
- Raw : []byte (resMatch ),
57
- RawV2 : []byte (resMatch + resUrlMatch ),
58
- }
59
-
60
- if verify {
61
- req , err := http .NewRequestWithContext (ctx , "GET" , fmt .Sprintf ("https://api.apiflash.com/v1/urltoimage?url=%s&access_key=%s" , resUrlMatch , resMatch ), nil )
62
- if err != nil {
63
- continue
64
- }
65
- res , err := client .Do (req )
66
- if err == nil {
67
- defer res .Body .Close ()
68
- if res .StatusCode >= 200 && res .StatusCode < 300 {
69
- s1 .Verified = true
70
- }
71
- }
72
- }
73
-
74
- results = append (results , s1 )
52
+
53
+ if verify {
54
+ isVerified , verificationErr := verifyAPIFlash (ctx , client , key )
55
+ s1 .Verified = isVerified
56
+ s1 .SetVerificationError (verificationErr , key )
75
57
}
58
+
59
+ results = append (results , s1 )
76
60
}
77
61
78
62
return results , nil
@@ -85,3 +69,28 @@ func (s Scanner) Type() detectorspb.DetectorType {
85
69
func (s Scanner ) Description () string {
86
70
return "Apiflash is a screenshot API service. Apiflash keys can be used to access and utilize the screenshot API service."
87
71
}
72
+
73
+ func verifyAPIFlash (ctx context.Context , client * http.Client , accessKey string ) (bool , error ) {
74
+ req , err := http .NewRequestWithContext (ctx , "GET" , fmt .Sprintf ("https://api.apiflash.com/v1/urltoimage?url=%s&access_key=%s&wait_until=page_loaded" , urlToCapture , accessKey ), http .NoBody )
75
+ if err != nil {
76
+ return false , err
77
+ }
78
+
79
+ resp , err := client .Do (req )
80
+ if err != nil {
81
+ return false , nil
82
+ }
83
+ defer func () {
84
+ _ , _ = io .Copy (io .Discard , resp .Body )
85
+ _ = resp .Body .Close ()
86
+ }()
87
+
88
+ switch resp .StatusCode {
89
+ case http .StatusOK :
90
+ return true , nil
91
+ case http .StatusUnauthorized :
92
+ return false , nil
93
+ default :
94
+ return false , fmt .Errorf ("unexpected status code: %d" , resp .StatusCode )
95
+ }
96
+ }
0 commit comments