@dotenvx/dotenvx 0.18.0 → 0.19.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/cli/actions/precommit.js +0 -102
- package/src/cli/actions/scan.js +27 -0
- package/src/cli/dotenvx.js +5 -0
- package/src/lib/services/precommit.js +54 -1
package/package.json
CHANGED
|
@@ -1,11 +1,5 @@
|
|
|
1
|
-
const fs = require('fs')
|
|
2
|
-
const path = require('path')
|
|
3
|
-
const ignore = require('ignore')
|
|
4
|
-
|
|
5
1
|
const logger = require('./../../shared/logger')
|
|
6
2
|
|
|
7
|
-
const helpers = require('./../helpers')
|
|
8
|
-
|
|
9
3
|
const Precommit = require('./../../lib/services/precommit')
|
|
10
4
|
|
|
11
5
|
function precommit () {
|
|
@@ -14,102 +8,6 @@ function precommit () {
|
|
|
14
8
|
|
|
15
9
|
const precommit = new Precommit(options)
|
|
16
10
|
precommit.run()
|
|
17
|
-
|
|
18
|
-
// 0. handle the --install flag
|
|
19
|
-
if (options.install) {
|
|
20
|
-
installPrecommitHook()
|
|
21
|
-
return
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
// 1. check for .gitignore file
|
|
25
|
-
if (!fs.existsSync('.gitignore')) {
|
|
26
|
-
logger.errorvp('.gitignore missing')
|
|
27
|
-
logger.help2('? add it with [touch .gitignore]')
|
|
28
|
-
process.exit(1)
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
// 2. check .env* files against .gitignore file
|
|
32
|
-
let warningCount = 0
|
|
33
|
-
const ig = ignore().add(fs.readFileSync('.gitignore').toString())
|
|
34
|
-
const files = fs.readdirSync(process.cwd())
|
|
35
|
-
const dotenvFiles = files.filter(file => file.match(/^\.env(\..+)?$/))
|
|
36
|
-
dotenvFiles.forEach(file => {
|
|
37
|
-
// check if that file is being ignored
|
|
38
|
-
if (ig.ignores(file)) {
|
|
39
|
-
switch (file) {
|
|
40
|
-
case '.env.example':
|
|
41
|
-
warningCount += 1
|
|
42
|
-
logger.warnv(`${file} (currently ignored but should not be)`)
|
|
43
|
-
logger.help2(`? add !${file} to .gitignore with [echo "!${file}" >> .gitignore]`)
|
|
44
|
-
break
|
|
45
|
-
case '.env.vault':
|
|
46
|
-
warningCount += 1
|
|
47
|
-
logger.warnv(`${file} (currently ignored but should not be)`)
|
|
48
|
-
logger.help2(`? add !${file} to .gitignore with [echo "!${file}" >> .gitignore]`)
|
|
49
|
-
break
|
|
50
|
-
default:
|
|
51
|
-
break
|
|
52
|
-
}
|
|
53
|
-
} else {
|
|
54
|
-
switch (file) {
|
|
55
|
-
case '.env.example':
|
|
56
|
-
break
|
|
57
|
-
case '.env.vault':
|
|
58
|
-
break
|
|
59
|
-
default:
|
|
60
|
-
logger.errorvp(`${file} not properly gitignored`)
|
|
61
|
-
logger.help2(`? add ${file} to .gitignore with [echo ".env*" >> .gitignore]`)
|
|
62
|
-
process.exit(1) // 3.1 exit early with error code
|
|
63
|
-
break
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
})
|
|
67
|
-
|
|
68
|
-
// 3. outpout success
|
|
69
|
-
if (warningCount > 0) {
|
|
70
|
-
logger.successvp(`success (with ${helpers.pluralize('warning', warningCount)})`)
|
|
71
|
-
} else {
|
|
72
|
-
logger.successvp('success')
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
function installPrecommitHook () {
|
|
77
|
-
const hookScript = `#!/bin/sh
|
|
78
|
-
|
|
79
|
-
if ! command -v dotenvx &> /dev/null
|
|
80
|
-
then
|
|
81
|
-
echo "[dotenvx][precommit] 'dotenvx' command not found"
|
|
82
|
-
echo "[dotenvx][precommit] ? install it with [brew install dotenvx/brew/dotenvx]"
|
|
83
|
-
echo "[dotenvx][precommit] ? other install options [https://dotenvx.com/docs/install]"
|
|
84
|
-
exit 1
|
|
85
|
-
fi
|
|
86
|
-
|
|
87
|
-
dotenvx precommit`
|
|
88
|
-
const hookPath = path.join('.git', 'hooks', 'pre-commit')
|
|
89
|
-
|
|
90
|
-
try {
|
|
91
|
-
// Check if the pre-commit file already exists
|
|
92
|
-
if (fs.existsSync(hookPath)) {
|
|
93
|
-
// Read the existing content of the file
|
|
94
|
-
const existingContent = fs.readFileSync(hookPath, 'utf8')
|
|
95
|
-
|
|
96
|
-
// Check if 'dotenvx precommit' already exists in the file
|
|
97
|
-
if (!existingContent.includes('dotenvx precommit')) {
|
|
98
|
-
// Append 'dotenvx precommit' to the existing file
|
|
99
|
-
fs.appendFileSync(hookPath, '\n' + hookScript)
|
|
100
|
-
logger.successvp(`dotenvx precommit appended [${hookPath}]`)
|
|
101
|
-
} else {
|
|
102
|
-
logger.warnvp(`dotenvx precommit exists [${hookPath}]`)
|
|
103
|
-
}
|
|
104
|
-
} else {
|
|
105
|
-
// If the pre-commit file doesn't exist, create a new one with the hookScript
|
|
106
|
-
fs.writeFileSync(hookPath, hookScript)
|
|
107
|
-
fs.chmodSync(hookPath, '755') // Make the file executable
|
|
108
|
-
logger.successvp(`dotenvx precommit installed [${hookPath}]`)
|
|
109
|
-
}
|
|
110
|
-
} catch (err) {
|
|
111
|
-
logger.errorvp(`Failed to modify pre-commit hook: ${err.message}`)
|
|
112
|
-
}
|
|
113
11
|
}
|
|
114
12
|
|
|
115
13
|
module.exports = precommit
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
const execa = require('execa')
|
|
2
|
+
|
|
3
|
+
const logger = require('./../../shared/logger')
|
|
4
|
+
|
|
5
|
+
async function scan () {
|
|
6
|
+
const options = this.opts()
|
|
7
|
+
logger.debug(`options: ${JSON.stringify(options)}`)
|
|
8
|
+
|
|
9
|
+
try {
|
|
10
|
+
await execa('gitleaks', ['version'])
|
|
11
|
+
} catch (error) {
|
|
12
|
+
logger.error('gitleaks command not found')
|
|
13
|
+
logger.help('? install gitleaks: [brew install gitleaks]')
|
|
14
|
+
logger.help2('? other install options: [https://github.com/gitleaks/gitleaks]')
|
|
15
|
+
process.exit(1)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
try {
|
|
19
|
+
const { stderr } = await execa('gitleaks', ['detect', '-v'])
|
|
20
|
+
logger.blank(stderr) // gitleaks sends output as stderr for strange reason
|
|
21
|
+
} catch (error) {
|
|
22
|
+
logger.error(error.message)
|
|
23
|
+
process.exit(1)
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
module.exports = scan
|
package/src/cli/dotenvx.js
CHANGED
|
@@ -97,6 +97,11 @@ program.command('genexample')
|
|
|
97
97
|
.option('-f, --env-file <paths...>', 'path(s) to your env file(s)', '.env')
|
|
98
98
|
.action(require('./actions/genexample'))
|
|
99
99
|
|
|
100
|
+
// dotenvx scan
|
|
101
|
+
program.command('scan')
|
|
102
|
+
.description('scan for leaked secrets')
|
|
103
|
+
.action(require('./actions/scan'))
|
|
104
|
+
|
|
100
105
|
// dotenvx ls
|
|
101
106
|
program.command('ls')
|
|
102
107
|
.description('print all .env files in a tree structure')
|
|
@@ -1,4 +1,8 @@
|
|
|
1
|
+
/* istanbul ignore file */
|
|
2
|
+
const fs = require('fs')
|
|
3
|
+
const ignore = require('ignore')
|
|
1
4
|
const logger = require('./../../shared/logger')
|
|
5
|
+
const helpers = require('./../../cli/helpers')
|
|
2
6
|
|
|
3
7
|
const InstallPrecommitHook = require('./../helpers/installPrecommitHook')
|
|
4
8
|
|
|
@@ -14,7 +18,56 @@ class Precommit {
|
|
|
14
18
|
return true
|
|
15
19
|
}
|
|
16
20
|
|
|
17
|
-
|
|
21
|
+
// 1. check for .gitignore file
|
|
22
|
+
if (!fs.existsSync('.gitignore')) {
|
|
23
|
+
logger.errorvp('.gitignore missing')
|
|
24
|
+
logger.help2('? add it with [touch .gitignore]')
|
|
25
|
+
process.exit(1)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// 2. check .env* files against .gitignore file
|
|
29
|
+
let warningCount = 0
|
|
30
|
+
const ig = ignore().add(fs.readFileSync('.gitignore').toString())
|
|
31
|
+
const files = fs.readdirSync(process.cwd())
|
|
32
|
+
const dotenvFiles = files.filter(file => file.match(/^\.env(\..+)?$/))
|
|
33
|
+
dotenvFiles.forEach(file => {
|
|
34
|
+
// check if that file is being ignored
|
|
35
|
+
if (ig.ignores(file)) {
|
|
36
|
+
switch (file) {
|
|
37
|
+
case '.env.example':
|
|
38
|
+
warningCount += 1
|
|
39
|
+
logger.warnv(`${file} (currently ignored but should not be)`)
|
|
40
|
+
logger.help2(`? add !${file} to .gitignore with [echo "!${file}" >> .gitignore]`)
|
|
41
|
+
break
|
|
42
|
+
case '.env.vault':
|
|
43
|
+
warningCount += 1
|
|
44
|
+
logger.warnv(`${file} (currently ignored but should not be)`)
|
|
45
|
+
logger.help2(`? add !${file} to .gitignore with [echo "!${file}" >> .gitignore]`)
|
|
46
|
+
break
|
|
47
|
+
default:
|
|
48
|
+
break
|
|
49
|
+
}
|
|
50
|
+
} else {
|
|
51
|
+
switch (file) {
|
|
52
|
+
case '.env.example':
|
|
53
|
+
break
|
|
54
|
+
case '.env.vault':
|
|
55
|
+
break
|
|
56
|
+
default:
|
|
57
|
+
logger.errorvp(`${file} not properly gitignored`)
|
|
58
|
+
logger.help2(`? add ${file} to .gitignore with [echo ".env*" >> .gitignore]`)
|
|
59
|
+
process.exit(1) // 3.1 exit early with error code
|
|
60
|
+
break
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
// 3. outpout success
|
|
66
|
+
if (warningCount > 0) {
|
|
67
|
+
logger.successvp(`success (with ${helpers.pluralize('warning', warningCount)})`)
|
|
68
|
+
} else {
|
|
69
|
+
logger.successvp('success')
|
|
70
|
+
}
|
|
18
71
|
}
|
|
19
72
|
|
|
20
73
|
/* istanbul ignore next */
|