Conversation
| if err != nil { | ||
| if strings.Contains(err.Error(), "404") { | ||
| fileId := strconv.Itoa(fileID) | ||
| return nil, nil, errors.New("KnoxIQ CI/CD analyses for fileID " + fileId + " not found (404)") |
| Supported keys: | ||
| include-needs-review Include KnoxIQ "needs review" vulnerabilities in the | ||
| CI check results and build decision (default: false).`, | ||
| } |
There was a problem hiding this comment.
update README.md for all changes done
|
| var drfResponse DRFResponseKnoxIQCICDAnalysis | ||
| _, err = s.client.Do(ctx, req, &drfResponse) | ||
| if err != nil { | ||
| if strings.Contains(err.Error(), "404") { |
There was a problem hiding this comment.
read the response code (StatusCodeOf
| ) (enums.KnoxIQScanStatusType, bool) { | ||
| scanStatus, _, err := client.KnoxIQ.GetScanStatus(ctx, fileID) | ||
| if err != nil { | ||
| switch appknox.StatusCodeOf(err) { |
There was a problem hiding this comment.
-switch statusCode {
-case 403, 404:
-default:
- PrintError(err)
-}
-return disabled, false
+if statusCode == 403 || statusCode == 404 {
+ return disabled, false
+}
+PrintError(err)
|
|
||
| func init() { | ||
| RootCmd.AddCommand(sarifCmd) | ||
| sarifCmd.Flags().StringP( |
There was a problem hiding this comment.
can we add something like --no-knoxiq to skips the KnoxIQ wait entirely and produces the plain report immediately
| os.Create(file) | ||
| return | ||
| } | ||
|
|
There was a problem hiding this comment.
consider adding below to provide more context about read failures , if it makes sense
+if _, statErr := os.Stat(configFile); statErr == nil {
+ fmt.Println("Warning: config file exists but could not be read; recreating it.")
+}
| os.Exit(1) | ||
| } | ||
| viper.Set(key, value) | ||
| if err := viper.WriteConfig(); err != nil { |
There was a problem hiding this comment.
consider below
-viper.Set(key, value)
-if err := viper.WriteConfig(); err != nil {
+if err := setOnlyThisKey(key, value); err != nil { // patches just `key` in the file on disk
| Short: "Print the current value of a configuration key.", | ||
| Args: cobra.ExactArgs(1), | ||
| Run: func(cmd *cobra.Command, args []string) { | ||
| fmt.Println(viper.GetString(args[0])) |
There was a problem hiding this comment.
+ key := args[0]
+ if !isKnownConfigKey(key) {
+ helper.PrintError(fmt.Errorf(
+ "unknown config key %q. Supported keys: %s",
+ key, strings.Join(knownConfigKeys, ", "),
+ ))
+ os.Exit(1)
+ }
- fmt.Println(viper.GetString(args[0]))
+ fmt.Println(viper.GetString(key))
},
}
consider adding restrictions for get cmd as well
| )) | ||
| os.Exit(1) | ||
| } | ||
| viper.Set(key, value) |
There was a problem hiding this comment.
config set saves a value without validating it so a include-needs-review Yes is accepted but checks strictly compares like if settings["include_needs_review"] == "true":
| PrintError("exploit-likelihood gating requires KnoxIQ triage — skipping (no KnoxIQ results for this file)") | ||
| return 0 | ||
| } | ||
| if !waitForKnoxIQ(ctx, client, fileID, policy.Budget.KnoxIQDeadline()) { |
There was a problem hiding this comment.
the above check can be used as a short circuit for next wait call , less probability but still can be helpful if ci is run for some file where it already exists or has been evaluated at the first call itself
-func countLikelihoodOffenders(ctx context.Context, client *appknox.Client, fileID int, policy CiPolicy) int {
- if _, available := knoxIQAvailable(ctx, client, fileID); !available {
+func countLikelihoodOffenders(ctx context.Context, client *appknox.Client, fileID int, policy CiPolicy) int {
+ status, available := knoxIQAvailable(ctx, client, fileID)
+ if !available {
...
- if !waitForKnoxIQ(ctx, client, fileID, policy.Budget.KnoxIQDeadline()) {
+ if status != enums.KnoxIQStatusCompleted && !waitForKnoxIQ(ctx, client, fileID, policy.Budget.KnoxIQDeadline()) {
| t.Print() | ||
| } | ||
|
|
||
| func reportKnoxIQGate(fileID int, policy CiPolicy, triaged []*appknox.KnoxIQCICDAnalysis) { |
There was a problem hiding this comment.
write a test that calls the existing reportKnoxIQGate with one made-up finding that has: highest risk level (Critical), highest likelihood level (High), and NeedsReview = true — set the risk and likelihood thresholds so that a normal finding with this severity would fail the build — and checks that the build does not fail (no offending count, no exit) precisely because that one finding is marked "needs review."
| // 403 (org without the KnoxIQ feature) and 404 (backend without the KnoxIQ | ||
| // endpoints) both mean "not available", so the CLI silently falls back to the | ||
| // plain SAST flow. Anything else is surfaced before falling back. | ||
| func knoxIQAvailable( |
There was a problem hiding this comment.
consider adding tests
func TestKnoxIQAvailable_404IsQuiet(t testing.T) { / 404 -> false, nothing printed */ }
func TestKnoxIQAvailable_ServerErrorIsLoud(t testing.T) { / 500 -> false, error printed */ }
func TestKnoxIQAvailable_TrueWhenInProgressOrDone(t testing.T) { / pending/running/completed -> true */ }
| enums.KnoxIQStatusLegacy: | ||
| return false | ||
| } | ||
| if time.Now().After(deadline) { |
There was a problem hiding this comment.
consider adding test case
TestWaitForKnoxIQ_DeadlinePassed
utkarshpandey12
left a comment
There was a problem hiding this comment.
requested changes



APPKNOX_KNOXIQ_TIMEOUT(KnoxIQ triage timeout),APPKNOX_INCLUDE_NEEDS_REVIEW(needs-review inclusion)sherlock-knoxiq-uatknoxiq_scan/status, so older/non-KnoxIQ backends are unaffectedChangelog
--knoxiqflag touploadto request KnoxIQ triage for a specific CI/CD buildcicheck: intermediary → triage status → final triaged results, with AEIS score and exploit likelihood columns--exploit-likelihood-threshold low|medium|hightocicheckto gate builds on KnoxIQ exploit likelihood--include-needs-reviewflag andconfig get/set include-needs-reviewto control whether KnoxIQ needs-review vulnerabilities count toward the build decision (default: excluded)--knoxiq-timeout(default 30 min), combined with the static-scan timeout into one budget so unused SAST time carries over to KnoxIQ; shared consistently acrosscicheck,sarif, andreports knoxiqreports knoxiq <file_id>to generate and download the KnoxIQ PDF report in one step; fails explicitly if the file has no KnoxIQ results instead of falling back to a standard reportsarifto parity withcicheck: shares the same timeout budget and availability check, excludes needs-review by default, addsaeisScore/exploitLikelihoodresult propertiesreports knoxiqprinted its fail-fast error but exited 0 instead of 1viper's$HOMEexpansion silently broke on Windows path separators, causingconfig set/initto fail with "Config File Not Found"File.IsKnoxIQAutomated/KnoxIQStatusfields andGetByIDV3(superseded by the newknoxiq_scan/statusandcicd/analysesendpoints)Dependent PRs
PD-2352— backend endpoints/fields this CLI work depends on (cicd/analyses, per-buildknoxiq_requested,is_knoxiqon reports)