Skip to content

Add issue get command for FoD and SSC - #978

Open
jmadhur87 wants to merge 11 commits into
fortify:dev/v3.xfrom
jmadhur87:mjain6/974
Open

Add issue get command for FoD and SSC#978
jmadhur87 wants to merge 11 commits into
fortify:dev/v3.xfrom
jmadhur87:mjain6/974

Conversation

@jmadhur87

@jmadhur87 jmadhur87 commented Apr 17, 2026

Copy link
Copy Markdown
Contributor

Added issue get command for both SSC and FoD to fetch a single issue by ID, avoiding full list + client-side filtering.
Supports optional --embed to include additional issue details.

fcli fod issue get
fcli ssc issue get

feat: Add get command for fcli ssc issue and fcli fod issue(#974 )

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

Adds new get subcommands to the ssc issue and fod issue command groups to retrieve a single issue/vulnerability by identifier, supporting optional embedded data and avoiding manual client-side filtering workflows.

Changes:

  • Added fcli ssc issue get <id> --av <appversion> command and supporting i18n/table output definitions.
  • Added fcli fod issue get <id|vulnId> --rel <release> command with i18n updates and command registration.
  • Refactored SSC issue option message keys so --embed/--include descriptions can be shared beyond the list command.

Reviewed changes

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

Show a summary per file
File Description
fcli-core/fcli-ssc/src/main/resources/com/fortify/cli/ssc/i18n/SSCMessages.properties Adds SSC issue-get help + table defaults; renames embed/include message keys for reuse.
fcli-core/fcli-ssc/src/main/java/com/fortify/cli/ssc/issue/cli/mixin/SSCIssueIncludeMixin.java Updates description key to new shared SSC issue include message key.
fcli-core/fcli-ssc/src/main/java/com/fortify/cli/ssc/issue/cli/cmd/SSCIssueGetCommand.java New SSC leaf command to fetch a single issue for an app version.
fcli-core/fcli-ssc/src/main/java/com/fortify/cli/ssc/issue/cli/cmd/SSCIssueCommands.java Registers SSCIssueGetCommand under ssc issue.
fcli-core/fcli-fod/src/main/resources/com/fortify/cli/fod/i18n/FoDMessages.properties Adds FoD issue-get help text keys.
fcli-core/fcli-fod/src/main/java/com/fortify/cli/fod/issue/cli/cmd/FoDIssueGetCommand.java New FoD leaf command to fetch a single vulnerability for a release.
fcli-core/fcli-fod/src/main/java/com/fortify/cli/fod/issue/cli/cmd/FoDIssueCommands.java Registers FoDIssueGetCommand under fod issue.

@rsenden rsenden left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Apart from the individual comments on implementation details, we need to decide on what id's we should support, which is a tradeoff between fcli consistency vs usability.

For (almost) all other get commands in fcli, we just accept a single type of id, which corresponds to the id expected by the corresponding REST endpoint. This is what you've implemented for SSC, and would simplify the FoD implementation.

Also, we want to ensure consistency between issue get and issue update commands; these should accept the same type(s) of id('s). I think both FoD and SSC issue update commands currently only accept a single type of id (id for SSC, vulnId for FoD), so we should have the issue get commands accept those same types of id's only.

Having said that, for future consideration, we might want to consider deviating from this approach given that issues have multiple id's (id, issue instance id, and for FoD, vulnId).

For example, although users can see the SSC issue id in the output of the issue list command, I don't think this id is visible anywhere in the SSC UI. So, if users view an issue in SSC and then want to work on this issue in fcli (through issue get or issue update commands), they need to somehow figure out the issue id. Even SSC itself uses issueInstanceId filter instead of passing the issue id when opening the details for a given issue in a different browser window.

We can leave support for multiple types of id's as a future enhancement, although we need to think about the potential impact on command structure, for example whether we should have explicit options instead of a positional parameter (but that's inconsistent with other fcli get commands), to be able to differentiate between --id and --instance-id for example if we can't automatically determine the type of id being queried by the user. Alternatively, we can just try passing the given id through multiple REST queries on different fields (like you're more or less doing for FoD now, but not optimal from performance perspective), or support an optional prefix for the positional parameter, i.e., fcli ssc issue get instance-id:... vs fcli ssc issue get id:....

Somewhat related, for the issue update commands, I can imagine having a generic query option, i.e., update all issues that match a given query to perform bulk update, for example updating all issues in SQL Injection category, but again that's a potential future enhancement.

To summarize, maybe best to just have the issue get commands accept the same type of id as accepted by the issue update command for now, and raising an enhancement request for supporting additional id types on the issue get and issue update commands (again, these should be consistent as to what id types they support, likely through some shared helper class or resolver mixin), and another enhancement request for adding query support on the issue update command (maybe such an ER already exists though).

}

