Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
.DS_Store
._.DS_Store
.Trash/
Thumbs.db
/.env
/.env.local
Expand Down
1 change: 1 addition & 0 deletions src/commands/ci/handle-ci.mts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ export async function handleCi(autoManifest: boolean): Promise<void> {
pendingHead: true,
pullRequest: 0,
reach: {
excludePaths: [],
reachAnalysisMemoryLimit: 0,
reachAnalysisTimeout: 0,
reachConcurrency: 1,
Expand Down
4 changes: 2 additions & 2 deletions src/commands/install/socket-completion.bash
Original file line number Diff line number Diff line change
Expand Up @@ -125,12 +125,12 @@ FLAGS=(
[repos update]="--default-branch --homepage --interactive --org --repo-description --repo-name --visibility"
[repos view]="--interactive --org --repo-name"
[scan]=""
[scan create]="--auto-manifest --branch --commit-hash --commit-message --committers --cwd --default-branch --interactive --json --markdown --org --pull-request --reach --reach-analysis-memory-limit --reach-analysis-timeout --reach-disable-analytics --reach-ecosystems --reach-exclude-paths --read-only --repo --report --set-as-alerts-page --tmp"
[scan create]="--auto-manifest --branch --commit-hash --commit-message --committers --cwd --default-branch --exclude-paths --interactive --json --markdown --org --pull-request --reach --reach-analysis-memory-limit --reach-analysis-timeout --reach-disable-analytics --reach-ecosystems --reach-exclude-paths --read-only --repo --report --set-as-alerts-page --tmp"
[scan del]="--interactive --org"
[scan diff]="--depth --file --interactive --org"
[scan list]="--branch --direction --from-time --interactive --json --markdown --org --page --per-page --repo --sort --until-time"
[scan metadata]="--interactive --org"
[scan reach]="--reach-analysis-memory-limit --reach-analysis-timeout --reach-disable-analytics --reach-ecosystems --reach-exclude-paths"
[scan reach]="--exclude-paths --reach-analysis-memory-limit --reach-analysis-timeout --reach-disable-analytics --reach-ecosystems --reach-exclude-paths"
[scan report]="--fold --interactive --license --org --report-level --short"
[scan view]="--interactive --org --stream"
[threat-feed]="--direction --eco --filter --interactive --json --markdown --org --page --per-page"
Expand Down
10 changes: 8 additions & 2 deletions src/commands/scan/cmd-scan-create.mts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ import path from 'node:path'
import { joinAnd } from '@socketsecurity/registry/lib/arrays'
import { logger } from '@socketsecurity/registry/lib/logger'

import { assertValidExcludePaths } from './exclude-paths.mts'
import { handleCreateNewScan } from './handle-create-new-scan.mts'
import { outputCreateNewScan } from './output-create-new-scan.mts'
import { reachabilityFlags } from './reachability-flags.mts'
import { excludePathsFlag, reachabilityFlags } from './reachability-flags.mts'
import { suggestOrgSlug } from './suggest-org-slug.mts'
import { suggestTarget } from './suggest_target.mts'
import { validateReachabilityTarget } from './validate-reachability-target.mts'
Expand Down Expand Up @@ -171,6 +172,7 @@ async function run(
hidden,
flags: {
...generalFlags,
...excludePathsFlag,
...reachabilityFlags,
},
help: command => `
Expand All @@ -181,7 +183,7 @@ async function run(
${getFlagApiRequirementsOutput(`${parentName}:${CMD_NAME}`)}

Options
${getFlagListOutput(generalFlags)}
${getFlagListOutput({ ...generalFlags, ...excludePathsFlag })}

Reachability Options (when --reach is used)
${getFlagListOutput(reachabilityFlags)}
Expand Down Expand Up @@ -463,6 +465,9 @@ async function run(
logger.error('')
}

const excludePaths = cmdFlagValueToArray(cli.flags['excludePaths'])
assertValidExcludePaths(excludePaths)

const reachExcludePaths = cmdFlagValueToArray(cli.flags['reachExcludePaths'])

// Validation helpers for better readability.
Expand Down Expand Up @@ -608,6 +613,7 @@ async function run(
pendingHead: Boolean(pendingHead),
pullRequest: Number(pullRequest),
reach: {
excludePaths,
reachAnalysisMemoryLimit: Number(reachAnalysisMemoryLimit),
reachAnalysisTimeout: Number(reachAnalysisTimeout),
reachConcurrency: Number(reachConcurrency),
Expand Down
83 changes: 83 additions & 0 deletions src/commands/scan/cmd-scan-create.test.mts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ describe('socket scan create', async () => {
--committers Committers
--cwd working directory, defaults to process.cwd()
--default-branch Set the default branch of the repository to the branch of this full-scan. Should only need to be done once, for example for the "main" or "master" branch.
--exclude-paths List of glob patterns to exclude from the scan, including SCA/SBOM manifest discovery and (when --reach is enabled) Tier 1 reachability analysis. Patterns are anchored micromatch globs matched relative to the Socket scan root, which is the command working directory (\`--cwd\` if set), not the reachability target: \`tests\` matches only \`<cwd>/tests\`; use \`**/tests\` to match at any depth. Negation patterns (\`!path\`) are not supported. Accepts a comma-separated value or multiple flags.
--interactive Allow for interactive elements, asking for input. Use --no-interactive to prevent any input questions, defaulting them to cancel/no.
--json Output as JSON
--markdown Output as Markdown
Expand Down Expand Up @@ -185,6 +186,62 @@ describe('socket scan create', async () => {
},
)

cmdit(
[
'scan',
'create',
FLAG_ORG,
'fakeOrg',
'target',
FLAG_DRY_RUN,
'--repo',
'xyz',
'--branch',
'abc',
'--exclude-paths',
'tests',
FLAG_CONFIG,
'{"apiToken":"fakeToken"}',
],
'should succeed when --exclude-paths is used without --reach',
async cmd => {
const { code, stdout } = await spawnSocketCli(binCliPath, cmd)
expect(stdout).toMatchInlineSnapshot(`"[DryRun]: Bailing now"`)
expect(
code,
'should exit with code 0 when --exclude-paths is used standalone',
).toBe(0)
},
)

cmdit(
[
'scan',
'create',
FLAG_ORG,
'fakeOrg',
'target',
FLAG_DRY_RUN,
'--repo',
'xyz',
'--branch',
'abc',
'--exclude-paths',
'!tests/keep',
FLAG_CONFIG,
'{"apiToken":"fakeToken"}',
],
'should reject --exclude-paths negation patterns',
async cmd => {
const { code, stderr, stdout } = await spawnSocketCli(binCliPath, cmd)
const output = stdout + stderr
expect(output).toContain(
"--exclude-paths does not support negation patterns. Got: '!tests/keep'.",
)
expect(code, 'should exit with non-zero code').not.toBe(0)
},
)

cmdit(
[
'scan',
Expand Down Expand Up @@ -437,6 +494,32 @@ describe('socket scan create', async () => {
},
)

cmdit(
[
'scan',
'create',
FLAG_ORG,
'fakeOrg',
'test/fixtures/commands/scan/simple-npm',
FLAG_DRY_RUN,
'--repo',
'xyz',
'--branch',
'abc',
'--reach',
'--exclude-paths',
'tests',
FLAG_CONFIG,
'{"apiToken":"fakeToken"}',
],
'should succeed when --exclude-paths is used with --reach',
async cmd => {
const { code, stdout } = await spawnSocketCli(binCliPath, cmd)
expect(stdout).toMatchInlineSnapshot(`"[DryRun]: Bailing now"`)
expect(code, 'should exit with code 0 when all flags are valid').toBe(0)
},
)

cmdit(
[
'scan',
Expand Down
9 changes: 7 additions & 2 deletions src/commands/scan/cmd-scan-reach.mts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ import path from 'node:path'
import { joinAnd } from '@socketsecurity/registry/lib/arrays'
import { logger } from '@socketsecurity/registry/lib/logger'

import { assertValidExcludePaths } from './exclude-paths.mts'
import { handleScanReach } from './handle-scan-reach.mts'
import { reachabilityFlags } from './reachability-flags.mts'
import { excludePathsFlag, reachabilityFlags } from './reachability-flags.mts'
import { suggestTarget } from './suggest_target.mts'
import { validateReachabilityTarget } from './validate-reachability-target.mts'
import constants from '../../constants.mts'
Expand Down Expand Up @@ -74,6 +75,7 @@ async function run(
hidden,
flags: {
...generalFlags,
...excludePathsFlag,
...reachabilityFlags,
},
help: command =>
Expand All @@ -88,7 +90,7 @@ async function run(
${getFlagListOutput(generalFlags)}

Reachability Options
${getFlagListOutput(reachabilityFlags)}
${getFlagListOutput({ ...excludePathsFlag, ...reachabilityFlags })}

Runs the Socket reachability analysis without creating a scan in Socket.
The output is written to .socket.facts.json in the current working directory
Expand Down Expand Up @@ -167,8 +169,10 @@ async function run(
const dryRun = !!cli.flags['dryRun']

// Process comma-separated values for isMultiple flags.
const excludePaths = cmdFlagValueToArray(cli.flags['excludePaths'])
const reachEcosystemsRaw = cmdFlagValueToArray(cli.flags['reachEcosystems'])
const reachExcludePaths = cmdFlagValueToArray(cli.flags['reachExcludePaths'])
assertValidExcludePaths(excludePaths)

// Validate ecosystem values.
const reachEcosystems: PURL_Type[] = []
Expand Down Expand Up @@ -272,6 +276,7 @@ async function run(
outputKind,
outputPath: outputPath || '',
reachabilityOptions: {
excludePaths,
reachAnalysisMemoryLimit: Number(reachAnalysisMemoryLimit),
reachAnalysisTimeout: Number(reachAnalysisTimeout),
reachConcurrency: Number(reachConcurrency),
Expand Down
68 changes: 68 additions & 0 deletions src/commands/scan/cmd-scan-reach.test.mts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ describe('socket scan reach', async () => {
--output Path to write the reachability report to (must end with .json). Defaults to .socket.facts.json in the current working directory.

Reachability Options
--exclude-paths List of glob patterns to exclude from the scan, including SCA/SBOM manifest discovery and (when --reach is enabled) Tier 1 reachability analysis. Patterns are anchored micromatch globs matched relative to the Socket scan root, which is the command working directory (\`--cwd\` if set), not the reachability target: \`tests\` matches only \`<cwd>/tests\`; use \`**/tests\` to match at any depth. Negation patterns (\`!path\`) are not supported. Accepts a comma-separated value or multiple flags.
--reach-analysis-memory-limit The maximum memory in MB to use for the reachability analysis. The default is 8192MB.
--reach-analysis-timeout Set timeout for the reachability analysis. Split analysis runs may cause the total scan time to exceed this timeout significantly.
--reach-concurrency Set the maximum number of concurrent reachability analysis runs. It is recommended to choose a concurrency level that ensures each analysis run has at least the --reach-analysis-memory-limit amount of memory available. NPM reachability analysis does not support concurrent execution, so the concurrency level is ignored for NPM.
Expand Down Expand Up @@ -295,6 +296,50 @@ describe('socket scan reach', async () => {
'scan',
'reach',
FLAG_DRY_RUN,
'--exclude-paths',
'node_modules,dist',
'--org',
'fakeOrg',
FLAG_CONFIG,
'{"apiToken":"fakeToken"}',
],
'should accept --exclude-paths with comma-separated values',
async cmd => {
const { code, stdout } = await spawnSocketCli(binCliPath, cmd)
expect(stdout).toMatchInlineSnapshot(`"[DryRun]: Bailing now"`)
expect(code, 'should exit with code 0').toBe(0)
},
)

cmdit(
[
'scan',
'reach',
FLAG_DRY_RUN,
'--exclude-paths',
'node_modules',
'--exclude-paths',
'dist',
'--org',
'fakeOrg',
FLAG_CONFIG,
'{"apiToken":"fakeToken"}',
],
'should accept multiple --exclude-paths flags',
async cmd => {
const { code, stdout } = await spawnSocketCli(binCliPath, cmd)
expect(stdout).toMatchInlineSnapshot(`"[DryRun]: Bailing now"`)
expect(code, 'should exit with code 0').toBe(0)
},
)

cmdit(
[
'scan',
'reach',
FLAG_DRY_RUN,
'--exclude-paths',
'build',
'--reach-exclude-paths',
'node_modules,dist',
'--org',
Expand All @@ -310,6 +355,29 @@ describe('socket scan reach', async () => {
},
)

cmdit(
[
'scan',
'reach',
FLAG_DRY_RUN,
'--exclude-paths',
'!tests/keep',
'--org',
'fakeOrg',
FLAG_CONFIG,
'{"apiToken":"fakeToken"}',
],
'should reject --exclude-paths negation patterns',
async cmd => {
const { code, stderr, stdout } = await spawnSocketCli(binCliPath, cmd)
const output = stdout + stderr
expect(output).toContain(
"--exclude-paths does not support negation patterns. Got: '!tests/keep'.",
)
expect(code, 'should exit with non-zero code').not.toBe(0)
},
)

cmdit(
[
'scan',
Expand Down
1 change: 1 addition & 0 deletions src/commands/scan/create-scan-from-github.mts
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,7 @@ async function scanOneRepo(
pendingHead: true,
pullRequest: 0,
reach: {
excludePaths: [],
reachAnalysisMemoryLimit: 0,
reachAnalysisTimeout: 0,
reachConcurrency: 1,
Expand Down
Loading
Loading