| 189 | } |
| 190 | |
| 191 | func RunAllSecurityChecks(command string) SecurityCheckResult { |
| 192 | result := SecurityCheckResult{Passed: true, CheckIDs: map[int]bool{}} |
| 193 | appendFindings := func(findings []SecurityFinding) { |
| 194 | for _, finding := range findings { |
| 195 | result.Findings = append(result.Findings, finding) |
| 196 | result.CheckIDs[finding.ID] = true |
| 197 | } |
| 198 | } |
| 199 | appendFindings(checkIncompleteCommands(command)) |
| 200 | appendFindings(singleREFinding(command, jqSystemRE, CheckJQSystemFunction, "jq system() function call detected", true)) |
| 201 | appendFindings(singleREFinding(command, jqFileArgRE, CheckJQFileArguments, "jq file argument flags detected", true)) |
| 202 | appendFindings(singleREFinding(command, obfuscatedFlagRE, CheckObfuscatedFlags, "Obfuscated flag detected: command substitution in flag", true)) |
| 203 | appendFindings(checkShellMetacharacters(command)) |
| 204 | appendFindings(singleREFinding(command, dangerousVariablesRE, CheckDangerousVariables, "Suspicious variable assignment detected", true)) |
| 205 | appendFindings(checkNewlines(command)) |
| 206 | appendFindings(checkCommandSubstitution(command)) |
| 207 | appendFindings(singleREFinding(command, dangerousInputRE, CheckDangerousPatternsInputRedirection, "Dangerous input redirection to /dev/tcp or /dev/udp", true)) |
| 208 | appendFindings(singleREFinding(command, dangerousOutputRE, CheckDangerousPatternsOutputRedirection, "Dangerous output redirection to device/proc files", true)) |
| 209 | appendFindings(singleREFinding(command, ifsInjectionRE, CheckIFSInjection, "IFS variable manipulation detected", true)) |
| 210 | appendFindings(singleREFinding(command, gitCommitSubRE, CheckGitCommitSubstitution, "Command substitution in git commit", true)) |
| 211 | appendFindings(singleRawFinding(command, procEnvironRE, CheckProcEnvironAccess, "/proc/self/environ access detected")) |
| 212 | appendFindings(singleREFinding(command, malformedTokenRE, CheckMalformedTokenInjection, "Base64-encoded blob detected", true)) |
| 213 | appendFindings(singleREFinding(command, backslashWhitespaceRE, CheckBackslashEscapedWhitespace, "Backslash-escaped whitespace detected", false)) |
| 214 | appendFindings(singleREFinding(command, braceExpansionRE, CheckBraceExpansion, "Brace expansion detected", true)) |
| 215 | appendFindings(singleRawFinding(command, controlCharsRE, CheckControlCharacters, "Control characters detected")) |
| 216 | appendFindings(singleRawFinding(command, unicodeWhitespaceRE, CheckUnicodeWhitespace, "Unicode whitespace homoglyph detected")) |
| 217 | appendFindings(singleREFinding(command, midWordHashRE, CheckMidWordHash, "Mid-word # detected (possible comment injection)", true)) |
| 218 | appendFindings(checkZshDangerous(command)) |
| 219 | appendFindings(singleREFinding(command, backslashOperatorRE, CheckBackslashEscapedOperators, "Backslash-escaped shell operator detected", false)) |
| 220 | appendFindings(checkCommentQuoteDesync(command)) |
| 221 | appendFindings(checkQuotedNewline(command)) |
| 222 | result.Passed = len(result.Findings) == 0 |
| 223 | return result |
| 224 | } |
| 225 | |
| 226 | func IsBlocking(result SecurityCheckResult) bool { |
| 227 | for id := range result.CheckIDs { |