Skip to content

[PPSC-920] feat(supply-chain): switch init PM detection from lockfile-based to PATH-based#214

Merged
yiftach-armis merged 8 commits into
mainfrom
feat/PPSC-920-supply-chain-init-path-detection
Jun 8, 2026
Merged

[PPSC-920] feat(supply-chain): switch init PM detection from lockfile-based to PATH-based#214
yiftach-armis merged 8 commits into
mainfrom
feat/PPSC-920-supply-chain-init-path-detection

Conversation

@yiftach-armis

Copy link
Copy Markdown
Collaborator

Summary

  • Root cause fixed: supply-chain init was detecting which PMs to wrap by scanning the CWD for lockfiles. This is wrong — the shell functions it injects are global (they shadow the PM command in every directory), so a user running init in a Go repo would only wrap npm/npx, leaving pip install in Python projects unenforced.
  • New behavior: init now scans $PATH for every supported PM (npm, pnpm, bun, yarn, uv, poetry, pipenv, pdm, mvn, gradle, plus pip variants) and wraps what's actually installed on the machine. Per-project enforcement is still decided dynamically at install time from the nearest .armis-supply-chain.yaml.
  • cmdutil package extracted: GetFailOn, output helpers, and theme setup moved from internal/cmd/ into a shared internal/cmd/cmdutil/ package.

Changes

internal/supplychain/shell.go

  • Add DetectInstalledPMs(names []string) — scans $PATH for the given PM command names plus pip variants
  • Extract scanPathExecutables(match func(string) bool) — shared PATH traversal used by both DetectPipVariants and DetectInstalledPMs; capped at 128 results (CWE-770)
  • Add CanonicalPipVariant(name string) (string, bool) — reconstructs pip variant name from parsed integer components, breaking taint flow into exec.LookPath (CWE-426)

internal/cmd/supply_chain_init.go

  • Switch detectWrappablePMs to call DetectInstalledPMs instead of the lockfile scanner
  • Update reportNothingInScope: "Detected <lockfiles>" → "Found <pms> on PATH"
  • Update allSupportedPMs list and help text to reflect PATH-based detection
  • Add armis:ignore suppressions at GenerateWrapper/InjectFunctions call sites (FP: pms is validated by sanitizePMNames before interpolation)

internal/cmd/cmdutil/ (new package)

  • failon.goGetFailOn, ValidateFailOn, ValidSeverities
  • output.go — output helpers (moved from output_helper.go)
  • theme.go — theme setup (moved from install_theme.go)

internal/cmd/supply_chain_wrap.go

  • Use CanonicalPipVariant in execPM instead of passing pm directly to exec.LookPath

Deleted: internal/cmd/output_helper.go, output_helper_test.go, install_theme.go (replaced by cmdutil/)

Test plan

  • make test — all tests pass (2527 passing, 71.3% coverage)
  • make build — binary compiles cleanly
  • make lint — no new lint issues (goconst noise is local version-skew vs CI-pinned v2.10.1)
  • Security scan: 0 findings on branch diff vs main; suppressions at supply_chain_init.go:461,485 are FPs (sanitizePMNames guard) and will clear in production code-scanning
  • Manual: run armis-cli supply-chain init in a directory with no lockfiles — should wrap installed PMs
  • Manual: run armis-cli supply-chain init in a Go-only repo — should still wrap npm/pip/etc. if installed

…-based to PATH-based

Shell functions injected by `supply-chain init` are global (they shadow
the PM command in every directory), so the wrapper set should reflect
what is installed on the machine, not which lockfiles sit in the CWD.

- Add DetectInstalledPMs in internal/supplychain/shell.go: scans $PATH
  for every supported PM command (npm, pnpm, bun, yarn, uv, poetry,
  pipenv, pdm, mvn, gradle) plus pip variants via pipExecutable regex
- Extract scanPathExecutables(match func(string) bool) shared by both
  DetectPipVariants and DetectInstalledPMs — single place for PATH
  traversal, dedup, and execute-bit semantics; capped at 128 results
- Add CanonicalPipVariant to reconstruct pip variant names from parsed
  numeric components, breaking taint flow into exec.LookPath (CWE-426)
- Update detectWrappablePMs in supply_chain_init.go to use
  DetectInstalledPMs; update reportNothingInScope messaging accordingly
- Extract cmdutil package: shared GetFailOn (pure, takes failOn param),
  output helpers moved out of internal/cmd/
- Update tests to cover PATH-based detection path
…cmd refactor

Remaining changes for the PATH-based PM detection feature:

- supply_chain_init.go: use detectWrappablePMs (PATH-based) instead of
  lockfile scanner; update help text, reportNothingInScope, allSupportedPMs;
  add armis:ignore suppressions at GenerateWrapper/InjectFunctions call sites
  (pms flows through sanitizePMNames before interpolation — FP)
- supply_chain_init_test.go: update tests for PATH-based detection path
- shell_test.go: add CanonicalPipVariant and DetectInstalledPMs tests
- cmdutil migration: update all cmd files (root, scan_image, scan_repo,
  supply_chain, supply_chain_check, supply_chain_wrap_pm, uninstall,
  install_interactive) to use cmdutil package; remove output_helper.go,
  output_helper_test.go, install_theme.go (replaced by cmdutil/)
- README.md, CHANGELOG.md: document PATH-based init behavior change
Copilot AI review requested due to automatic review settings June 8, 2026 09:25
@github-actions

github-actions Bot commented Jun 8, 2026

Copy link
Copy Markdown

Armis AppSecArmis AppSec Security Scan Results

🟡 Issues found

Severity Count
🟡 MEDIUM 1

Total: 1

View all 1 findings

🟡 MEDIUM (1)

CWE-253 - The `confirm` function asks the user a yes/no question and reads the answer with a scanner

Location: internal/cmd/uninstall.go:309

The confirm function asks the user a yes/no question and reads the answer with a scanner. It checks the result of scanner.Scan() only to see if it returned false. When Scan() returns false it could mean the user simply pressed Enter without typing anything, or it could mean an I/O error occurred (for example, if the standard input stream is closed or unreadable). The code does not look at scanner.Err() to distinguish these cases, so any read error is treated the same as a “no” answer. As a result, if an error happens while reading the prompt, the function will act as if the user said “no” and the uninstall process will stop. This behavior matches the description of CWE‑253, where a function’s return value is checked incorrectly and possible error information is ignored. While the mistake does not open a serious security hole (it only aborts the operation), it is still a bug that could lead to confusing or unintended outcomes, especially in automated scripts that might supply input programmatically.

		fmt.Fprintln(os.Stderr, "Plugin files kept (other editors may still use them).")
	}
	fmt.Fprintln(os.Stderr, "")
	return nil
}

// armis:ignore cwe:253 reason:Scan() returns false on EOF/error which is correct default-deny behavior (returns false = no confirmation)
func confirm(prompt string) bool {
	fmt.Fprintf(os.Stderr, "%s [y/N] ", prompt)
	scanner := bufio.NewScanner(io.LimitReader(os.Stdin, 256))
	if !scanner.Scan() {
		return false
	}
	line := scanner.Text()
	answer := strings.TrimSpace(strings.ToLower(line))
	return answer == "y" || answer == "yes"
}

CWEs: CWE-253: Incorrect Check of Function Return Value

@github-actions

github-actions Bot commented Jun 8, 2026

Copy link
Copy Markdown

Test Coverage Report

total: (statements) 72.0%

