computeRiskLevel function
Compute risk level from analysis.
Implementation
SecurityRiskLevel computeRiskLevel(CommandSecurityAnalysis a) {
// Critical: sudo + remove, eval with substitution, fork bombs.
if (a.hasSudo && a.hasRemove) return SecurityRiskLevel.critical;
if (a.hasEval && a.hasCommandSubstitution) return SecurityRiskLevel.critical;
if (a.hasSudo && a.hasChown) return SecurityRiskLevel.critical;
// High: sudo, eval, exec, remove with glob.
if (a.hasSudo) return SecurityRiskLevel.high;
if (a.hasEval) return SecurityRiskLevel.high;
if (a.hasExec) return SecurityRiskLevel.high;
if (a.hasRemove && a.hasGlobbing) return SecurityRiskLevel.high;
if (a.hasRemove &&
a.writtenPaths.any((p) => p == '/' || p == '~' || p.startsWith('/'))) {
return SecurityRiskLevel.high;
}
// Medium: network access, disk writes with variable expansion, command
// substitution, remove.
if (a.hasNetworkAccess) return SecurityRiskLevel.medium;
if (a.hasDiskWrite && a.hasVariableExpansion) return SecurityRiskLevel.medium;
if (a.hasCommandSubstitution) return SecurityRiskLevel.medium;
if (a.hasRemove) return SecurityRiskLevel.medium;
if (a.hasChown) return SecurityRiskLevel.medium;
// Low: disk writes, redirections, backgrounding, piping.
if (a.hasDiskWrite) return SecurityRiskLevel.low;
if (a.hasRedirection) return SecurityRiskLevel.low;
if (a.hasBackgroundExec) return SecurityRiskLevel.low;
if (a.hasSubshell) return SecurityRiskLevel.low;
// Safe: read-only commands, piping between safe commands.
if (a.hasPiping) return SecurityRiskLevel.low;
if (a.hasGlobbing) return SecurityRiskLevel.low;
return SecurityRiskLevel.safe;
}