Skip to content

[PPSC-718] feat(scan): add inline armis:ignore comment suppression#170

Merged
yiftach-armis merged 2 commits into
mainfrom
feat/PPSC-718-inline-suppression
May 12, 2026
Merged

[PPSC-718] feat(scan): add inline armis:ignore comment suppression#170
yiftach-armis merged 2 commits into
mainfrom
feat/PPSC-718-inline-suppression

Conversation

@yiftach-armis
Copy link
Copy Markdown
Collaborator

@yiftach-armis yiftach-armis commented May 12, 2026

Related Issue

Type of Change

  • New feature (non-breaking change which adds functionality)

Problem

Developers need a way to suppress individual findings at the source line level, similar to how // nolint or # nosec work in other tools. The existing .armisignore file only supports project-wide suppression by severity, category, CWE, or rule ID.

Solution

Add inline armis:ignore comment directives that suppress findings on the annotated line (or the line below). Supports all major comment syntaxes (//, #, --, <!--, /*, ;), accepts scope parameters (category:, rule:, cwe:, severity:, reason:) in any order with AND logic, and integrates with both human and SARIF output formatters.

Security hardening includes quote-aware parsing to reject directives inside string literals (prevents bypass via URLs like "http://armis:ignore@..."), path traversal protection via SafeJoinPath, and a 10MB file size cap.

Testing

Automated Tests

  • Unit tests added/updated
  • All tests passing locally

Manual Testing

Verified via go test ./internal/scan/repo/... ./internal/output/... — all pass. Linter passes for changed files.

Reviewer Notes

  • The inline suppression runs after .armisignore suppression, only on non-suppressed findings
  • SARIF uses kind: "inSource" for inline and kind: "external" for .armisignore to differentiate suppression sources
  • Parameters are parsed order-independently (unlike a single ordered regex) to avoid silent scope-broadening when users write params in different order

Checklist

  • Code follows project style guidelines
  • Pre-commit hooks pass
  • Self-review performed
  • No new warnings generated

Copilot AI review requested due to automatic review settings May 12, 2026 08:20
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 12, 2026

Armis AppSecArmis AppSec Security Scan Results

🟡 Issues found

Severity Count
🔵 LOW 1

Total: 1

View all 1 findings

🔵 LOW (1)

CWE-253 - In the `ApplyInlineSuppression` function the file is opened with `os.Open` and later closed with `defer f.Close()`

Location: internal/scan/repo/inline.go:81

In the ApplyInlineSuppression function the file is opened with os.Open and later closed with defer f.Close(). The Close method returns an error, but the code deliberately ignores that return value (the comment //nolint:errcheck tells the linter not to warn). Because the error is not checked, any problem that occurs while closing the file – for example, a failure to write buffered data or a permission issue – will be hidden. This means the program could think the file was closed successfully when it was not, potentially leading to lost data or other unexpected behavior. The issue is not about malicious input reaching the code; it is about the missing check on the function’s return value. Adding a proper error check after f.Close() would make the problem go away.

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

Add support for suppressing findings via inline code comments.
Developers can now annotate source lines with `armis:ignore` directives
to suppress specific findings at the line level, complementing the
existing .armisignore file-level suppression.

Key features:
- Supports all major comment syntaxes (// # -- <!-- /* ;)
- Parameters in any order: category, rule, cwe, severity, reason
- AND logic: all specified params must match for suppression
- Rejects directives inside string literals to prevent bypass
- File content cached for performance across multiple findings
- SARIF output uses "inSource" kind for inline vs "external" for .armisignore

Security hardening:
- Path traversal protection via SafeJoinPath
- 10MB file size limit prevents memory exhaustion
- Quote-aware comment prefix detection prevents false positives
  from URLs like "http://armis:ignore@..." or string literals
@yiftach-armis yiftach-armis force-pushed the feat/PPSC-718-inline-suppression branch from 1a8c2c1 to dfce618 Compare May 12, 2026 08:23
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 12, 2026

Test Coverage Report

total: (statements) 77.3%

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:44:	NewScanner				100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/agentdetect.go:52:	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:44:		dirExists				100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:53:		fileExists				100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:63:		hasExtensionPrefix			80.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:82:		findExtensionVersion			64.3%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:104:	readVersionFromPackageJSON		71.4%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:119:	hasJetBrainsPlugin			100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:132:	Name					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:134:	Detect					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:139:	CheckMCP				100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:143:	DetectVersion				100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:151:	Name					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:153:	Detect					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:163:	CheckMCP				100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:167:	DetectVersion				100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:175:	Name					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:177:	Detect					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:181:	CheckMCP				100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:185:	DetectVersion				0.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:193:	Name					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:195:	Detect					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:205:	CheckMCP				100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:210:	DetectVersion				0.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:218:	Name					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:220:	Detect					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:227:	CheckMCP				100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:231:	DetectVersion				100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:239:	Name					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:241:	Detect					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:248:	CheckMCP				100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:254:	DetectVersion				100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:262:	Name					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:264:	Detect					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:271:	CheckMCP				100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:275:	DetectVersion				100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:283:	Name					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:285:	Detect					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:292:	CheckMCP				0.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:296:	DetectVersion				0.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:304:	Name					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:306:	Detect					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:310:	CheckMCP				0.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:314:	DetectVersion				0.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:322:	Name					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:324:	Detect					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:328:	CheckMCP				0.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:332:	DetectVersion				0.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:340:	Name					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:342:	Detect					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:352:	CheckMCP				100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:356:	DetectVersion				100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:364:	Name					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:366:	Detect					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:381:	CheckMCP				100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:385:	DetectVersion				0.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:393:	Name					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:395:	Detect					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:403:	CheckMCP				75.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:411:	DetectVersion				0.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:419:	Name					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:421:	Detect					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:425:	CheckMCP				83.3%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:445:	DetectVersion				0.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:453:	Name					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:455:	Detect					100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:459:	CheckMCP				100.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/detector.go:463:	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:49:		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:39:	HasArmisMCPInClaudeSettings		86.7%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/mcpconfig.go:66:	HasArmisMCPInZedSettings		66.7%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/mcpconfig.go:95:	HasArmisMCPInVSCodeFormat		66.7%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/mcpconfig.go:118:	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:24:	VSCodeExtensionsDir			0.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/platform_linux.go:28:	JetBrainsPluginDirs			0.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/platform_linux.go:32:	VSCodeUserConfigDir			0.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/platform_linux.go:36:	CursorAppExists				0.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/platform_linux.go:40:	JunieBinaryPaths			0.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/platform_linux.go:47:	ZedConfigDir				0.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/platform_linux.go:51:	IsRoot					0.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/userprofile.go:12:	enumerateUserDirs			0.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/userprofile.go:39:	currentUserOnly				0.0%
github.com/ArmisSecurity/armis-cli/internal/agentdetect/userprofile.go:53:	globJetBrainsPluginDirs			0.0%
github.com/ArmisSecurity/armis-cli/internal/api/agents.go:29:			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:270:			StartIngest				72.3%
github.com/ArmisSecurity/armis-cli/internal/api/client.go:429:			GetIngestStatus				82.6%
github.com/ArmisSecurity/armis-cli/internal/api/client.go:470:			WaitForIngest				84.6%
github.com/ArmisSecurity/armis-cli/internal/api/client.go:521:			FetchNormalizedResults			74.2%
github.com/ArmisSecurity/armis-cli/internal/api/client.go:576:			FetchAllNormalizedResults		91.7%
github.com/ArmisSecurity/armis-cli/internal/api/client.go:601:			GetScanResult				68.4%
github.com/ArmisSecurity/armis-cli/internal/api/client.go:636:			WaitForScan				90.0%
github.com/ArmisSecurity/armis-cli/internal/api/client.go:657:			formatBytes				100.0%
github.com/ArmisSecurity/armis-cli/internal/api/client.go:679:			FetchArtifactScanResults		75.0%
github.com/ArmisSecurity/armis-cli/internal/api/client.go:734:			ValidatePresignedURL			100.0%
github.com/ArmisSecurity/armis-cli/internal/api/client.go:770:			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:196:			exchangeCredentials			87.9%
github.com/ArmisSecurity/armis-cli/internal/auth/auth.go:267:			refreshIfNeeded				100.0%
github.com/ArmisSecurity/armis-cli/internal/auth/auth.go:297:			parseJWTClaims				93.3%
github.com/ArmisSecurity/armis-cli/internal/auth/client.go:29:			Error					100.0%
github.com/ArmisSecurity/armis-cli/internal/auth/client.go:41:			NewAuthClient				100.0%
github.com/ArmisSecurity/armis-cli/internal/auth/client.go:97:			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:74:		Save					76.9%
github.com/ArmisSecurity/armis-cli/internal/auth/region_cache.go:104:		Clear					75.0%
github.com/ArmisSecurity/armis-cli/internal/auth/region_cache.go:114:		getFilePath				83.3%
github.com/ArmisSecurity/armis-cli/internal/auth/region_cache.go:131:		loadCachedRegion			100.0%
github.com/ArmisSecurity/armis-cli/internal/auth/region_cache.go:135:		saveCachedRegion			100.0%
github.com/ArmisSecurity/armis-cli/internal/auth/region_cache.go:139:		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:201:			PrintWarning				100.0%
github.com/ArmisSecurity/armis-cli/internal/cli/color.go:206:			PrintWarningf				100.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:41:		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/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:58:			styledUsageTemplate			100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/help.go:101:			defaultUsageTemplate			100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/help.go:108:			initColorsForHelp			35.3%
github.com/ArmisSecurity/armis-cli/internal/cmd/help.go:149:			styleHelpOutput				83.3%
github.com/ArmisSecurity/armis-cli/internal/cmd/install.go:54:			init					100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/install.go:59:			runInstall				0.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/install.go:76:			showInstalledVersions			0.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/install.go:96:			installAll				0.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/install.go:144:			installTargets				0.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/install.go:225:			printCredentialStatus			0.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/output_helper.go:27:		Cleanup					100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/output_helper.go:53:		ResolveOutput				96.4%
github.com/ArmisSecurity/armis-cli/internal/cmd/root.go:149:			SetVersion				100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/root.go:157:			Execute					100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/root.go:161:			init					100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/root.go:192:			PrintUpdateNotification			81.2%
github.com/ArmisSecurity/armis-cli/internal/cmd/root.go:234:			printUpdateNotificationOnce		75.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/root.go:247:			getEnvOrDefault				100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/root.go:254:			getEnvOrDefaultInt			100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/root.go:264:			getAPIBaseURL				100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/root.go:277:			getAuthProvider				100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/root.go:289:			getPageLimit				100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/root.go:296:			validatePageLimit			100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/root.go:306:			validateFailOn				100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/root.go:324:			getFailOn				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:152:		init					100.0%
github.com/ArmisSecurity/armis-cli/internal/cmd/scan_repo.go:192:		init					100.0%
github.com/ArmisSecurity/armis-cli/internal/httpclient/client.go:31:		NewClient				100.0%
github.com/ArmisSecurity/armis-cli/internal/httpclient/client.go:57:		Do					86.1%
github.com/ArmisSecurity/armis-cli/internal/install/claude.go:23:		NewClaudeInstaller			100.0%
github.com/ArmisSecurity/armis-cli/internal/install/claude.go:32:		InstalledVersion			100.0%
github.com/ArmisSecurity/armis-cli/internal/install/claude.go:37:		Install					14.3%
github.com/ArmisSecurity/armis-cli/internal/install/claude.go:67:		pluginCacheDir				100.0%
github.com/ArmisSecurity/armis-cli/internal/install/claude.go:72:		EnvFilePath				100.0%
github.com/ArmisSecurity/armis-cli/internal/install/claude.go:77:		GetInstalledVersion			76.2%
github.com/ArmisSecurity/armis-cli/internal/install/claude.go:108:		HasExistingEnv				100.0%
github.com/ArmisSecurity/armis-cli/internal/install/claude.go:113:		registerMarketplace			83.3%
github.com/ArmisSecurity/armis-cli/internal/install/claude.go:129:		registerPlugin				75.0%
github.com/ArmisSecurity/armis-cli/internal/install/claude.go:157:		enablePlugin				100.0%
github.com/ArmisSecurity/armis-cli/internal/install/editors.go:52:		EditorByID				100.0%
github.com/ArmisSecurity/armis-cli/internal/install/editors.go:65:		ConfigPath				100.0%
github.com/ArmisSecurity/armis-cli/internal/install/editors.go:76:		IsDetected				80.0%
github.com/ArmisSecurity/armis-cli/internal/install/editors.go:86:		Register				75.0%
github.com/ArmisSecurity/armis-cli/internal/install/editors.go:95:		DetectedEditors				100.0%
github.com/ArmisSecurity/armis-cli/internal/install/editors.go:112:		NewEditorInstaller			100.0%
github.com/ArmisSecurity/armis-cli/internal/install/editors.go:121:		InstalledVersion			100.0%
github.com/ArmisSecurity/armis-cli/internal/install/editors.go:124:		PluginDir				100.0%
github.com/ArmisSecurity/armis-cli/internal/install/editors.go:127:		EnvFilePath				100.0%
github.com/ArmisSecurity/armis-cli/internal/install/editors.go:130:		HasExistingEnv				100.0%
github.com/ArmisSecurity/armis-cli/internal/install/editors.go:137:		FetchPlugin				0.0%
github.com/ArmisSecurity/armis-cli/internal/install/editors.go:150:		GetInstalledVersion			80.0%
github.com/ArmisSecurity/armis-cli/internal/install/editors.go:160:		RegisterJetBrains			100.0%
github.com/ArmisSecurity/armis-cli/internal/install/editors.go:166:		defaultConfigPath			86.7%
github.com/ArmisSecurity/armis-cli/internal/install/editors.go:198:		homeDir					75.0%
github.com/ArmisSecurity/armis-cli/internal/install/editors.go:206:		appSupportPath				29.4%
github.com/ArmisSecurity/armis-cli/internal/install/editors.go:237:		registerEditor				100.0%
github.com/ArmisSecurity/armis-cli/internal/install/editors.go:251:		registerMCPServersFormat		100.0%
github.com/ArmisSecurity/armis-cli/internal/install/editors.go:265:		registerVSCodeFormat			100.0%
github.com/ArmisSecurity/armis-cli/internal/install/editors.go:284:		registerZedFormat			100.0%
github.com/ArmisSecurity/armis-cli/internal/install/editors.go:303:		stdServerEntry				100.0%
github.com/ArmisSecurity/armis-cli/internal/install/editors.go:310:		readJSONFileAsMap			100.0%
github.com/ArmisSecurity/armis-cli/internal/install/plugin.go:47:		newPluginInstaller			100.0%
github.com/ArmisSecurity/armis-cli/internal/install/plugin.go:55:		InstalledVersion			100.0%
github.com/ArmisSecurity/armis-cli/internal/install/plugin.go:60:		FetchAndInstall				0.0%
github.com/ArmisSecurity/armis-cli/internal/install/plugin.go:86:		fetchLatestRelease			69.6%
github.com/ArmisSecurity/armis-cli/internal/install/plugin.go:126:		downloadAndExtract			73.6%
github.com/ArmisSecurity/armis-cli/internal/install/plugin.go:242:		createVenv				0.0%
github.com/ArmisSecurity/armis-cli/internal/install/plugin.go:271:		validateGitHubURL			100.0%
github.com/ArmisSecurity/armis-cli/internal/install/plugin.go:285:		extractFile				57.1%
github.com/ArmisSecurity/armis-cli/internal/install/plugin.go:297:		writeJSON				66.7%
github.com/ArmisSecurity/armis-cli/internal/install/plugin.go:308:		findPython				69.2%
github.com/ArmisSecurity/armis-cli/internal/install/plugin.go:333:		writeEnvFromEnvironment			85.7%
github.com/ArmisSecurity/armis-cli/internal/install/plugin.go:358:		writeHelperScript			0.0%
github.com/ArmisSecurity/armis-cli/internal/install/plugin.go:404:		venvPython				66.7%
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.1%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:380:		SyncColors				100.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:384:		sortFindingsBySeverity			100.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:395:		loadSnippetFromFile			69.4%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:507:		formatCodeSnippetWithFrame		91.1%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:600:		truncatePlainLine			0.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:612:		highlightColumns			93.5%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:657:		scanDuration				89.5%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:690:		pluralize				100.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:699:		suppressionSummaryText			80.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:727:		renderBriefStatus			87.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:784:		renderSummaryDashboard			59.5%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:871:		renderFindings				88.9%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:900:		renderFinding				54.5%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:1012:		renderGroupedFindings			100.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:1036:		groupFindings				96.8%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:1093:		severityRank				100.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:1100:		isGitRepo				100.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:1107:		getGitBlame				38.1%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:1144:		parseGitBlame				95.2%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:1180:		maskEmail				100.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:1203:		getTopLevelDomain			75.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:1215:		getHumanDisplayTitle			100.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:1229:		wrapTitle				93.9%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:1288:		maskFixForDisplay			100.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:1323:		formatFixSection			0.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:1388:		formatProposedSnippet			0.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:1471:		limitHunkContext			64.7%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:1547:		parseDiffHunk				91.7%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:1569:		parseDiffLines				94.6%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:1660:		findInlineChanges			73.5%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:1731:		computeLCS				92.3%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:1783:		buildTokenPositions			100.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:1799:		tokenizeLine				92.9%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:1827:		isWordChar				100.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:1834:		formatDiffWithColorsStyled		77.1%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:1908:		extractDiffFilename			80.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:1930:		formatDiffHunkLine			100.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:1950:		formatDiffContextLine			100.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:1961:		formatDiffRemoveLine			86.4%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:2002:		formatDiffAddLine			86.4%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:2044:		applyInlineHighlights			81.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:2086:		truncateDiffLine			100.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:2093:		truncateDiffLineWithFlag		66.7%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:2107:		adjustHighlightSpans			83.3%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:2129:		groupDiffHunks				100.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:2160:		collectRenderOps			100.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:2203:		renderChangeBlock			100.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:2262:		formatDiffHunkSeparator			100.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:2277:		formatValidationSection			0.0%
github.com/ArmisSecurity/armis-cli/internal/output/human.go:2334:		getExposureDescription			0.0%
github.com/ArmisSecurity/armis-cli/internal/output/icons.go:24:			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			85.7%
github.com/ArmisSecurity/armis-cli/internal/output/junit.go:89:			isFailureSeverity			100.0%
github.com/ArmisSecurity/armis-cli/internal/output/junit.go:99:			convertToJUnitCasesWithSeverities	100.0%
github.com/ArmisSecurity/armis-cli/internal/output/junit.go:131:		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:204:		Format					100.0%
github.com/ArmisSecurity/armis-cli/internal/output/sarif.go:231:		firstNonEmpty				100.0%
github.com/ArmisSecurity/armis-cli/internal/output/sarif.go:250:		stableRuleID				100.0%
github.com/ArmisSecurity/armis-cli/internal/output/sarif.go:265:		buildRules				100.0%
github.com/ArmisSecurity/armis-cli/internal/output/sarif.go:330:		convertToSarifResults			92.3%
github.com/ArmisSecurity/armis-cli/internal/output/sarif.go:446:		buildMessageText			100.0%
github.com/ArmisSecurity/armis-cli/internal/output/sarif.go:453:		severityToSarifLevel			100.0%
github.com/ArmisSecurity/armis-cli/internal/output/sarif.go:472:		severityToSecurityScore			100.0%
github.com/ArmisSecurity/armis-cli/internal/output/sarif.go:491:		generateHelpURI				100.0%
github.com/ArmisSecurity/armis-cli/internal/output/sarif.go:515:		convertFixToSarif			90.5%
github.com/ArmisSecurity/armis-cli/internal/output/sarif.go:632:		FormatWithOptions			100.0%
github.com/ArmisSecurity/armis-cli/internal/output/styles.go:138:		DefaultStyles				100.0%
github.com/ArmisSecurity/armis-cli/internal/output/styles.go:276:		NoColorStyles				100.0%
github.com/ArmisSecurity/armis-cli/internal/output/styles.go:353:		GetStyles				100.0%
github.com/ArmisSecurity/armis-cli/internal/output/styles.go:361:		SyncStylesWithColorMode			100.0%
github.com/ArmisSecurity/armis-cli/internal/output/styles.go:386:		GetSeverityText				100.0%
github.com/ArmisSecurity/armis-cli/internal/output/styles.go:414:		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:142:		Writer					100.0%
github.com/ArmisSecurity/armis-cli/internal/output/writer.go:147:		Close					100.0%
github.com/ArmisSecurity/armis-cli/internal/output/writer.go:164:		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:141:		NewSpinnerWithContext			100.0%
github.com/ArmisSecurity/armis-cli/internal/progress/progress.go:149:		SetWriter				100.0%
github.com/ArmisSecurity/armis-cli/internal/progress/progress.go:158:		Start					86.4%
github.com/ArmisSecurity/armis-cli/internal/progress/progress.go:268:		Stop					100.0%
github.com/ArmisSecurity/armis-cli/internal/progress/progress.go:303:		Update					100.0%
github.com/ArmisSecurity/armis-cli/internal/progress/progress.go:310:		GetElapsed				100.0%
github.com/ArmisSecurity/armis-cli/internal/progress/progress.go:317:		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:230:		exportImage				0.0%
github.com/ArmisSecurity/armis-cli/internal/scan/image/image.go:280:		isDockerAvailable			42.9%
github.com/ArmisSecurity/armis-cli/internal/scan/image/image.go:294:		getDockerCommand			75.0%
github.com/ArmisSecurity/armis-cli/internal/scan/image/image.go:303:		validateDockerCommand			100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/image/image.go:311:		imageExistsLocally			100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/image/image.go:319:		determinePullBehavior			100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/image/image.go:337:		isRetryableError			75.0%
github.com/ArmisSecurity/armis-cli/internal/scan/image/image.go:345:		buildScanResult				100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/image/image.go:372:		convertNormalizedFindings		85.0%
github.com/ArmisSecurity/armis-cli/internal/scan/image/image.go:495:		shouldFilterByExploitability		100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/image/image.go:514:		cleanDescription			100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/image/image.go:533:		isEmptyFinding				100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/image/image.go:548:		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:21:			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:93:		Files					100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/files.go:98:		RepoRoot				100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/files.go:103:		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:102:	gitRepoRoot				80.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/gitchanges.go:126:	changedUncommitted			41.7%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/gitchanges.go:155:	changedStaged				75.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/gitchanges.go:168:	validateRef				100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/gitchanges.go:181:	changedSinceRef				75.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/gitchanges.go:204:	filterToScanPath			94.1%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/gitchanges.go:239:	runGit					91.7%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/gitchanges.go:265:	parseLines				100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/gitchanges.go:285:	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:77:		LoadArmisIgnore				92.9%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/ignore.go:135:		parseArmisIgnoreFile			92.5%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/ignore.go:201:		Match					100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/ignore.go:213:		shouldSkipDir				100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/inline.go:57:		ApplyInlineSuppression			98.3%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/inline.go:161:		parseInlineComment			93.3%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/inline.go:190:		findCommentStart			83.3%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/inline.go:230:		parseDirectiveParams			93.9%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/inline.go:288:		matchesInlineDirective			100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/inline.go:317:		buildInlineSuppressionInfo		100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/inline.go:345:		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:61:		cweMatches				100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/matcher.go:77:		ApplySuppression			100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/matcher.go:100:		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:290:		tarGzDirectory				71.8%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/repo.go:373:		isPathContained				75.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/repo.go:382:		tarGzFiles				78.6%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/repo.go:473:		safeAddSize				100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/repo.go:480:		calculateFilesSize			78.6%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/repo.go:505:		calculateDirSize			76.9%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/repo.go:552:		shouldSkip				100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/repo.go:583:		isTestFile				100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/repo.go:629:		isRetryableError			75.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/repo.go:638:		buildScanResult				100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/repo.go:665:		convertNormalizedFindings		73.3%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/repo.go:788:		shouldFilterByExploitability		100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/repo.go:807:		cleanDescription			100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/repo.go:828:		generateFindingTitle			100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/repo.go:832:		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:171:	hasDirectivePrefix			100.0%
github.com/ArmisSecurity/armis-cli/internal/scan/repo/suppression.go:185:	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			0.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:193:		getCacheFilePath			66.7%
github.com/ArmisSecurity/armis-cli/internal/update/update.go:208:		readCache				84.6%
github.com/ArmisSecurity/armis-cli/internal/update/update.go:231:		writeCache				76.9%
github.com/ArmisSecurity/armis-cli/internal/update/update.go:254:		IsNewer					100.0%
github.com/ArmisSecurity/armis-cli/internal/update/update.go:277:		parseVersion				100.0%
github.com/ArmisSecurity/armis-cli/internal/update/update.go:300:		FormatNotification			100.0%
github.com/ArmisSecurity/armis-cli/internal/update/update.go:319:		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:163:			maskValue				83.3%
github.com/ArmisSecurity/armis-cli/internal/util/mask.go:189:			MaskSecretInLines			100.0%
github.com/ArmisSecurity/armis-cli/internal/util/mask.go:203:			MaskSecretInMultiLineString		100.0%
github.com/ArmisSecurity/armis-cli/internal/util/mask.go:217:			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:51:			SafeJoinPath				87.5%
github.com/ArmisSecurity/armis-cli/test/sample-repo/src/main.go:6:		main					0.0%
total:										(statements)				77.3%

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds inline armis:ignore comment directives to suppress individual scan findings at the source line level, complementing existing .armisignore-based suppression and surfacing suppression provenance in human + SARIF outputs.

Changes:

  • Apply inline suppression after .armisignore suppression and recompute scan summary when additional suppressions occur.
  • Introduce inline directive parsing/matching with scope parameters (category/rule/CWE/severity/reason) plus unit tests.
  • Differentiate suppression sources (armisignore vs inline) in SARIF (kind: external vs inSource) and improve human output suppression summaries/labels.

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
internal/scan/repo/repo.go Runs inline suppression after .armisignore suppression and recomputes summary.
internal/scan/repo/matcher.go Adds suppression source metadata for .armisignore suppressions.
internal/scan/repo/inline.go Implements inline directive parsing, file scanning, and suppression application.
internal/scan/repo/inline_test.go Adds unit tests for directive parsing/matching and suppression application.
internal/output/output.go Introduces shared constant for inline suppression source detection in output.
internal/output/sarif.go Emits SARIF suppression kind/justification based on suppression source.
internal/output/sarif_test.go Updates/adds SARIF tests for external vs in-source suppressions.
internal/output/human.go Improves human output to summarize suppressions by source and label inline-suppressed findings.
internal/output/human_test.go Updates human formatter tests to account for source-aware suppression summaries.
internal/model/finding.go Extends suppression metadata model to include suppression Source.

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

Comment on lines +259 to +263
continue
}
key := strings.ToLower(token[:colonIdx])
value := token[colonIdx+1:]

Comment on lines +82 to +86
scanner := bufio.NewScanner(f)
for scanner.Scan() {
entry.lines = append(entry.lines, scanner.Text())
}
if scanner.Err() == nil {
Comment thread internal/scan/repo/inline.go Outdated
Comment on lines +248 to +252
// Try to match key:value
parts := strings.SplitN(remainder, " ", 2)
token := parts[0]
if len(parts) > 1 {
remainder = parts[1]
Comment on lines +185 to +189
// findCommentStart finds the first occurrence of prefix that is not inside a
// quoted string. Returns -1 if not found or only found inside quotes.
func findCommentStart(line, prefix string) int {
inSingle := false
inDouble := false
Comment thread internal/scan/repo/inline.go Outdated
Comment on lines +36 to +40
".js": {"//"}, ".ts": {"//"}, ".jsx": {"//"}, ".tsx": {"//"}, ".java": {"//"},
".c": {"//"}, ".h": {"//"}, ".cpp": {"//"}, ".hpp": {"//"}, ".cs": {"//"},
".go": {"//"}, ".rs": {"//"}, ".swift": {"//"}, ".kt": {"//"}, ".scala": {"//"},
".dart": {"//"}, ".groovy": {"//"},

- Add 1MB scanner buffer to handle minified files with long lines
- Track backtick quotes in findCommentStart to prevent template literal bypass
- Replace SplitN with strings.Fields for robust whitespace handling
- Reject directives with only unrecognized keys to catch typos
- Add block comment support (/*...*/) to C-family languages
if err != nil {
return entry
}
defer f.Close() //nolint:errcheck
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

False positive — this file is opened read-only (os.Open = O_RDONLY). There is no buffered write data that could be lost on close. For read-only file descriptors, Close() errors are benign (the kernel simply releases the fd), and ignoring the return value is idiomatic Go. The //nolint:errcheck annotation documents this deliberate choice.

@yiftach-armis yiftach-armis merged commit a5c3a0c into main May 12, 2026
9 checks passed
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