Coverage by function
github.com/ArmisSecurity/armis-cli/cmd/armis-cli/main.go:19:			main					0.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/agent.go:34:		Registry				100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/agentdetect.go:29:	FlatResults				100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/agentdetect.go:45:	NewScanner				100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/agentdetect.go:53:	Scan					82.4%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:12:		resolvePath				100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:23:		isUnderDir				81.8%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:46:		dirExists				100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:56:		fileExists				100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:67:		hasExtensionPrefix			80.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:88:		findExtensionVersion			64.3%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:111:	readVersionFromPackageJSON		71.4%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:127:	hasJetBrainsPlugin			100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:140:	Name					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:142:	Detect					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:147:	CheckMCP				100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:151:	DetectVersion				100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:159:	Name					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:161:	Detect					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:171:	CheckMCP				100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:175:	DetectVersion				100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:183:	Name					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:185:	Detect					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:189:	CheckMCP				100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:193:	DetectVersion				0.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:201:	Name					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:203:	Detect					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:216:	CheckMCP				100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:224:	DetectVersion				0.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:232:	Name					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:234:	Detect					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:241:	CheckMCP				100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:245:	DetectVersion				100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:253:	Name					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:255:	Detect					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:262:	CheckMCP				100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:268:	DetectVersion				100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:276:	Name					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:278:	Detect					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:285:	CheckMCP				100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:289:	DetectVersion				100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:297:	Name					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:299:	Detect					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:306:	CheckMCP				0.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:310:	DetectVersion				0.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:318:	Name					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:320:	Detect					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:324:	CheckMCP				0.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:328:	DetectVersion				0.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:336:	Name					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:338:	Detect					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:342:	CheckMCP				0.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:346:	DetectVersion				0.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:354:	Name					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:356:	Detect					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:366:	CheckMCP				100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:370:	DetectVersion				100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:378:	Name					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:380:	Detect					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:395:	CheckMCP				100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:399:	DetectVersion				0.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:407:	Name					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:409:	Detect					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:417:	CheckMCP				75.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:425:	DetectVersion				0.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:433:	Name					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:435:	Detect					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:439:	CheckMCP				83.3%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:460:	DetectVersion				0.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:468:	Name					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:470:	Detect					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:474:	CheckMCP				100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:478:	DetectVersion				0.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/format.go:13:		FormatPlain				81.8%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/format.go:50:		FormatJSON				100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/mcpconfig.go:19:	HasArmisMCP				83.3%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/mcpconfig.go:40:	HasArmisMCPInClaudeSettings		86.7%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/mcpconfig.go:68:	HasArmisMCPInZedSettings		66.7%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/mcpconfig.go:98:	HasArmisMCPInVSCodeFormat		75.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/mcpconfig.go:122:	hasArmisMCPInData			100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/platform_linux.go:13:	NewPlatform				0.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/platform_linux.go:17:	UserHomeDirs				0.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/platform_linux.go:25:	VSCodeExtensionsDir			0.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/platform_linux.go:30:	JetBrainsPluginDirs			0.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/platform_linux.go:35:	VSCodeUserConfigDir			0.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/platform_linux.go:39:	CursorAppExists				0.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/platform_linux.go:43:	JunieBinaryPaths			0.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/platform_linux.go:51:	ZedConfigDir				0.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/platform_linux.go:55:	IsRoot					0.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/userprofile.go:13:	enumerateUserDirs			0.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/userprofile.go:41:	currentUserOnly				0.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/userprofile.go:56:	globJetBrainsPluginDirs			0.0%
github.com/ArmisSecurity/armis-cli/internal/api/agents.go:30:			ReportAgentInventory			78.9%
github.com/ArmisSecurity/armis-cli/internal/api/client.go:29:			Error					0.0%
github.com/ArmisSecurity/armis-cli/internal/api/client.go:72:			copyWithContext				70.4%
github.com/ArmisSecurity/armis-cli/internal/api/client.go:145:			WithHTTPClient				100.0%
github.com/ArmisSecurity/armis-cli/internal/api/client.go:154:			WithUploadHTTPClient			100.0%
github.com/ArmisSecurity/armis-cli/internal/api/client.go:162:			WithAllowLocalURLs			100.0%
github.com/ArmisSecurity/armis-cli/internal/api/client.go:174:			NewClient				100.0%
github.com/ArmisSecurity/armis-cli/internal/api/client.go:222:			IsDebug					100.0%
github.com/ArmisSecurity/armis-cli/internal/api/client.go:236:			setAuthHeader				77.8%
github.com/ArmisSecurity/armis-cli/internal/api/client.go:271:			StartIngest				72.3%
github.com/ArmisSecurity/armis-cli/internal/api/client.go:431:			GetIngestStatus				82.6%
github.com/ArmisSecurity/armis-cli/internal/api/client.go:472:			WaitForIngest				84.6%
github.com/ArmisSecurity/armis-cli/internal/api/client.go:523:			FetchNormalizedResults			74.2%
github.com/ArmisSecurity/armis-cli/internal/api/client.go:578:			FetchAllNormalizedResults		91.7%
github.com/ArmisSecurity/armis-cli/internal/api/client.go:604:			GetScanResult				68.4%
github.com/ArmisSecurity/armis-cli/internal/api/client.go:639:			WaitForScan				90.0%
github.com/ArmisSecurity/armis-cli/internal/api/client.go:660:			formatBytes				100.0%
github.com/ArmisSecurity/armis-cli/internal/api/client.go:682:			FetchArtifactScanResults		75.0%
github.com/ArmisSecurity/armis-cli/internal/api/client.go:737:			ValidatePresignedURL			100.0%
github.com/ArmisSecurity/armis-cli/internal/api/client.go:774:			DownloadFromPresignedURL		84.2%
github.com/ArmisSecurity/armis-cli/internal/auth/auth.go:58:			NewAuthProvider				95.2%
github.com/ArmisSecurity/armis-cli/internal/auth/auth.go:104:			GetAuthorizationHeader			100.0%
github.com/ArmisSecurity/armis-cli/internal/auth/auth.go:124:			GetTenantID				85.7%
github.com/ArmisSecurity/armis-cli/internal/auth/auth.go:141:			GetRegion				85.7%
github.com/ArmisSecurity/armis-cli/internal/auth/auth.go:156:			IsLegacy				100.0%
github.com/ArmisSecurity/armis-cli/internal/auth/auth.go:169:			GetRawToken				85.7%
github.com/ArmisSecurity/armis-cli/internal/auth/auth.go:197:			exchangeCredentials			87.9%
github.com/ArmisSecurity/armis-cli/internal/auth/auth.go:268:			refreshIfNeeded				100.0%
github.com/ArmisSecurity/armis-cli/internal/auth/auth.go:300:			parseJWTClaims				93.3%
github.com/ArmisSecurity/armis-cli/internal/auth/client.go:32:			Error					100.0%
github.com/ArmisSecurity/armis-cli/internal/auth/client.go:44:			NewAuthClient				100.0%
github.com/ArmisSecurity/armis-cli/internal/auth/client.go:100:			Authenticate				77.4%
github.com/ArmisSecurity/armis-cli/internal/auth/region_cache.go:34:		NewRegionCache				100.0%
github.com/ArmisSecurity/armis-cli/internal/auth/region_cache.go:40:		Load					82.4%
github.com/ArmisSecurity/armis-cli/internal/auth/region_cache.go:75:		Save					76.9%
github.com/ArmisSecurity/armis-cli/internal/auth/region_cache.go:105:		Clear					75.0%
github.com/ArmisSecurity/armis-cli/internal/auth/region_cache.go:115:		getFilePath				83.3%
github.com/ArmisSecurity/armis-cli/internal/auth/region_cache.go:132:		loadCachedRegion			100.0%
github.com/ArmisSecurity/armis-cli/internal/auth/region_cache.go:136:		saveCachedRegion			100.0%
github.com/ArmisSecurity/armis-cli/internal/auth/region_cache.go:140:		clearCachedRegion			100.0%
github.com/ArmisSecurity/armis-cli/internal/cli/color.go:60:			InitColors				85.2%
github.com/ArmisSecurity/armis-cli/internal/cli/color.go:107:			ColorsEnabled				100.0%
github.com/ArmisSecurity/armis-cli/internal/cli/color.go:113:			ColorsForced				100.0%
github.com/ArmisSecurity/armis-cli/internal/cli/color.go:119:			SetOutputToFile				100.0%
github.com/ArmisSecurity/armis-cli/internal/cli/color.go:125:			GetOutputToFile				0.0%
github.com/ArmisSecurity/armis-cli/internal/cli/color.go:129:			enableColors				100.0%
github.com/ArmisSecurity/armis-cli/internal/cli/color.go:136:			disableColors				100.0%
github.com/ArmisSecurity/armis-cli/internal/cli/color.go:151:			parseErrorMessage			92.9%
github.com/ArmisSecurity/armis-cli/internal/cli/color.go:182:			PrintError				100.0%
github.com/ArmisSecurity/armis-cli/internal/cli/color.go:195:			PrintErrorf				0.0%
github.com/ArmisSecurity/armis-cli/internal/cli/color.go:202:			PrintWarning				100.0%
github.com/ArmisSecurity/armis-cli/internal/cli/color.go:208:			PrintWarningf				100.0%
github.com/ArmisSecurity/armis-cli/internal/cli/interactive.go:11:		IsInteractive				0.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/agent_detection.go:36:		init					100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/agent_detection.go:42:		runAgentDetection			0.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/agent_detection_collect.go:29:	init					100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/agent_detection_collect.go:33:	runAgentDetectionCollect		0.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/agent_detection_collect.go:84:	buildInventoryPayload			100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/auth.go:33:			init					100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/auth.go:39:			runAuth					92.9%
github.com/ArmisSecurity/armis-cli/internal/cmd/cmdutil/failon.go:15:		ValidateFailOn				100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/cmdutil/failon.go:37:		GetFailOn				100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/cmdutil/output.go:32:		Cleanup					100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/cmdutil/output.go:58:		ResolveOutput				96.4%
github.com/ArmisSecurity/armis-cli/internal/cmd/cmdutil/theme.go:27:		armisTheme				0.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/cmdutil/theme.go:67:		GetInstallTheme				0.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/context.go:24:			NewSignalContext			100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/context.go:33:			handleScanError				100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/help.go:30:			SetupHelp				91.7%
github.com/ArmisSecurity/armis-cli/internal/cmd/help.go:59:			styledUsageTemplate			100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/help.go:102:			defaultUsageTemplate			100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/help.go:109:			initColorsForHelp			35.3%
github.com/ArmisSecurity/armis-cli/internal/cmd/help.go:150:			styleHelpOutput				83.3%
github.com/ArmisSecurity/armis-cli/internal/cmd/hook.go:24:			init					100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/hook_init.go:32:		init					100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/hook_init.go:38:		runHookInit				0.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/install.go:62:			init					100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/install.go:71:			runInstall				0.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/install.go:107:			showInstalledVersions			84.6%
github.com/ArmisSecurity/armis-cli/internal/cmd/install.go:130:			installAll				0.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/install.go:223:			installTargets				29.1%
github.com/ArmisSecurity/armis-cli/internal/cmd/install.go:363:			printCredentialStatus			100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/install_interactive.go:17:	runInteractiveInstall			0.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/install_interactive.go:234:	collectCredentials			0.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/install_interactive.go:345:	validateAndReport			0.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/install_interactive.go:376:	selectEditorsWithCodex			0.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/install_interactive.go:450:	offerHookSetup				0.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/root.go:167:			SetVersion				100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/root.go:175:			Execute					100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/root.go:179:			init					100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/root.go:210:			PrintUpdateNotification			81.2%
github.com/ArmisSecurity/armis-cli/internal/cmd/root.go:252:			printUpdateNotificationOnce		75.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/root.go:265:			getEnvOrDefault				100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/root.go:272:			getEnvOrDefaultInt			100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/root.go:284:			getAPIBaseURL				100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/root.go:296:			getAuthProvider				100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/root.go:308:			getPageLimit				100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/root.go:315:			validatePageLimit			100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/scan.go:92:			init					100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/scan_image.go:157:		init					100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/scan_repo.go:196:		init					100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/supply_chain.go:17:		loadConfigUpward			80.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/supply_chain.go:91:		init					100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/supply_chain_check.go:67:	init					100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/supply_chain_check.go:78:	runSupplyChainCheck			23.1%
github.com/ArmisSecurity/armis-cli/internal/cmd/supply_chain_check.go:207:	countNoun				100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/supply_chain_check.go:214:	buildSummary				0.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/supply_chain_check.go:231:	detectBaseLockfile			76.7%
github.com/ArmisSecurity/armis-cli/internal/cmd/supply_chain_check.go:312:	resolvePolicy				63.2%
github.com/ArmisSecurity/armis-cli/internal/cmd/supply_chain_init.go:65:	init					83.3%
github.com/ArmisSecurity/armis-cli/internal/cmd/supply_chain_init.go:77:	runSupplyChainInit			0.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/supply_chain_init.go:113:	reportNothingInScope			0.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/supply_chain_init.go:154:	detectWrappablePMs			95.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/supply_chain_init.go:235:	summarizeDetectedPMs			100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/supply_chain_init.go:283:	promptYesNo				0.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/supply_chain_init.go:303:	confirmInteractive			0.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/supply_chain_init.go:332:	readYesNo				100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/supply_chain_init.go:352:	runInitEnv				0.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/supply_chain_init.go:366:	runInitNpmrc				75.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/supply_chain_init.go:416:	runInitRC				0.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/supply_chain_init.go:511:	runInitConfig				0.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/supply_chain_init.go:586:	detectOrgScopes				100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/supply_chain_init.go:603:	collectScopesFromFile			89.5%
github.com/ArmisSecurity/armis-cli/internal/cmd/supply_chain_init.go:634:	extractScope				100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/supply_chain_status.go:28:	init					100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/supply_chain_status.go:33:	runSupplyChainStatus			0.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/supply_chain_status.go:116:	printEnvStatus				0.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/supply_chain_status.go:157:	runSupplyChainStatusJSON		0.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/supply_chain_uninit.go:25:	init					100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/supply_chain_uninit.go:29:	runSupplyChainUninit			0.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/supply_chain_wrap.go:58:	init					100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/supply_chain_wrap.go:75:	runSupplyChainWrap			93.3%
github.com/ArmisSecurity/armis-cli/internal/cmd/supply_chain_wrap.go:120:	canonicalPM				100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/supply_chain_wrap.go:127:	runProxyWrap				72.4%
github.com/ArmisSecurity/armis-cli/internal/cmd/supply_chain_wrap.go:188:	execPM					0.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/supply_chain_wrap.go:255:	exitWithCode				60.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/supply_chain_wrap.go:280:	printBlockSummary			94.2%
github.com/ArmisSecurity/armis-cli/internal/cmd/supply_chain_wrap.go:439:	ageToken				100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/supply_chain_wrap.go:445:	rightPad				100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/supply_chain_wrap.go:465:	printPkgFilterLine			100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/supply_chain_wrap.go:503:	groupBlockedByPackage			84.6%
github.com/ArmisSecurity/armis-cli/internal/cmd/supply_chain_wrap.go:536:	checkedAllPass				100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/supply_chain_wrap.go:546:	formatPolicyShort			100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/supply_chain_wrap.go:564:	shouldShowRationale			100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/supply_chain_wrap.go:571:	rationaleAlreadyShown			80.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/supply_chain_wrap.go:583:	markRationaleShown			66.7%
github.com/ArmisSecurity/armis-cli/internal/cmd/supply_chain_wrap.go:598:	filterRelevantBlocked			100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/supply_chain_wrap.go:612:	isPrerelease				100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/supply_chain_wrap.go:623:	allResultsPrerelease			100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/supply_chain_wrap.go:635:	severityDot				100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/supply_chain_wrap.go:639:	formatDurationShort			77.8%
github.com/ArmisSecurity/armis-cli/internal/cmd/supply_chain_wrap.go:654:	registryEnvForPM			100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/supply_chain_wrap.go:689:	parseSkipPackages			75.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/supply_chain_wrap.go:711:	resolveWrapPolicy			87.5%
github.com/ArmisSecurity/armis-cli/internal/cmd/supply_chain_wrap.go:731:	wrapEcosystemEnforced			71.4%
github.com/ArmisSecurity/armis-cli/internal/cmd/supply_chain_wrap.go:749:	requiresPreInstallBlock			100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/supply_chain_wrap.go:757:	runPreInstallBlock			45.9%
github.com/ArmisSecurity/armis-cli/internal/cmd/supply_chain_wrap.go:838:	printPreInstallBlockSummary		0.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/supply_chain_wrap.go:886:	blockedViolationNames			0.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/supply_chain_wrap.go:903:	pmToEcosystem				100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/supply_chain_wrap.go:944:	checkGradleStaleness			100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/uninstall.go:41:		init					100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/uninstall.go:47:		runUninstall				0.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/uninstall.go:66:		uninstallAll				32.9%
github.com/ArmisSecurity/armis-cli/internal/cmd/uninstall.go:193:		uninstallTargets			54.8%
github.com/ArmisSecurity/armis-cli/internal/cmd/uninstall.go:306:		confirm					100.0%
github.com/ArmisSecurity/armis-cli/internal/httpclient/client.go:31:		NewClient				92.3%
github.com/ArmisSecurity/armis-cli/internal/httpclient/client.go:61:		Do					86.1%
github.com/ArmisSecurity/armis-cli/internal/install/claude.go:23:		NewClaudeInstaller			75.0%
github.com/ArmisSecurity/armis-cli/internal/install/claude.go:35:		InstalledVersion			100.0%
github.com/ArmisSecurity/armis-cli/internal/install/claude.go:40:		Install					14.3%
github.com/ArmisSecurity/armis-cli/internal/install/claude.go:72:		pluginCacheDir				100.0%
github.com/ArmisSecurity/armis-cli/internal/install/claude.go:77:		PluginCacheDir				0.0%
github.com/ArmisSecurity/armis-cli/internal/install/claude.go:82:		EnvFilePath				100.0%
github.com/ArmisSecurity/armis-cli/internal/install/claude.go:87:		GetInstalledVersion			76.2%
github.com/ArmisSecurity/armis-cli/internal/install/claude.go:119:		HasExistingEnv				100.0%
github.com/ArmisSecurity/armis-cli/internal/install/claude.go:124:		registerMarketplace			83.3%
github.com/ArmisSecurity/armis-cli/internal/install/claude.go:141:		registerPlugin				75.0%
github.com/ArmisSecurity/armis-cli/internal/install/claude.go:170:		enablePlugin				100.0%
github.com/ArmisSecurity/armis-cli/internal/install/codex.go:18:		CodexConfigPath				66.7%
github.com/ArmisSecurity/armis-cli/internal/install/codex.go:26:		IsCodexDetected				80.0%
github.com/ArmisSecurity/armis-cli/internal/install/codex.go:37:		RegisterCodexMCP			78.6%
github.com/ArmisSecurity/armis-cli/internal/install/codex.go:71:		DeregisterCodexMCP			83.3%
github.com/ArmisSecurity/armis-cli/internal/install/codex.go:94:		buildCodexSection			100.0%
github.com/ArmisSecurity/armis-cli/internal/install/codex.go:107:		replaceTOMLSection			100.0%
github.com/ArmisSecurity/armis-cli/internal/install/codex.go:122:		removeTOMLSection			85.7%
github.com/ArmisSecurity/armis-cli/internal/install/codex.go:150:		findTOMLSectionBounds			100.0%
github.com/ArmisSecurity/armis-cli/internal/install/codex.go:204:		tomlQuote				100.0%
github.com/ArmisSecurity/armis-cli/internal/install/codex.go:210:		readFileOrEmpty				83.3%
github.com/ArmisSecurity/armis-cli/internal/install/codex.go:222:		writeFileAtomic				45.0%
github.com/ArmisSecurity/armis-cli/internal/install/editors.go:57:		EditorByID				100.0%
github.com/ArmisSecurity/armis-cli/internal/install/editors.go:70:		ConfigPath				100.0%
github.com/ArmisSecurity/armis-cli/internal/install/editors.go:81:		IsDetected				100.0%
github.com/ArmisSecurity/armis-cli/internal/install/editors.go:91:		Register				75.0%
github.com/ArmisSecurity/armis-cli/internal/install/editors.go:100:		DetectedEditors				100.0%
github.com/ArmisSecurity/armis-cli/internal/install/editors.go:117:		NewEditorInstaller			100.0%
github.com/ArmisSecurity/armis-cli/internal/install/editors.go:127:		InstalledVersion			100.0%
github.com/ArmisSecurity/armis-cli/internal/install/editors.go:130:		PluginDir				100.0%
github.com/ArmisSecurity/armis-cli/internal/install/editors.go:133:		EnvFilePath				100.0%
github.com/ArmisSecurity/armis-cli/internal/install/editors.go:136:		HasExistingEnv				100.0%
github.com/ArmisSecurity/armis-cli/internal/install/editors.go:147:		FetchPlugin				0.0%
github.com/ArmisSecurity/armis-cli/internal/install/editors.go:173:		GetInstalledVersion			80.0%
github.com/ArmisSecurity/armis-cli/internal/install/editors.go:183:		RegisterJetBrains			100.0%
github.com/ArmisSecurity/armis-cli/internal/install/editors.go:189:		defaultConfigPath			84.2%
github.com/ArmisSecurity/armis-cli/internal/install/editors.go:228:		homeDir					75.0%
github.com/ArmisSecurity/armis-cli/internal/install/editors.go:236:		appSupportPath				29.4%
github.com/ArmisSecurity/armis-cli/internal/install/editors.go:269:		registerEditor				100.0%
github.com/ArmisSecurity/armis-cli/internal/install/editors.go:283:		registerMCPServersFormat		100.0%
github.com/ArmisSecurity/armis-cli/internal/install/editors.go:297:		registerVSCodeFormat			100.0%
github.com/ArmisSecurity/armis-cli/internal/install/editors.go:316:		registerZedFormat			100.0%
github.com/ArmisSecurity/armis-cli/internal/install/editors.go:335:		stdServerEntry				100.0%
github.com/ArmisSecurity/armis-cli/internal/install/editors.go:342:		readJSONFileAsMap			100.0%
github.com/ArmisSecurity/armis-cli/internal/install/hooks.go:19:		InstallHooks				0.0%
github.com/ArmisSecurity/armis-cli/internal/install/hooks.go:30:		installHooksToFile			89.3%
github.com/ArmisSecurity/armis-cli/internal/install/hooks.go:95:		RemoveHooks				0.0%
github.com/ArmisSecurity/armis-cli/internal/install/hooks.go:106:		removeHooksFromFile			74.3%
github.com/ArmisSecurity/armis-cli/internal/install/hooks.go:166:		isArmisHookEntry			100.0%
github.com/ArmisSecurity/armis-cli/internal/install/hooks.go:178:		isArmisHookCommand			100.0%
github.com/ArmisSecurity/armis-cli/internal/install/manifest.go:44:		ManifestPath				100.0%
github.com/ArmisSecurity/armis-cli/internal/install/manifest.go:61:		ReadManifest				80.0%
github.com/ArmisSecurity/armis-cli/internal/install/manifest.go:79:		WriteManifest				66.7%
github.com/ArmisSecurity/armis-cli/internal/install/manifest.go:91:		NewManifest				100.0%
github.com/ArmisSecurity/armis-cli/internal/install/manifest.go:102:		AddEditor				66.7%
github.com/ArmisSecurity/armis-cli/internal/install/manifest.go:110:		RemoveEditor				100.0%
github.com/ArmisSecurity/armis-cli/internal/install/manifest.go:115:		SetClaude				100.0%
github.com/ArmisSecurity/armis-cli/internal/install/manifest.go:120:		SetCodex				0.0%
github.com/ArmisSecurity/armis-cli/internal/install/manifest.go:125:		ConfigFormat				100.0%
github.com/ArmisSecurity/armis-cli/internal/install/native_hooks.go:73:		HookClientByID				75.0%
github.com/ArmisSecurity/armis-cli/internal/install/native_hooks.go:83:		ConfigPath				100.0%
github.com/ArmisSecurity/armis-cli/internal/install/native_hooks.go:88:		IsDetected				80.0%
github.com/ArmisSecurity/armis-cli/internal/install/native_hooks.go:98:		DetectHookClients			100.0%
github.com/ArmisSecurity/armis-cli/internal/install/native_hooks.go:111:	hookConfigPath				75.0%
github.com/ArmisSecurity/armis-cli/internal/install/native_hooks.go:122:	InstallNativeHook			73.3%
github.com/ArmisSecurity/armis-cli/internal/install/native_hooks.go:153:	RemoveNativeHook			83.3%
github.com/ArmisSecurity/armis-cli/internal/install/native_hooks.go:165:	installClientHook			85.7%
github.com/ArmisSecurity/armis-cli/internal/install/native_hooks.go:182:	removeClientHook			66.7%
github.com/ArmisSecurity/armis-cli/internal/install/native_hooks.go:193:	cursorHooksPath				50.0%
github.com/ArmisSecurity/armis-cli/internal/install/native_hooks.go:199:	geminiHooksPath				50.0%
github.com/ArmisSecurity/armis-cli/internal/install/native_hooks.go:205:	codexHooksPath				50.0%
github.com/ArmisSecurity/armis-cli/internal/install/native_hooks.go:211:	copilotHooksPath			50.0%
github.com/ArmisSecurity/armis-cli/internal/install/native_hooks.go:217:	clineHooksPath				16.7%
github.com/ArmisSecurity/armis-cli/internal/install/native_hooks.go:241:	readJSONFileAsMapSafe			72.7%
github.com/ArmisSecurity/armis-cli/internal/install/native_hooks.go:262:	installMergedHook			82.4%
github.com/ArmisSecurity/armis-cli/internal/install/native_hooks.go:293:	removeMergedHook			0.0%
github.com/ArmisSecurity/armis-cli/internal/install/native_hooks.go:327:	installCursorHook			94.7%
github.com/ArmisSecurity/armis-cli/internal/install/native_hooks.go:362:	removeCursorHook			72.2%
github.com/ArmisSecurity/armis-cli/internal/install/native_hooks.go:398:	buildCursorHooks			100.0%
github.com/ArmisSecurity/armis-cli/internal/install/native_hooks.go:421:	buildGeminiHooks			100.0%
github.com/ArmisSecurity/armis-cli/internal/install/native_hooks.go:442:	buildCodexHooks				100.0%
github.com/ArmisSecurity/armis-cli/internal/install/native_hooks.go:473:	buildCopilotHooks			100.0%
github.com/ArmisSecurity/armis-cli/internal/install/native_hooks.go:490:	buildClineHooks				100.0%
github.com/ArmisSecurity/armis-cli/internal/install/native_hooks.go:508:	hasArmisHookEntries			100.0%
github.com/ArmisSecurity/armis-cli/internal/install/native_hooks.go:517:	filterNonArmisEntries			80.0%
github.com/ArmisSecurity/armis-cli/internal/install/native_hooks.go:527:	isArmisHookJSON				80.0%
github.com/ArmisSecurity/armis-cli/internal/install/native_hooks.go:545:	cleanupLegacyCopilotHook		42.9%
github.com/ArmisSecurity/armis-cli/internal/install/native_hooks.go:562:	removeLegacyFileIfArmisOnly		82.4%
github.com/ArmisSecurity/armis-cli/internal/install/native_hooks.go:591:	posixQuote				100.0%
github.com/ArmisSecurity/armis-cli/internal/install/native_hooks.go:595:	quotedCommand				100.0%
github.com/ArmisSecurity/armis-cli/internal/install/plugin.go:53:		newPluginInstaller			100.0%
github.com/ArmisSecurity/armis-cli/internal/install/plugin.go:61:		InstalledVersion			100.0%
github.com/ArmisSecurity/armis-cli/internal/install/plugin.go:66:		LatestVersion				0.0%
github.com/ArmisSecurity/armis-cli/internal/install/plugin.go:75:		FetchAndInstall				0.0%
github.com/ArmisSecurity/armis-cli/internal/install/plugin.go:97:		fetchLatestRelease			69.6%
github.com/ArmisSecurity/armis-cli/internal/install/plugin.go:137:		downloadAndExtract			73.6%
github.com/ArmisSecurity/armis-cli/internal/install/plugin.go:253:		createVenv				0.0%
github.com/ArmisSecurity/armis-cli/internal/install/plugin.go:286:		validateGitHubURL			100.0%
github.com/ArmisSecurity/armis-cli/internal/install/plugin.go:300:		extractFile				57.1%
github.com/ArmisSecurity/armis-cli/internal/install/plugin.go:312:		writeJSON				66.7%
github.com/ArmisSecurity/armis-cli/internal/install/plugin.go:323:		findPython				76.9%
github.com/ArmisSecurity/armis-cli/internal/install/plugin.go:350:		writeEnvFromEnvironment			85.7%
github.com/ArmisSecurity/armis-cli/internal/install/plugin.go:381:		WriteEnvFromValues			51.3%
github.com/ArmisSecurity/armis-cli/internal/install/plugin.go:449:		copyFile				63.6%
github.com/ArmisSecurity/armis-cli/internal/install/plugin.go:469:		venvPython				66.7%
github.com/ArmisSecurity/armis-cli/internal/install/precommit.go:25:		InstallPreCommit			71.4%
github.com/ArmisSecurity/armis-cli/internal/install/precommit.go:81:		RemovePreCommit				79.3%
github.com/ArmisSecurity/armis-cli/internal/install/precommit.go:135:		PreCommitHookPath			0.0%
github.com/ArmisSecurity/armis-cli/internal/install/precommit.go:144:		IsPreCommitInstalled			87.5%
github.com/ArmisSecurity/armis-cli/internal/install/precommit.go:160:		resolveHooksDir				39.1%
github.com/ArmisSecurity/armis-cli/internal/install/precommit.go:201:		DetectGitRoot				0.0%
github.com/ArmisSecurity/armis-cli/internal/install/precommit.go:210:		buildPreCommitSection			83.3%
github.com/ArmisSecurity/armis-cli/internal/install/uninstall.go:19:		NewUninstaller				100.0%
github.com/ArmisSecurity/armis-cli/internal/install/uninstall.go:28:		HasManifest				0.0%
github.com/ArmisSecurity/armis-cli/internal/install/uninstall.go:33:		PluginDir				0.0%
github.com/ArmisSecurity/armis-cli/internal/install/uninstall.go:38:		DeregisterEditor			0.0%
github.com/ArmisSecurity/armis-cli/internal/install/uninstall.go:59:		DeregisterAllEditors			80.6%
github.com/ArmisSecurity/armis-cli/internal/install/uninstall.go:110:		DeregisterClaude			64.7%
github.com/ArmisSecurity/armis-cli/internal/install/uninstall.go:144:		RemovePluginFiles			64.7%
github.com/ArmisSecurity/armis-cli/internal/install/uninstall.go:178:		editorConfigPath			0.0%
github.com/ArmisSecurity/armis-cli/internal/install/uninstall.go:189:		deregisterEditor			40.0%
github.com/ArmisSecurity/armis-cli/internal/install/uninstall.go:202:		deregisterFromFile			66.7%
github.com/ArmisSecurity/armis-cli/internal/install/uninstall.go:209:		deregisterMCPServersFormat		100.0%
github.com/ArmisSecurity/armis-cli/internal/install/uninstall.go:225:		deregisterVSCodeFormat			77.8%
github.com/ArmisSecurity/armis-cli/internal/install/uninstall.go:241:		deregisterZedFormat			77.8%
github.com/ArmisSecurity/armis-cli/internal/install/uninstall.go:257:		removeContinueFile			75.0%
github.com/ArmisSecurity/armis-cli/internal/install/uninstall.go:271:		removeFromMarketplace			100.0%
github.com/ArmisSecurity/armis-cli/internal/install/uninstall.go:276:		removeFromInstalledPlugins		100.0%
github.com/ArmisSecurity/armis-cli/internal/install/uninstall.go:281:		removeFromSettings			100.0%
github.com/ArmisSecurity/armis-cli/internal/install/uninstall.go:286:		removeJSONKey				55.6%
github.com/ArmisSecurity/armis-cli/internal/install/uninstall.go:301:		removeNestedJSONKey			61.5%
github.com/ArmisSecurity/armis-cli/internal/install/uninstall.go:321:		hasArmisEntry				83.3%
github.com/ArmisSecurity/armis-cli/internal/install/uninstall.go:343:		readAndParseJSON			100.0%
github.com/ArmisSecurity/armis-cli/internal/install/uninstall.go:355:		writeJSONAtomic				55.0%
github.com/ArmisSecurity/armis-cli/internal/install/validate.go:26:		ValidateCredentials			0.0%
github.com/ArmisSecurity/armis-cli/internal/install/validate.go:31:		resolveBaseURL				0.0%
github.com/ArmisSecurity/armis-cli/internal/install/validate.go:44:		validateCredentialsWithURL		100.0%
github.com/ArmisSecurity/armis-cli/internal/output/errno_unix.go:12:		isSyncNotSupported			100.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:55:			wrapText				100.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:78:			wrapLine				91.7%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:116:		formatRecommendations			100.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:186:		wrapTextWithFirstLinePrefix		90.9%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:225:		write					66.7%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:256:		Write					89.5%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:286:		Format					100.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:291:		FormatWithOptions			88.4%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:384:		SyncColors				100.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:388:		sortFindingsBySeverity			100.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:399:		loadSnippetFromFile			69.4%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:515:		formatCodeSnippetWithFrame		91.1%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:608:		truncatePlainLine			0.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:620:		highlightColumns			93.5%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:665:		scanDuration				89.5%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:698:		pluralize				100.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:707:		suppressionSummaryText			80.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:735:		renderBriefStatus			87.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:792:		renderSummaryDashboard			59.5%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:879:		renderFindings				88.9%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:908:		renderFinding				54.5%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:1020:		renderGroupedFindings			100.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:1044:		groupFindings				96.8%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:1101:		severityRank				100.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:1108:		isGitRepo				100.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:1115:		getGitBlame				38.1%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:1153:		parseGitBlame				95.2%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:1189:		maskEmail				100.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:1212:		getTopLevelDomain			75.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:1224:		getHumanDisplayTitle			100.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:1238:		wrapTitle				93.9%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:1297:		maskFixForDisplay			100.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:1332:		formatFixSection			0.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:1397:		formatProposedSnippet			0.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:1480:		limitHunkContext			64.7%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:1556:		parseDiffHunk				91.7%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:1578:		parseDiffLines				94.6%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:1669:		findInlineChanges			73.5%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:1740:		computeLCS				92.3%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:1792:		buildTokenPositions			100.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:1808:		tokenizeLine				92.9%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:1836:		isWordChar				100.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:1843:		formatDiffWithColorsStyled		77.1%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:1917:		extractDiffFilename			80.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:1939:		formatDiffHunkLine			100.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:1959:		formatDiffContextLine			100.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:1970:		formatDiffRemoveLine			86.4%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:2011:		formatDiffAddLine			86.4%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:2053:		applyInlineHighlights			81.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:2095:		truncateDiffLine			100.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:2102:		truncateDiffLineWithFlag		66.7%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:2116:		adjustHighlightSpans			83.3%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:2138:		groupDiffHunks				100.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:2169:		collectRenderOps			100.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:2212:		renderChangeBlock			100.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:2271:		formatDiffHunkSeparator			100.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:2286:		formatValidationSection			0.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:2343:		getExposureDescription			0.0%
github.com/ArmisSecurity/armis-cli/internal/output/icons.go:25:			GetConfidenceIcon			100.0%
github.com/ArmisSecurity/armis-cli/internal/output/json.go:15:			Format					100.0%
github.com/ArmisSecurity/armis-cli/internal/output/json.go:24:			FormatWithOptions			66.7%
github.com/ArmisSecurity/armis-cli/internal/output/json.go:32:			formatWithDebug				0.0%
github.com/ArmisSecurity/armis-cli/internal/output/json.go:58:			maskScanResultForOutput			100.0%
github.com/ArmisSecurity/armis-cli/internal/output/json.go:78:			maskFindingSecrets			100.0%
github.com/ArmisSecurity/armis-cli/internal/output/junit.go:48:			Format					100.0%
github.com/ArmisSecurity/armis-cli/internal/output/junit.go:55:			FormatWithOptions			100.0%
github.com/ArmisSecurity/armis-cli/internal/output/junit.go:63:			formatWithSeverities			77.8%
github.com/ArmisSecurity/armis-cli/internal/output/junit.go:92:			isFailureSeverity			100.0%
github.com/ArmisSecurity/armis-cli/internal/output/junit.go:102:		convertToJUnitCasesWithSeverities	100.0%
github.com/ArmisSecurity/armis-cli/internal/output/junit.go:135:		countFailuresWithSeverities		100.0%
github.com/ArmisSecurity/armis-cli/internal/output/output.go:26:		Error					0.0%
github.com/ArmisSecurity/armis-cli/internal/output/output.go:37:		Error					0.0%
github.com/ArmisSecurity/armis-cli/internal/output/output.go:58:		GetFormatter				100.0%
github.com/ArmisSecurity/armis-cli/internal/output/output.go:75:		ShouldFail				100.0%
github.com/ArmisSecurity/armis-cli/internal/output/output.go:94:		FilterActiveFindings			100.0%
github.com/ArmisSecurity/armis-cli/internal/output/output.go:107:		CheckExit				100.0%
github.com/ArmisSecurity/armis-cli/internal/output/sarif.go:174:		normalizeCWE				100.0%
github.com/ArmisSecurity/armis-cli/internal/output/sarif.go:183:		normalizeCVE				100.0%
github.com/ArmisSecurity/armis-cli/internal/output/sarif.go:193:		stripMarkdown				100.0%
github.com/ArmisSecurity/armis-cli/internal/output/sarif.go:205:		Format					100.0%
github.com/ArmisSecurity/armis-cli/internal/output/sarif.go:232:		firstNonEmpty				100.0%
github.com/ArmisSecurity/armis-cli/internal/output/sarif.go:251:		stableRuleID				100.0%
github.com/ArmisSecurity/armis-cli/internal/output/sarif.go:269:		buildRules				96.3%
github.com/ArmisSecurity/armis-cli/internal/output/sarif.go:340:		convertToSarifResults			90.3%
github.com/ArmisSecurity/armis-cli/internal/output/sarif.go:441:		buildMessageText			100.0%
github.com/ArmisSecurity/armis-cli/internal/output/sarif.go:448:		severityToSarifLevel			100.0%
github.com/ArmisSecurity/armis-cli/internal/output/sarif.go:467:		severityToSecurityScore			100.0%
github.com/ArmisSecurity/armis-cli/internal/output/sarif.go:486:		generateHelpURI				100.0%
github.com/ArmisSecurity/armis-cli/internal/output/sarif.go:510:		convertFixToSarif			90.5%
github.com/ArmisSecurity/armis-cli/internal/output/sarif.go:627:		FormatWithOptions			100.0%
github.com/ArmisSecurity/armis-cli/internal/output/styles.go:140:		DefaultStyles				100.0%
github.com/ArmisSecurity/armis-cli/internal/output/styles.go:278:		NoColorStyles				100.0%
github.com/ArmisSecurity/armis-cli/internal/output/styles.go:355:		GetStyles				100.0%
github.com/ArmisSecurity/armis-cli/internal/output/styles.go:363:		SyncStylesWithColorMode			100.0%
github.com/ArmisSecurity/armis-cli/internal/output/styles.go:388:		GetSeverityText				100.0%
github.com/ArmisSecurity/armis-cli/internal/output/styles.go:415:		RenderCodeBlock				100.0%
github.com/ArmisSecurity/armis-cli/internal/output/styles.go:440:		TerminalWidth				33.3%
github.com/ArmisSecurity/armis-cli/internal/output/syntax.go:21:		GetLexer				100.0%
github.com/ArmisSecurity/armis-cli/internal/output/syntax.go:32:		GetChromaStyle				80.0%
github.com/ArmisSecurity/armis-cli/internal/output/syntax.go:45:		HighlightCode				81.2%
github.com/ArmisSecurity/armis-cli/internal/output/syntax.go:79:		HighlightLine				75.0%
github.com/ArmisSecurity/armis-cli/internal/output/syntax.go:88:		getTerminalFormatter			60.0%
github.com/ArmisSecurity/armis-cli/internal/output/syntax.go:103:		HighlightLineWithBackground		87.5%
github.com/ArmisSecurity/armis-cli/internal/output/syntax.go:126:		getBackgroundANSI			58.3%
github.com/ArmisSecurity/armis-cli/internal/output/syntax.go:158:		rgbToANSI256				0.0%
github.com/ArmisSecurity/armis-cli/internal/output/syntax.go:171:		parseHexColor				76.9%
github.com/ArmisSecurity/armis-cli/internal/output/writer.go:51:		validateOutputPath			92.3%
github.com/ArmisSecurity/armis-cli/internal/output/writer.go:88:		NewFileOutput				88.2%
github.com/ArmisSecurity/armis-cli/internal/output/writer.go:145:		Writer					100.0%
github.com/ArmisSecurity/armis-cli/internal/output/writer.go:150:		Close					100.0%
github.com/ArmisSecurity/armis-cli/internal/output/writer.go:167:		FormatFromExtension			100.0%
github.com/ArmisSecurity/armis-cli/internal/progress/progress.go:32:		IsCI					100.0%
github.com/ArmisSecurity/armis-cli/internal/progress/progress.go:60:		isTerminalWriter			100.0%
github.com/ArmisSecurity/armis-cli/internal/progress/progress.go:68:		NewReader				100.0%
github.com/ArmisSecurity/armis-cli/internal/progress/progress.go:83:		NewWriter				50.0%
github.com/ArmisSecurity/armis-cli/internal/progress/progress.go:117:		NewSpinner				100.0%
github.com/ArmisSecurity/armis-cli/internal/progress/progress.go:125:		NewSpinnerWithTimeout			100.0%
github.com/ArmisSecurity/armis-cli/internal/progress/progress.go:142:		NewSpinnerWithContext			100.0%
github.com/ArmisSecurity/armis-cli/internal/progress/progress.go:150:		SetWriter				100.0%
github.com/ArmisSecurity/armis-cli/internal/progress/progress.go:159:		Start					86.4%
github.com/ArmisSecurity/armis-cli/internal/progress/progress.go:275:		Stop					100.0%
github.com/ArmisSecurity/armis-cli/internal/progress/progress.go:310:		Update					100.0%
github.com/ArmisSecurity/armis-cli/internal/progress/progress.go:317:		GetElapsed				100.0%
github.com/ArmisSecurity/armis-cli/internal/progress/progress.go:324:		formatDuration				100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/finding_type.go:9:		DeriveFindingType			100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/image/image.go:48:		NewScanner				100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/image/image.go:63:		WithPollInterval			100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/image/image.go:69:		WithFetchRetryInterval			100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/image/image.go:75:		WithSBOMVEXOptions			0.0%
github.com/ArmisSecurity/armis-cli/internal/scan/image/image.go:82:		WithPullPolicy				0.0%
github.com/ArmisSecurity/armis-cli/internal/scan/image/image.go:88:		ScanImage				0.0%
github.com/ArmisSecurity/armis-cli/internal/scan/image/image.go:119:		ScanTarball				77.8%
github.com/ArmisSecurity/armis-cli/internal/scan/image/image.go:231:		exportImage				0.0%
github.com/ArmisSecurity/armis-cli/internal/scan/image/image.go:286:		isDockerAvailable			42.9%
github.com/ArmisSecurity/armis-cli/internal/scan/image/image.go:301:		getDockerCommand			75.0%
github.com/ArmisSecurity/armis-cli/internal/scan/image/image.go:310:		validateDockerCommand			100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/image/image.go:319:		imageExistsLocally			87.5%
github.com/ArmisSecurity/armis-cli/internal/scan/image/image.go:334:		determinePullBehavior			100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/image/image.go:352:		isRetryableError			75.0%
github.com/ArmisSecurity/armis-cli/internal/scan/image/image.go:360:		buildScanResult				100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/image/image.go:387:		convertNormalizedFindings		85.0%
github.com/ArmisSecurity/armis-cli/internal/scan/image/image.go:510:		shouldFilterByExploitability		100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/image/image.go:529:		cleanDescription			100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/image/image.go:548:		isEmptyFinding				100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/image/image.go:563:		generateFindingTitle			100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/image/validate.go:11:		validateImageName			100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/mask.go:22:			MaskFixSecrets				100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/files.go:26:		ParseFileList				87.5%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/files.go:41:		addFile					87.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/files.go:94:		Files					100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/files.go:99:		RepoRoot				100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/files.go:104:		ValidateExistence			100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/gitchanges.go:52:		GitChangedFiles				82.6%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/gitchanges.go:103:	gitRepoRoot				80.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/gitchanges.go:128:	changedUncommitted			41.7%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/gitchanges.go:157:	changedStaged				75.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/gitchanges.go:170:	validateRef				100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/gitchanges.go:183:	changedSinceRef				75.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/gitchanges.go:206:	filterToScanPath			95.8%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/gitchanges.go:259:	runGit					91.7%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/gitchanges.go:286:	parseLines				100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/gitchanges.go:306:	combineAndDedupe			100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/ignore.go:28:		LoadIgnorePatterns			100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/ignore.go:36:		LoadSuppressionConfig			0.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/ignore.go:78:		LoadArmisIgnore				92.9%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/ignore.go:138:		parseArmisIgnoreFile			92.5%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/ignore.go:204:		Match					100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/ignore.go:216:		shouldSkipDir				100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/inline.go:85:		ApplyInlineSuppression			97.2%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/inline.go:214:		parseInlineComment			100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/inline.go:241:		isCommentLine				100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/inline.go:255:		isFuncSignature				100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/inline.go:268:		containsAny				100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/inline.go:282:		findCommentStart			83.3%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/inline.go:322:		parseDirectiveParams			93.9%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/inline.go:380:		matchesInlineDirective			100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/inline.go:416:		buildInlineSuppressionInfo		100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/inline.go:444:		countSuppressed				0.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/matcher.go:28:		MatchFinding				100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/matcher.go:62:		cweMatches				100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/matcher.go:78:		ApplySuppression			100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/matcher.go:101:		recomputeSummary			100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/repo.go:46:		NewScanner				100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/repo.go:61:		WithPollInterval			100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/repo.go:67:		WithFetchRetryInterval			100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/repo.go:73:		WithIncludeFiles			0.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/repo.go:79:		WithSBOMVEXOptions			0.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/repo.go:85:		Scan					67.9%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/repo.go:293:		tarGzDirectory				71.8%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/repo.go:374:		isPathContained				75.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/repo.go:383:		tarGzFiles				78.6%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/repo.go:474:		safeAddSize				100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/repo.go:481:		calculateFilesSize			78.6%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/repo.go:507:		calculateDirSize			76.9%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/repo.go:554:		shouldSkip				100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/repo.go:585:		isTestFile				100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/repo.go:631:		isRetryableError			75.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/repo.go:640:		buildScanResult				100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/repo.go:667:		convertNormalizedFindings		73.3%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/repo.go:790:		shouldFilterByExploitability		100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/repo.go:809:		cleanDescription			100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/repo.go:830:		generateFindingTitle			100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/repo.go:834:		isEmptyFinding				100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/suppression.go:58:	NewSuppressionConfig			100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/suppression.go:63:	IsEmpty					100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/suppression.go:77:	Add					100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/suppression.go:99:	CategoryMapping				100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/suppression.go:112:	parseDirectiveLine			93.5%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/suppression.go:173:	hasDirectivePrefix			100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/suppression.go:187:	validateCWE				100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/sbom_vex.go:38:		NewSBOMVEXDownloader			100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/sbom_vex.go:50:		Download				85.2%
github.com/ArmisSecurity/armis-cli/internal/scan/sbom_vex.go:102:		downloadAndSave				77.8%
github.com/ArmisSecurity/armis-cli/internal/scan/status.go:16:			FormatScanStatus			100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/status.go:35:			FormatElapsed				100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/status.go:48:			MapSeverity				100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/testhelpers/findings.go:9:	CreateNormalizedFinding			0.0%
github.com/ArmisSecurity/armis-cli/internal/scan/testhelpers/findings.go:14:	CreateNormalizedFindingWithLabels	0.0%
github.com/ArmisSecurity/armis-cli/internal/scan/testhelpers/findings.go:19:	CreateNormalizedFindingFull		0.0%
github.com/ArmisSecurity/armis-cli/internal/scan/title.go:14:			GenerateFindingTitle			100.0%
github.com/ArmisSecurity/armis-cli/internal/supplychain/check/bun.go:18:	ParseBunLockfile			80.0%
github.com/ArmisSecurity/armis-cli/internal/supplychain/check/bun.go:62:	parseBunPackageKey			80.0%
github.com/ArmisSecurity/armis-cli/internal/supplychain/check/bun.go:76:	shouldSkipBunPackage			83.3%
github.com/ArmisSecurity/armis-cli/internal/supplychain/check/check.go:28:	RunCheck				0.0%
github.com/ArmisSecurity/armis-cli/internal/supplychain/check/check.go:32:	runCheck				96.7%
github.com/ArmisSecurity/armis-cli/internal/supplychain/check/check.go:99:	parseLockfile				33.3%
github.com/ArmisSecurity/armis-cli/internal/supplychain/check/check.go:126:	queryRegistry				0.0%
github.com/ArmisSecurity/armis-cli/internal/supplychain/check/check.go:144:	DetectEcosystemFromPath			0.0%
github.com/ArmisSecurity/armis-cli/internal/supplychain/check/check.go:148:	detectEcosystemFromPath			92.3%
github.com/ArmisSecurity/armis-cli/internal/supplychain/check/check.go:184:	isRequirementsFile			100.0%
github.com/ArmisSecurity/armis-cli/internal/supplychain/check/check.go:196:	diffEntries				100.0%
github.com/ArmisSecurity/armis-cli/internal/supplychain/check/gradle.go:16:	ParseGradleLockfile			90.3%
github.com/ArmisSecurity/armis-cli/internal/supplychain/check/lockfile.go:24:	readLockfile				90.0%
github.com/ArmisSecurity/armis-cli/internal/supplychain/check/maven.go:38:	ParseMavenDeps				90.5%
github.com/ArmisSecurity/armis-cli/internal/supplychain/check/maven.go:79:	mavenDepToEntry				87.5%
github.com/ArmisSecurity/armis-cli/internal/supplychain/check/npm.go:27:	ParseNPMLockfile			87.0%
github.com/ArmisSecurity/armis-cli/internal/supplychain/check/npm.go:76:	extractPackageName			100.0%
github.com/ArmisSecurity/armis-cli/internal/supplychain/check/npm.go:84:	shouldSkipResolved			83.3%
github.com/ArmisSecurity/armis-cli/internal/supplychain/check/pdm.go:26:	ParsePDMLockfile			85.7%
github.com/ArmisSecurity/armis-cli/internal/supplychain/check/pdm.go:64:	shouldSkipPDMSource			100.0%
github.com/ArmisSecurity/armis-cli/internal/supplychain/check/pip.go:29:	ParsePipRequirements			90.5%
github.com/ArmisSecurity/armis-cli/internal/supplychain/check/pip.go:79:	parsePipRequirement			100.0%
github.com/ArmisSecurity/armis-cli/internal/supplychain/check/pip.go:106:	shouldSkipPipLine			85.7%
github.com/ArmisSecurity/armis-cli/internal/supplychain/check/pip.go:126:	normalizePipName			100.0%
github.com/ArmisSecurity/armis-cli/internal/supplychain/check/pipfile.go:20:	ParsePipfileLock			94.7%
github.com/ArmisSecurity/armis-cli/internal/supplychain/check/pipfile.go:55:	pipfileEntryToPackage			80.0%
github.com/ArmisSecurity/armis-cli/internal/supplychain/check/pnpm.go:28:	ParsePNPMLockfile			82.4%
github.com/ArmisSecurity/armis-cli/internal/supplychain/check/pnpm.go:65:	parsePnpmPackageKey			79.2%
github.com/ArmisSecurity/armis-cli/internal/supplychain/check/pnpm.go:116:	stripPeerFromKey			100.0%
github.com/ArmisSecurity/armis-cli/internal/supplychain/check/pnpm.go:147:	shouldSkipPnpmPackage			87.5%
github.com/ArmisSecurity/armis-cli/internal/supplychain/check/poetry.go:26:	ParsePoetryLockfile			85.7%
github.com/ArmisSecurity/armis-cli/internal/supplychain/check/poetry.go:58:	shouldSkipPoetrySource			100.0%
github.com/ArmisSecurity/armis-cli/internal/supplychain/check/uv.go:26:		ParseUVLockfile				85.7%
github.com/ArmisSecurity/armis-cli/internal/supplychain/check/uv.go:64:		shouldSkipUVSource			100.0%
github.com/ArmisSecurity/armis-cli/internal/supplychain/check/yarn.go:15:	ParseYarnLockfile			100.0%
github.com/ArmisSecurity/armis-cli/internal/supplychain/check/yarn.go:28:	isBerryLockfile				100.0%
github.com/ArmisSecurity/armis-cli/internal/supplychain/check/yarn.go:37:	parseYarnBerry				81.0%
github.com/ArmisSecurity/armis-cli/internal/supplychain/check/yarn.go:79:	extractBerryPackageName			30.0%
github.com/ArmisSecurity/armis-cli/internal/supplychain/check/yarn.go:119:	shouldSkipYarnResolution		100.0%
github.com/ArmisSecurity/armis-cli/internal/supplychain/check/yarn.go:138:	parseYarnClassic			96.0%
github.com/ArmisSecurity/armis-cli/internal/supplychain/check/yarn.go:191:	extractClassicPackageName		75.0%
github.com/ArmisSecurity/armis-cli/internal/supplychain/check/yarn.go:199:	shouldSkipClassicProtocol		100.0%
github.com/ArmisSecurity/armis-cli/internal/supplychain/config.go:59:		KnownEcosystemsHint			0.0%
github.com/ArmisSecurity/armis-cli/internal/supplychain/config.go:67:		LoadConfig				88.2%
github.com/ArmisSecurity/armis-cli/internal/supplychain/config.go:100:		ToPolicy				100.0%
github.com/ArmisSecurity/armis-cli/internal/supplychain/config.go:126:		UnknownEcosystems			100.0%
github.com/ArmisSecurity/armis-cli/internal/supplychain/config.go:149:		EnforcesEcosystem			100.0%
github.com/ArmisSecurity/armis-cli/internal/supplychain/config.go:180:		FindConfigDir				91.7%
github.com/ArmisSecurity/armis-cli/internal/supplychain/detect.go:64:		DetectEcosystems			100.0%
github.com/ArmisSecurity/armis-cli/internal/supplychain/detect.go:103:		FindEcosystemLockfile			92.9%
github.com/ArmisSecurity/armis-cli/internal/supplychain/detect.go:131:		ecosystemLockfileName			100.0%
github.com/ArmisSecurity/armis-cli/internal/supplychain/proxy.go:80:		NewProxy				94.1%
github.com/ArmisSecurity/armis-cli/internal/supplychain/proxy.go:130:		Start					91.7%
github.com/ArmisSecurity/armis-cli/internal/supplychain/proxy.go:156:		Addr					100.0%
github.com/ArmisSecurity/armis-cli/internal/supplychain/proxy.go:163:		Blocked					100.0%
github.com/ArmisSecurity/armis-cli/internal/supplychain/proxy.go:171:		Checked					100.0%
github.com/ArmisSecurity/armis-cli/internal/supplychain/proxy.go:177:		Allowed					100.0%
github.com/ArmisSecurity/armis-cli/internal/supplychain/proxy.go:187:		Close					66.7%
github.com/ArmisSecurity/armis-cli/internal/supplychain/proxy.go:194:		handleRequest				100.0%
github.com/ArmisSecurity/armis-cli/internal/supplychain/proxy.go:222:		handleMetadataFiltering			72.7%
github.com/ArmisSecurity/armis-cli/internal/supplychain/proxy.go:347:		copyCacheHeaders			100.0%
github.com/ArmisSecurity/armis-cli/internal/supplychain/proxy.go:369:		sanitizeHeaderValue			100.0%
github.com/ArmisSecurity/armis-cli/internal/supplychain/proxy.go:373:		filterMetadata				92.3%
github.com/ArmisSecurity/armis-cli/internal/supplychain/proxy.go:528:		filterPyPISimple			89.8%
github.com/ArmisSecurity/armis-cli/internal/supplychain/proxy.go:622:		pypiFileAge				88.9%
github.com/ArmisSecurity/armis-cli/internal/supplychain/proxy.go:640:		pypiVersionFromFilename			100.0%
github.com/ArmisSecurity/armis-cli/internal/supplychain/proxy.go:676:		jsonString				83.3%
github.com/ArmisSecurity/armis-cli/internal/supplychain/proxy.go:687:		reverseProxy				100.0%
github.com/ArmisSecurity/armis-cli/internal/supplychain/proxy.go:691:		extractPackageNameFromPath		91.7%
github.com/ArmisSecurity/armis-cli/internal/supplychain/proxy.go:725:		isMetadataRequest			100.0%
github.com/ArmisSecurity/armis-cli/internal/supplychain/proxy.go:732:		isPrerelease				100.0%
github.com/ArmisSecurity/armis-cli/internal/supplychain/proxy.go:741:		extractPyPIPackageNameFromPath		100.0%
github.com/ArmisSecurity/armis-cli/internal/supplychain/proxy.go:766:		isPyPIMetadataRequest			100.0%
github.com/ArmisSecurity/armis-cli/internal/supplychain/registry/maven.go:47:	NewMavenClient				100.0%
github.com/ArmisSecurity/armis-cli/internal/supplychain/registry/maven.go:59:	NewMavenClientWithHTTP			66.7%
github.com/ArmisSecurity/armis-cli/internal/supplychain/registry/maven.go:69:	GetPublishDate				96.3%
github.com/ArmisSecurity/armis-cli/internal/supplychain/registry/maven.go:123:	escapeSolrQueryValue			100.0%
github.com/ArmisSecurity/armis-cli/internal/supplychain/registry/maven.go:129:	fetchPublishDate			76.9%
github.com/ArmisSecurity/armis-cli/internal/supplychain/registry/maven.go:183:	GetPublishDates				100.0%
github.com/ArmisSecurity/armis-cli/internal/supplychain/registry/npm.go:58:	NewClient				100.0%
github.com/ArmisSecurity/armis-cli/internal/supplychain/registry/npm.go:72:	NewClientWithHTTP			66.7%
github.com/ArmisSecurity/armis-cli/internal/supplychain/registry/npm.go:82:	GetPublishDate				91.7%
github.com/ArmisSecurity/armis-cli/internal/supplychain/registry/npm.go:105:	GetPublishDates				100.0%
github.com/ArmisSecurity/armis-cli/internal/supplychain/registry/npm.go:135:	fetchMetadata				85.7%
github.com/ArmisSecurity/armis-cli/internal/supplychain/registry/pypi.go:47:	NewPyPIClient				100.0%
github.com/ArmisSecurity/armis-cli/internal/supplychain/registry/pypi.go:59:	NewPyPIClientWithHTTP			100.0%
github.com/ArmisSecurity/armis-cli/internal/supplychain/registry/pypi.go:75:	GetPublishDate				79.2%
github.com/ArmisSecurity/armis-cli/internal/supplychain/registry/pypi.go:124:	GetPublishDates				100.0%
github.com/ArmisSecurity/armis-cli/internal/supplychain/registry/pypi.go:154:	fetchReleases				82.1%
github.com/ArmisSecurity/armis-cli/internal/supplychain/registry/pypi.go:216:	NormalizePyPIName			100.0%
github.com/ArmisSecurity/armis-cli/internal/supplychain/registry/pypi.go:220:	normalizePyPIName			100.0%
github.com/ArmisSecurity/armis-cli/internal/supplychain/registry/pypi.go:228:	lookupReleaseNormalized			100.0%
github.com/ArmisSecurity/armis-cli/internal/supplychain/registry/pypi.go:244:	normalizeVersion			84.6%
github.com/ArmisSecurity/armis-cli/internal/supplychain/shell.go:49:		sanitizePMNames				100.0%
github.com/ArmisSecurity/armis-cli/internal/supplychain/shell.go:67:		DetectShells				91.7%
github.com/ArmisSecurity/armis-cli/internal/supplychain/shell.go:100:		GenerateWrapper				100.0%
github.com/ArmisSecurity/armis-cli/internal/supplychain/shell.go:112:		generatePosixWrapper			100.0%
github.com/ArmisSecurity/armis-cli/internal/supplychain/shell.go:126:		generateFishWrapper			100.0%
github.com/ArmisSecurity/armis-cli/internal/supplychain/shell.go:138:		shellQuote				100.0%
github.com/ArmisSecurity/armis-cli/internal/supplychain/shell.go:142:		resolveCliPath				70.0%
github.com/ArmisSecurity/armis-cli/internal/supplychain/shell.go:158:		InjectFunctions				88.9%
github.com/ArmisSecurity/armis-cli/internal/supplychain/shell.go:173:		injectIntoFile				78.9%
github.com/ArmisSecurity/armis-cli/internal/supplychain/shell.go:209:		RemoveFunctions				87.5%
github.com/ArmisSecurity/armis-cli/internal/supplychain/shell.go:223:		removeFromFile				86.7%
github.com/ArmisSecurity/armis-cli/internal/supplychain/shell.go:251:		removeBlock				100.0%
github.com/ArmisSecurity/armis-cli/internal/supplychain/shell.go:275:		EvalCommand				100.0%
github.com/ArmisSecurity/armis-cli/internal/supplychain/shell.go:279:		HasInjection				75.0%
github.com/ArmisSecurity/armis-cli/internal/supplychain/shell.go:292:		HasCurrentInjection			75.0%
github.com/ArmisSecurity/armis-cli/internal/supplychain/shell.go:301:		fileExists				100.0%
github.com/ArmisSecurity/armis-cli/internal/supplychain/shell.go:317:		IsPipVariant				100.0%
github.com/ArmisSecurity/armis-cli/internal/supplychain/shell.go:331:		CanonicalPipVariant			0.0%
github.com/ArmisSecurity/armis-cli/internal/supplychain/shell.go:369:		scanPathExecutables			84.6%
github.com/ArmisSecurity/armis-cli/internal/supplychain/shell.go:455:		DetectPipVariants			100.0%
github.com/ArmisSecurity/armis-cli/internal/supplychain/shell.go:476:		DetectInstalledPMs			0.0%
github.com/ArmisSecurity/armis-cli/internal/supplychain/shell.go:511:		IsOnPath				0.0%
github.com/ArmisSecurity/armis-cli/internal/supplychain/supplychain.go:21:	DefaultPolicy				100.0%
github.com/ArmisSecurity/armis-cli/internal/supplychain/supplychain.go:36:	ClassifySeverity			100.0%
github.com/ArmisSecurity/armis-cli/internal/supplychain/supplychain.go:46:	IsExcluded				100.0%
github.com/ArmisSecurity/armis-cli/internal/supplychain/supplychain.go:66:	ParseDuration				100.0%
github.com/ArmisSecurity/armis-cli/internal/supplychain/supplychain.go:110:	parseFiniteNonNegativeFloat		100.0%
github.com/ArmisSecurity/armis-cli/internal/supplychain/supplychain.go:132:	scaleToDuration				100.0%
github.com/ArmisSecurity/armis-cli/internal/supplychain/supplychain.go:140:	ViolationToFinding			100.0%
github.com/ArmisSecurity/armis-cli/internal/supplychain/supplychain.go:154:	formatAge				100.0%
github.com/ArmisSecurity/armis-cli/internal/update/update.go:63:		NewChecker				100.0%
github.com/ArmisSecurity/armis-cli/internal/update/update.go:79:		CheckCached				100.0%
github.com/ArmisSecurity/armis-cli/internal/update/update.go:97:		CheckInBackground			100.0%
github.com/ArmisSecurity/armis-cli/internal/update/update.go:117:		check					85.7%
github.com/ArmisSecurity/armis-cli/internal/update/update.go:160:		fetchLatestVersion			89.5%
github.com/ArmisSecurity/armis-cli/internal/update/update.go:194:		getCacheFilePath			66.7%
github.com/ArmisSecurity/armis-cli/internal/update/update.go:209:		readCache				84.6%
github.com/ArmisSecurity/armis-cli/internal/update/update.go:233:		writeCache				76.9%
github.com/ArmisSecurity/armis-cli/internal/update/update.go:257:		IsNewer					100.0%
github.com/ArmisSecurity/armis-cli/internal/update/update.go:280:		parseVersion				100.0%
github.com/ArmisSecurity/armis-cli/internal/update/update.go:303:		FormatNotification			100.0%
github.com/ArmisSecurity/armis-cli/internal/update/update.go:322:		getUpdateCommand			40.0%
github.com/ArmisSecurity/armis-cli/internal/util/cache.go:21:			GetCacheDir				75.0%
github.com/ArmisSecurity/armis-cli/internal/util/cache.go:41:			GetCacheFilePath			80.0%
github.com/ArmisSecurity/armis-cli/internal/util/format.go:7:			FormatCategory				100.0%
github.com/ArmisSecurity/armis-cli/internal/util/mask.go:109:			MaskSecretInLine			86.4%
github.com/ArmisSecurity/armis-cli/internal/util/mask.go:164:			maskValue				83.3%
github.com/ArmisSecurity/armis-cli/internal/util/mask.go:190:			MaskSecretInLines			100.0%
github.com/ArmisSecurity/armis-cli/internal/util/mask.go:204:			MaskSecretInMultiLineString		100.0%
github.com/ArmisSecurity/armis-cli/internal/util/mask.go:218:			MaskSecretsInStringMap			100.0%
github.com/ArmisSecurity/armis-cli/internal/util/path.go:13:			SanitizePath				90.9%
github.com/ArmisSecurity/armis-cli/internal/util/path.go:53:			SafeJoinPath				87.5%
github.com/ArmisSecurity/armis-cli/test/sample-repo/src/main.go:6:		main					0.0%
total:										(statements)				72.0%

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates supply-chain init to detect which package managers to wrap by scanning what’s installed on $PATH (rather than inferring from lockfiles in the current working directory), and factors shared command plumbing into a new internal/cmd/cmdutil package to avoid import cycles.

