Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/commands/fix/npm-fix.mts
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ export async function npmFix(
definitions: npmConfigDefinitions,
// Lazily access constants.execPath.
execPath: constants.execPath,
env: process.env,
env: { ...process.env },
flatten: npmConfigFlatten,
npmPath,
platform: process.platform,
Expand Down
16 changes: 15 additions & 1 deletion src/constants.mts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ type ENV = Remap<
INLINED_SYNP_VERSION: string
LOCALAPPDATA: string
NODE_COMPILE_CACHE: string
NODE_EXTRA_CA_CERTS: string
PATH: string
SOCKET_CLI_ACCEPT_RISKS: boolean
SOCKET_CLI_API_BASE_URL: string
Expand Down Expand Up @@ -308,6 +309,15 @@ const LAZY_ENV = () => {
? // Lazily access constants.socketCachePath.
constants.socketCachePath
: '',
// When set, the well known "root" CAs (like VeriSign) will be extended with
// the extra certificates in file. The file should consist of one or more
// trusted certificates in PEM format.
// https://nodejs.org/api/cli.html#node_extra_ca_certsfile
NODE_EXTRA_CA_CERTS:
envAsString(env['NODE_EXTRA_CA_CERTS']) ||
// Commonly used environment variable to specify the path to a single
// PEM-encoded certificate file.
envAsString(env['SSL_CERT_FILE']),
// PATH is an environment variable that lists directories where executable
// programs are located. When a command is run, the system searches these
// directories to find the executable.
Expand All @@ -323,7 +333,11 @@ const LAZY_ENV = () => {
// https://github.com/SocketDev/socket-cli?tab=readme-ov-file#environment-variables-for-development
SOCKET_CLI_API_PROXY:
envAsString(env['SOCKET_CLI_API_PROXY']) ||
envAsString(env['SOCKET_SECURITY_API_PROXY']),
envAsString(env['SOCKET_SECURITY_API_PROXY']) ||
// Commonly used environment variables to specify routing requests through
// a proxy server.
envAsString(env['HTTPS_PROXY']) ||
envAsString(env['https_proxy']),
// Flag to set the API token.
// https://github.com/SocketDev/socket-cli?tab=readme-ov-file#environment-variables
SOCKET_CLI_API_TOKEN:
Expand Down
40 changes: 31 additions & 9 deletions src/utils/sdk.mts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { HttpsProxyAgent } from 'hpagent'
import { HttpProxyAgent, HttpsProxyAgent } from 'hpagent'

import isInteractive from '@socketregistry/is-interactive/index.cjs'
import { password } from '@socketsecurity/registry/lib/prompts'
Expand All @@ -10,8 +10,6 @@ import constants from '../constants.mts'

import type { CResult } from '../types.mts'

const { SOCKET_PUBLIC_API_TOKEN } = constants

const TOKEN_PREFIX = 'sktsec_'

const { length: TOKEN_PREFIX_LENGTH } = TOKEN_PREFIX
Expand All @@ -21,15 +19,26 @@ function getDefaultApiBaseUrl(): string | undefined {
const baseUrl =
// Lazily access constants.ENV.SOCKET_CLI_API_BASE_URL.
constants.ENV.SOCKET_CLI_API_BASE_URL || getConfigValueOrUndef('apiBaseUrl')
return isNonEmptyString(baseUrl) ? baseUrl : undefined
return isUrl(baseUrl) ? baseUrl : undefined
}

// The API server that should be used for operations.
function getDefaultHttpProxy(): string | undefined {
function getDefaultProxyUrl(): string | undefined {
const apiProxy =
// Lazily access constants.ENV.SOCKET_CLI_API_PROXY.
constants.ENV.SOCKET_CLI_API_PROXY || getConfigValueOrUndef('apiProxy')
return isNonEmptyString(apiProxy) ? apiProxy : undefined
return isUrl(apiProxy) ? apiProxy : undefined
}

function isUrl(value: any): value is string {
if (isNonEmptyString(value)) {
try {
// eslint-disable-next-line no-new
new URL(value)
return true
} catch {}
}
return false
}

// This API key should be stored globally for the duration of the CLI execution.
Expand Down Expand Up @@ -64,14 +73,15 @@ export function getPublicToken(): string {
return (
// Lazily access constants.ENV.SOCKET_CLI_API_TOKEN.
(constants.ENV.SOCKET_CLI_API_TOKEN || getDefaultToken()) ??
SOCKET_PUBLIC_API_TOKEN
// Lazily access constants.SOCKET_PUBLIC_API_TOKEN.
constants.SOCKET_PUBLIC_API_TOKEN
)
}

export async function setupSdk(
apiToken: string | undefined = getDefaultToken(),
apiBaseUrl: string | undefined = getDefaultApiBaseUrl(),
proxy: string | undefined = getDefaultHttpProxy(),
proxy: string | undefined,
): Promise<CResult<SocketSdk>> {
if (typeof apiToken !== 'string' && isInteractive()) {
apiToken = await password({
Expand All @@ -87,10 +97,22 @@ export async function setupSdk(
cause: 'You need to provide an API Token. Run `socket login` first.',
}
}
if (!isUrl(proxy)) {
proxy = getDefaultProxyUrl()
}

const ProxyAgent = proxy?.startsWith('http:')
? HttpProxyAgent
: HttpsProxyAgent

return {
ok: true,
data: new SocketSdk(apiToken, {
agent: proxy ? new HttpsProxyAgent({ proxy }) : undefined,
agent: proxy
? new ProxyAgent({
proxy,
})
: undefined,
baseUrl: apiBaseUrl,
userAgent: createUserAgentFromPkgJson({
// Lazily access constants.ENV.INLINED_SOCKET_CLI_NAME.
Expand Down
1 change: 1 addition & 0 deletions test/socket-npm.test.mts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ for (const npmDir of ['npm9', 'npm10', 'npm11']) {
{
cwd: path.join(npmFixturesPath, 'lacking-typosquat'),
env: {
...process.env,
// Lazily access constants.ENV.PATH.
PATH: `${npmBinPath}:${constants.ENV.PATH}`,
},
Expand Down
Loading