private HttpRequest<?> getBaseRequest(UnirestInstance unirest, String appVersionId) {
return unirest.get(SSCUrls.PROJECT_VERSION_ISSUE(appVersionId, id)).queryString("qm", "issues");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Please double-check, but I think qm request parameter is not supported by SSC on this endpoint.

Also, we could consider using the issueDetails endpoint instead as that doesn't require application version to be specified (thereby simplifying CLI usage), but output of that endpoint is not the same as what we return on the list command, so users may not expect that inconsistency.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Verified the SSC api reference , query parameter is available for this endpoint.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think this uses the following endpoint, which doesn't list a qm query parameter:

Image

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code still shows qm request parameter, which is not supported on GET /projectVersions/{parentId}/issues/{id} endpoint.

@jmadhur87 jmadhur87 changed the title Added issue get command for FoD and SSC Add issue get command for FoD and SSC May 5, 2026

@rsenden rsenden left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Please check review comments. Also, as there's been some refactoring on FoD issue-related classes in http-mcp branch (which has higher priority to be merged than this PR), let's wait until that branch has been merged to dev/v3.x first, then update this PR as needed before merging it.

}

private HttpRequest<?> getBaseRequest(UnirestInstance unirest, String appVersionId) {
return unirest.get(SSCUrls.PROJECT_VERSION_ISSUE(appVersionId, id)).queryString("qm", "issues");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think this uses the following endpoint, which doesn't list a qm query parameter:

Image

@jmadhur87
jmadhur87 requested a review from rsenden June 22, 2026 09:54
}

private HttpRequest<?> getBaseRequest(UnirestInstance unirest, String appVersionId) {
return unirest.get(SSCUrls.PROJECT_VERSION_ISSUE(appVersionId, id)).queryString("qm", "issues");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code still shows qm request parameter, which is not supported on GET /projectVersions/{parentId}/issues/{id} endpoint.

@jmadhur87 jmadhur87 self-assigned this Jul 2, 2026

private HttpRequest<?> getBaseRequest(UnirestInstance unirest, String appVersionId) {
return unirest.get(SSCUrls.PROJECT_VERSION_ISSUE(appVersionId, id))
.queryString("showHidden", "true")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think the PROJECT_VERSION_ISSUE endpoint doesn't support these query parameters; it will always return the issue that corresponds to the given id, independent of whether that issue is hidden, removed, or suppressed.

}

@Override
public HttpRequest<?> updateRequest(HttpRequest<?> request) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I don't understand this code:

  • The PROJECT_VERSION_ISSUE endpoint used by this command doesn't support the qm query parameter
  • Even if qm was supported, I don't see why embedNames would need to be appended to its value; embed names are fcli-specific identifiers that SSC doesn't have any knowledge about (apart from that they may overlap with SSC endpoint names, but even then still not valid values for qm request parameter).


@Override
public final void addEmbedRequests(SSCBulkRequestBuilder builder, UnirestInstance unirest, JsonNode record) {
// Skip if data is already present in the record (e.g. returned by SSC via qm parameter)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This assumption is nonsense; SSC qm parameter (which is not even supported on the endpoint that's used by the issue get command) doesn't control embedding of extra data. Please undo all irrelevant code changes to this class and all related classes (i.e., remove all getEmbedFieldName methods)

@jmadhur87
jmadhur87 requested a review from rsenden August 13, 2026 10:04
@jmadhur87
jmadhur87 requested a review from rsenden August 14, 2026 08:06
FoDReleaseDescriptor releaseDescriptor = releaseResolver.getReleaseDescriptor(unirest);
String releaseId = releaseDescriptor.getReleaseId().toString();
JsonNode issue = findIssue(unirest, releaseDescriptor);
if ( issue instanceof ObjectNode issueObject ) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

What if issue is not instance of ObjectNode? In that case, we don't add release id/name, don't pass the node through transformRecord, and output is undefined.

It would be better to have findIssue return an ObjectNode, either through simple cast (throwing an exception if it's not an ObjectNode, which I guess is very unlikely to happen), or explicit check (throwing an explicit exception in case the issue is not of type ObjectNode).

String releaseId = releaseDescriptor.getReleaseId().toString();
JsonNode issue = findIssue(unirest, releaseDescriptor);
if ( issue instanceof ObjectNode issueObject ) {
issueObject.put("releaseId", releaseId);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Doesn't the issue object already contain releaseId and releaseName?

if ( issue instanceof ObjectNode issueObject ) {
issueObject.put("releaseId", releaseId);
issueObject.put("releaseName", releaseDescriptor.getReleaseName());
FoDIssueHelper.transformRecord(issueObject, IssueAggregationData.forSingleRelease(issueObject));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think this transformation is mostly meant for the list command, which can list issues from either an FoD app or release. Not sure whether it makes sense to add this data, although it does ensure that list and get commands output the same data. But if we want such consistency, then maybe the get command should accept either --rel or --app, with similar behavior as the list command (i.e., locate the given vuln id in either single release or all releases for given app, then transform based on appropriate IssueAggregationData factory method).

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