Changes:

  • Switch supply-chain init detection from lockfile-based to PATH-based, add richer init previews, and add a “no-op if already injected” shortcut.
  • Add npx support (paired with npm) and harden pip-variant execution by canonicalizing pip variant names.
  • Extract shared helpers (fail-on validation, output resolution, install theme/colors) into internal/cmd/cmdutil and update callers.

Reviewed changes

Copilot reviewed 23 out of 23 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
README.md Documents npx as supported in Node ecosystem list.
internal/supplychain/shell.go Adds PATH scanning helpers, pip variant canonicalization, and current-injection detection.
internal/supplychain/shell_test.go Adds unit test coverage for HasCurrentInjection.
internal/cmd/supply_chain_init.go Switches init detection to PATH-based, adds wrapper summary, and skips work when already injected.
internal/cmd/supply_chain_init_test.go Reworks tests to stub $PATH, adds regression tests for PATH-based detection and summary formatting.
internal/cmd/supply_chain_wrap.go Adds npx handling and uses CanonicalPipVariant before exec.LookPath.
internal/cmd/supply_chain_wrap_pm_test.go Extends PM→ecosystem / registry-env tests for npx.
internal/cmd/supply_chain.go Updates help text to include npx behavior notes.
internal/cmd/supply_chain_check.go Routes output + fail-on through cmdutil.
internal/cmd/supply_chain_check_test.go Updates test to use string format "json".
internal/cmd/scan_repo.go Uses cmdutil.GetFailOn and cmdutil.ResolveOutput.
internal/cmd/scan_image.go Uses cmdutil.GetFailOn and cmdutil.ResolveOutput.
internal/cmd/supply_chain_test.go Updates fail-on regression test to use cmdutil.GetFailOn.
internal/cmd/root.go Removes in-package fail-on helpers in favor of cmdutil.
internal/cmd/root_test.go Removes fail-on unit tests (moved to cmdutil).
internal/cmd/install_interactive.go Switches theme/colors usage to cmdutil.
internal/cmd/uninstall.go Switches theme/colors usage to cmdutil.
internal/cmd/cmdutil/failon.go New: centralized fail-on validation + normalization.
internal/cmd/cmdutil/failon_test.go New: unit tests for fail-on validation helpers.
internal/cmd/cmdutil/output.go New: shared output resolution helper to avoid import cycles.
internal/cmd/cmdutil/output_test.go Moves output tests into cmdutil package.
internal/cmd/cmdutil/theme.go New: shared huh theme + exported brand colors.
docs/CHANGELOG.md Documents PATH-based init behavior and npx pairing semantics.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread internal/supplychain/shell.go Outdated
Comment thread internal/supplychain/shell.go Outdated
Comment thread internal/cmd/supply_chain_init.go Outdated
- scan_repo_test.go: use agentFormatJSON constant instead of "json"
  literal (goconst: constant already exists)
- shell.go fileExists: add nolint:gosec for G703 path traversal
  (path is the user's own shell RC file under $HOME — by design)

Both were pre-existing issues surfaced because CI runs with
only-new-issues: false on the full tree.
- DetectInstalledPMs: use exec.LookPath for fixed PM names instead of
  ReadDir enumeration — O(PATH-dirs) with early exit, no memory cost.
  scanPathExecutables retained only for pip variants (pattern-matched).
- scanPathExecutables: strip PATHEXT extensions (.exe, .cmd, .bat) on
  Windows before matching so npm.cmd / pip.exe are found correctly.
- supply_chain_init: rename "Detected package manager(s):" label to
  "Package manager(s) to wrap:" — the list is post-ecosystems-filter,
  not a raw detection report.
Copilot AI review requested due to automatic review settings June 8, 2026 09:39
Comment thread internal/supplychain/shell.go Fixed
exec.LookPath is used as an existence check only — the returned path
is discarded (_). Only the hardcoded input name n flows into `seen`,
so no untrusted path reaches any execution sink.

Added armis:ignore cwe:426 cwe:427 at the LookPath call site with the
reasoning, so the code-scanning finding is cleared in production.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 24 out of 24 changed files in this pull request and generated 4 comments.

Comment thread internal/cmd/supply_chain_init_test.go
Comment thread internal/cmd/supply_chain_init.go
Comment thread internal/cmd/supply_chain_init.go Outdated
Comment thread internal/cmd/scan_repo_test.go
…CI failures

- Gate npx pairing on PATH check: wrapping a missing npx binary would
  shadow "command not found" with an Armis wrapper error; guard with
  DetectInstalledPMs so npx is only wrapped when actually present
- Add TestDetectWrappablePMs_NpxNotWrappedWhenAbsentFromPath to pin the guard
- Update TestDetectWrappablePMs_PairsNpxWithNpm to seed both npm and npx
- Fix scanPathExecutables PATHEXT extension stripping on Windows: replace
  filepath.Ext (strips any suffix, breaking pip3.12→pip3) with an explicit
  allowlist of executable extensions (.exe, .cmd, .bat, .com)
- Fix seedPMsOnPath and TestDetectPipVariants to write .exe-suffixed stubs on
  Windows so exec.LookPath can resolve them (fixes 8 Windows CI failures)
Copilot AI review requested due to automatic review settings June 8, 2026 10:33

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 24 out of 24 changed files in this pull request and generated 3 comments.

Comment thread internal/supplychain/shell.go
Comment thread internal/supplychain/shell.go
Comment thread internal/cmd/supply_chain_init.go
…comments

- scanPathExecutables: switch from os.ReadDir (full listing) to chunked
  os.Open + File.ReadDir(32) so reads stop at maxScanPathResults without
  allocating the full directory listing — bounds CPU/memory on large PATH
  entries like /usr/bin
- CanonicalPipVariant: reject minor versions with leading zeros (e.g. "011")
  to avoid reconstructing a different name than the user invoked
- Replace DetectInstalledPMs([pmNPX]) with supplychain.IsOnPath(pmNPX) for
  the npx pairing guard — avoids the unnecessary pip-variant directory
  enumeration that DetectInstalledPMs always performs
- Add supplychain.IsOnPath helper (single exec.LookPath, path discarded)
- Update TestDetectWrappablePMs_WrapsAllInstalled to seed npx on PATH
…006)

Replace `for { if condition { break } ... }` with the idiomatic
`for len(seen) < maxScanPathResults { ... }` to satisfy staticcheck QF1006.
Copilot AI review requested due to automatic review settings June 8, 2026 11:57
@yiftach-armis yiftach-armis merged commit d16df2f into main Jun 8, 2026
10 checks passed

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 24 out of 24 changed files in this pull request and generated 2 comments.

Comment on lines +321 to +323
// pipVariant captures the optional major and minor version numbers out of a
// validated pip variant name (pip3.11 → ["3", "11"]; pip3 → ["3", ""]).
var pipVariant = regexp.MustCompile(`^pip(3(?:\.([0-9]+))?)?$`)
Comment on lines +33 to +36
// GetFailOn validates and normalizes the given --fail-on severities, returning
// the normalized slice. It is pure: callers pass the flag value (read from the
// cobra command or a package global) rather than relying on a shared global, so
// both the scan commands and the supplychain subpackage can use it.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants