Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@dotenvx/dotenvx

Package Overview
Dependencies
Maintainers
2
Versions
187
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@dotenvx/dotenvx - npm Package Compare versions

Comparing version 0.4.0 to 0.5.0

2

package.json
{
"version": "0.4.0",
"version": "0.5.0",
"name": "@dotenvx/dotenvx",

@@ -4,0 +4,0 @@ "description": "a better dotenv–from the creator of `dotenv`",

@@ -161,3 +161,3 @@ ![dotenvx](https://dotenvx.com/better-banner.png)

```
dotenvx encrypt
$ dotenvx encrypt
```

@@ -164,0 +164,0 @@

@@ -5,3 +5,2 @@ #!/usr/bin/env node

const { Command } = require('commander')
const dotenv = require('dotenv')
const program = new Command()

@@ -63,36 +62,93 @@

// convert to array if needed
let optionEnvFile = options.envFile
if (!Array.isArray(optionEnvFile)) {
optionEnvFile = [optionEnvFile]
}
// load from .env.vault file
if (process.env.DOTENV_KEY && process.env.DOTENV_KEY.length > 0) {
const filepath = helpers.resolvePath('.env.vault')
const env = {}
const readableFilepaths = new Set()
const written = new Set()
if (!fs.existsSync(filepath)) {
logger.error(`you set DOTENV_KEY but your .env.vault file is missing: ${filepath}`)
} else {
logger.verbose(`injecting encrypted env from ${filepath}`)
for (const envFilepath of optionEnvFile) {
const filepath = helpers.resolvePath(envFilepath)
try {
logger.debug(`reading encrypted env from ${filepath}`)
const src = fs.readFileSync(filepath, { encoding: ENCODING })
logger.verbose(`injecting env from ${filepath}`)
logger.debug(`parsing encrypted env from ${filepath}`)
const parsedVault = main.parse(src)
try {
logger.debug(`reading env from ${filepath}`)
const src = fs.readFileSync(filepath, { encoding: ENCODING })
logger.debug(`decrypting encrypted env from ${filepath}`)
// handle scenario for comma separated keys - for use with key rotation
// example: DOTENV_KEY="dotenv://:key_1234@dotenv.org/vault/.env.vault?environment=prod,dotenv://:key_7890@dotenv.org/vault/.env.vault?environment=prod"
const dotenvKeys = process.env.DOTENV_KEY.split(',')
const length = dotenvKeys.length
logger.debug(`parsing env from ${filepath}`)
const parsed = main.parse(src)
let decrypted
for (let i = 0; i < length; i++) {
try {
// Get full dotenvKey
const dotenvKey = dotenvKeys[i].trim()
logger.debug(`writing env from ${filepath}`)
const result = main.write(process.env, parsed, options.overload)
const key = helpers._parseEncryptionKeyFromDotenvKey(dotenvKey)
const ciphertext = helpers._parseCipherTextFromDotenvKeyAndParsedVault(dotenvKey, parsedVault)
readableFilepaths.add(envFilepath)
result.written.forEach(key => written.add(key))
} catch (e) {
logger.warn(e)
// Decrypt
decrypted = main.decrypt(ciphertext, key)
break
} catch (error) {
// last key
if (i + 1 >= length) {
throw error
}
// try next key
}
}
logger.debug(decrypted)
logger.debug(`parsing decrypted env from ${filepath}`)
const parsed = main.parse(decrypted)
logger.debug(`writing decrypted env from ${filepath}`)
const result = main.write(process.env, parsed, options.overload)
logger.info(`injecting ${result.written.size} environment ${helpers.pluralize('variable', result.written.size)} from encrypted .env.vault`)
} catch (e) {
logger.error(e)
}
}
}
} else {
// convert to array if needed
let optionEnvFile = options.envFile
if (!Array.isArray(optionEnvFile)) {
optionEnvFile = [optionEnvFile]
}
if (readableFilepaths.size > 0) {
logger.info(`injecting ${written.size} environment ${helpers.pluralize('variable', written.size)} from ${[...readableFilepaths]}`)
const readableFilepaths = new Set()
const written = new Set()
for (const envFilepath of optionEnvFile) {
const filepath = helpers.resolvePath(envFilepath)
logger.verbose(`injecting env from ${filepath}`)
try {
logger.debug(`reading env from ${filepath}`)
const src = fs.readFileSync(filepath, { encoding: ENCODING })
logger.debug(`parsing env from ${filepath}`)
const parsed = main.parse(src)
logger.debug(`writing env from ${filepath}`)
const result = main.write(process.env, parsed, options.overload)
readableFilepaths.add(envFilepath)
result.written.forEach(key => written.add(key))
} catch (e) {
logger.warn(e)
}
}
if (readableFilepaths.size > 0) {
logger.info(`injecting ${written.size} environment ${helpers.pluralize('variable', written.size)} from ${[...readableFilepaths]}`)
}
}

@@ -108,3 +164,3 @@

helpers.executeCommand(subCommand, env)
helpers.executeCommand(subCommand, process.env)
}

@@ -130,3 +186,3 @@ })

const dotenvKeys = (dotenv.configDotenv({ path: '.env.keys' }).parsed || {})
const dotenvKeys = (main.configDotenv({ path: '.env.keys' }).parsed || {})

@@ -176,4 +232,4 @@ for (const envFilepath of optionEnvFile) {

const dotenvKeys = (dotenv.configDotenv({ path: '.env.keys' }).parsed || {})
const dotenvVaults = (dotenv.configDotenv({ path: '.env.vault' }).parsed || {})
const dotenvKeys = (main.configDotenv({ path: '.env.keys' }).parsed || {})
const dotenvVaults = (main.configDotenv({ path: '.env.vault' }).parsed || {})

@@ -219,6 +275,4 @@ for (const envFilepath of optionEnvFile) {

logger.info(`encrypted ${optionEnvFile} to .env.vault`)
// logger.info(`encrypting`)
})
program.parse(process.argv)

@@ -7,2 +7,3 @@ const fs = require('fs')

const XXHASH_SEED = 0xABCD
const NONCE_BYTES = 12

@@ -73,6 +74,6 @@ const main = require('./../lib/main')

const encryptFile = function (filepath, dotenvKey, encoding) {
const key = this._parseEncryptionKeyFromDotenvKey(dotenvKey)
const key = _parseEncryptionKeyFromDotenvKey(dotenvKey)
const message = fs.readFileSync(filepath, encoding)
const ciphertext = this.encrypt(key, message)
const ciphertext = encrypt(key, message)

@@ -84,3 +85,3 @@ return ciphertext

// set up nonce
const nonce = this._generateNonce()
const nonce = crypto.randomBytes(NONCE_BYTES)

@@ -104,7 +105,7 @@ // set up cipher

const changed = function (ciphertext, dotenvKey, filepath, encoding) {
const key = this._parseEncryptionKeyFromDotenvKey(dotenvKey)
const key = _parseEncryptionKeyFromDotenvKey(dotenvKey)
const decrypted = main.decrypt(ciphertext, key)
const raw = fs.readFileSync(filepath, encoding)
return this.hash(decrypted) !== this.hash(raw)
return hash(decrypted) !== hash(raw)
}

@@ -118,3 +119,8 @@

// Parse DOTENV_KEY. Format is a URI
const uri = new URL(dotenvKey)
let uri
try {
uri = new URL(dotenvKey)
} catch (e) {
throw new Error(`INVALID_DOTENV_KEY: ${e.message}`)
}

@@ -130,8 +136,25 @@ // Get decrypt key

const _generateNonce = function () {
return crypto.randomBytes(this._nonceBytes())
}
const _parseCipherTextFromDotenvKeyAndParsedVault = function (dotenvKey, parsedVault) {
// Parse DOTENV_KEY. Format is a URI
let uri
try {
uri = new URL(dotenvKey)
} catch (e) {
throw new Error(`INVALID_DOTENV_KEY: ${e.message}`)
}
const _nonceBytes = function () {
return 12
// Get environment
const environment = uri.searchParams.get('environment')
if (!environment) {
throw new Error('INVALID_DOTENV_KEY: Missing environment part')
}
// Get ciphertext payload
const environmentKey = `DOTENV_VAULT_${environment.toUpperCase()}`
const ciphertext = parsedVault[environmentKey] // DOTENV_VAULT_PRODUCTION
if (!ciphertext) {
throw new Error(`NOT_FOUND_DOTENV_ENVIRONMENT: cannot locate environment ${environmentKey} in your .env.vault file`)
}
return ciphertext
}

@@ -151,4 +174,3 @@

_parseEncryptionKeyFromDotenvKey,
_generateNonce,
_nonceBytes
_parseCipherTextFromDotenvKeyAndParsedVault
}

@@ -12,2 +12,6 @@ const logger = require('./../shared/logger')

const configDotenv = function (options) {
return dotenv.configDotenv(options)
}
const parse = function (src) {

@@ -61,2 +65,3 @@ const result = dotenv.parse(src)

config,
configDotenv,
decrypt,

@@ -63,0 +68,0 @@ parse,

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc