Skip to content

Conversation

@harshithb3304
Copy link
Contributor

No description provided.

Copy link
Contributor

@devsecopsbot devsecopsbot bot left a comment

Choose a reason for hiding this comment

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

🤖 AI Security analysis: "Automated security scan of the code changes found no issues. Continue with standard CI checks and monitor behavior after deployment."

Risk Level AI Score
🟢 NO RISK 5.0/100

Top 0 security issues / 0 total (Critical: 0, High: 0, Medium: 0, Low: 0)

Title Location Recommendation
No issues to display

🔗 View Detailed Report

Copy link
Contributor

@devsecopsbot devsecopsbot bot left a comment

Choose a reason for hiding this comment

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

🤖 AI Security analysis: "Automated security scan of the code changes found no issues. Continue with standard CI checks and monitor behavior after deployment."

Risk Level AI Score
🟢 NO RISK 5.0/100

Top 0 security issues / 0 total (Critical: 0, High: 0, Medium: 0, Low: 0)

Title Location Recommendation
No issues to display

🔗 View Detailed Report

@harshithb3304 harshithb3304 changed the title Threat activity highlight SchemaConform View Schema button Nov 19, 2025
Copilot AI review requested due to automatic review settings December 9, 2025 07:52
Copy link
Contributor

@devsecopsbot devsecopsbot bot left a comment

Choose a reason for hiding this comment

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

🤖 AI Security analysis: "Automated scanning reported no security findings for these changes. Residual risk remains because tools can miss logic errors, coverage gaps, or secrets; prioritize targeted manual review of security-critical areas and complementary dynamic and dependency scans in CI."

Risk Level AI Score
🟢 NO RISK 10.0/100

Top 0 security issues / 0 total (Critical: 0, High: 0, Medium: 0, Low: 0)

Title Location Recommendation
No issues to display

🔗 View Detailed Report

Copy link
Contributor

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

This PR adds a "View Schema" button to the Schema Validation Errors banner that allows users to view the uploaded OpenAPI schema for an API collection. The feature enhances the threat detection page by enabling users to reference the schema when reviewing validation errors, and handles page refresh scenarios by fetching event metadata when context is unavailable.

Key Changes:

  • Added a collapsible OpenAPI schema viewer within the Schema Validation Errors banner
  • Implemented backend endpoint to fetch uploaded OpenAPI schemas from the database
  • Enhanced ThreatDetectionPage to fetch event metadata on page refresh to ensure apiCollectionId is available

Reviewed changes

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

Show a summary per file
File Description
apps/dashboard/web/polaris_web/web/src/apps/dashboard/components/shared/SampleDataList.js Added View/Hide Schema button and collapsible schema viewer to SchemaValidationError component with async schema fetching
apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/observe/api.js Added fetchOpenApiSchema API method to retrieve schema from backend
apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/threat_detection/components/SampleDetails.jsx Passed apiCollectionId prop to SampleDataList component
apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/threat_detection/ThreatDetectionPage.jsx Added event metadata fetching on page refresh to retrieve apiCollectionId when rowContext is unavailable
apps/dashboard/src/main/java/com/akto/action/OpenApiAction.java Implemented fetchOpenApiSchema method to retrieve and decompress stored OpenAPI schema
apps/dashboard/src/main/resources/struts.xml Added Struts action mapping for fetchOpenApiSchema endpoint with READ access control

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

const response = await api.fetchOpenApiSchema(apiCollectionId);
setSchemaContent(response?.openApiSchema || "No schema available");
} catch (error) {
setSchemaContent("Error loading schema: " + error.message);
Copy link

Copilot AI Dec 9, 2025

Choose a reason for hiding this comment

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

When an error occurs, the error message is set as schemaContent and passed to the SampleData component with language="json". However, an error message string is not valid JSON. Consider either wrapping the error message in a proper format or conditionally rendering a different error UI:

} catch (error) {
    setSchemaContent(JSON.stringify({ error: error.message }, null, 2));
}

Or alternatively:

const [schemaError, setSchemaError] = useState(null);

// In catch block:
} catch (error) {
    setSchemaError(error.message);
}

// In render:
{schemaError ? (
    <Banner status="critical">{schemaError}</Banner>
) : (
    <SampleData data={{ original: schemaContent }} ... />
)}
Suggested change
setSchemaContent("Error loading schema: " + error.message);
setSchemaContent(JSON.stringify({ error: error.message }, null, 2));

Copilot uses AI. Check for mistakes.
Comment on lines +454 to +470
const eventListResponse = await api.fetchSuspectSampleData(
0, // skip
[queryParams.actor], // ips filter
[], // apiCollectionIds
[], // urls
[], // types
{}, // sort
0, // startTimestamp (use 0 to get all)
Math.floor(Date.now() / 1000), // endTimestamp (current time)
[queryParams.filterId], // latestAttack filter
10, // limit
queryParams.status || 'ACTIVE', // statusFilter
undefined, // successfulExploit
LABELS.THREAT, // label
[], // hosts
undefined // latestApiOrigRegex
);
Copy link

Copilot AI Dec 9, 2025

Choose a reason for hiding this comment

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

The event metadata fetch uses startTimestamp: 0 and endTimestamp: Date.now() to get all events, which could potentially retrieve a large dataset. Consider adding a more specific time range or using pagination parameters to limit the query scope. For example:

const eventListResponse = await api.fetchSuspectSampleData(
  0, // skip
  [queryParams.actor], // ips filter
  [], // apiCollectionIds
  [], // urls
  [], // types
  {}, // sort
  Math.floor(Date.now() / 1000) - 86400, // startTimestamp (last 24 hours instead of all time)
  Math.floor(Date.now() / 1000), // endTimestamp (current time)
  [queryParams.filterId], // latestAttack filter
  1, // limit - only need one matching event
  queryParams.status || 'ACTIVE', // statusFilter
  undefined, // successfulExploit
  LABELS.THREAT, // label
  [], // hosts
  undefined // latestApiOrigRegex
);

Copilot uses AI. Check for mistakes.
Comment on lines +473 to +483
const matchingEvent = eventListResponse?.maliciousEvents?.find(e => e.refId === queryParams.refId);
if (matchingEvent) {
eventMetadata = {
url: matchingEvent.url,
method: matchingEvent.method,
apiCollectionId: matchingEvent.apiCollectionId,
eventId: matchingEvent.id,
status: matchingEvent.status,
jiraTicketUrl: matchingEvent.jiraTicketUrl
};
}
Copy link

Copilot AI Dec 9, 2025

Choose a reason for hiding this comment

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

If the matchingEvent is not found in the response, eventMetadata will remain null, and the event will be displayed with empty metadata fields. Consider adding error handling to notify the user or retry with different parameters:

const matchingEvent = eventListResponse?.maliciousEvents?.find(e => e.refId === queryParams.refId);
if (matchingEvent) {
  eventMetadata = {
    url: matchingEvent.url,
    method: matchingEvent.method,
    apiCollectionId: matchingEvent.apiCollectionId,
    eventId: matchingEvent.id,
    status: matchingEvent.status,
    jiraTicketUrl: matchingEvent.jiraTicketUrl
  };
} else {
  // Event not found - could be deleted or filtered out
  throw new Error('Event not found');
}

Copilot uses AI. Check for mistakes.
<LegacyCard.Section>
<SampleData
data={{ original: schemaContent }}
language="json"
Copy link

Copilot AI Dec 9, 2025

Choose a reason for hiding this comment

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

The SampleData component expects the editorLanguage prop, not language. Change language="json" to editorLanguage="json":

<SampleData 
    data={{ original: schemaContent }} 
    editorLanguage="json" 
    minHeight="30vh" 
    wordWrap={true} 
/>

Note: This same issue exists on line 135, but that's outside the scope of this PR.

Suggested change
language="json"
editorLanguage="json"

Copilot uses AI. Check for mistakes.
Comment on lines +40 to +41
}
setLoadingSchema(false);
Copy link

Copilot AI Dec 9, 2025

Choose a reason for hiding this comment

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

There's a race condition in the handleViewSchema function. If the user clicks the button multiple times quickly before the API call completes, setLoadingSchema(false) on line 41 will be executed outside the try-catch block and could be called even if an error occurs. The state update should be in a finally block:

const handleViewSchema = async () => {
    if (!schemaOpen && !schemaContent && apiCollectionId) {
        setLoadingSchema(true);
        try {
            const response = await api.fetchOpenApiSchema(apiCollectionId);
            setSchemaContent(response?.openApiSchema || "No schema available");
        } catch (error) {
            setSchemaContent("Error loading schema: " + error.message);
        } finally {
            setLoadingSchema(false);
        }
    }
    setSchemaOpen(!schemaOpen);
};
Suggested change
}
setLoadingSchema(false);
} finally {
setLoadingSchema(false);
}

Copilot uses AI. Check for mistakes.
Comment on lines +69 to +82
{apiCollectionId && (
<Collapsible open={schemaOpen} id="schema-collapsible">
<LegacyCard>
<LegacyCard.Section>
<SampleData
data={{ original: schemaContent }}
language="json"
minHeight="30vh"
wordWrap={true}
/>
</LegacyCard.Section>
</LegacyCard>
</Collapsible>
)}
Copy link

Copilot AI Dec 9, 2025

Choose a reason for hiding this comment

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

[nitpick] The SampleData component will receive null as data.original before the schema is fetched. Consider rendering the Collapsible only after the schema content is loaded to avoid displaying empty or loading content:

{apiCollectionId && schemaContent && (
    <Collapsible open={schemaOpen} id="schema-collapsible">
        <LegacyCard>
            <LegacyCard.Section>
                <SampleData 
                    data={{ original: schemaContent }} 
                    language="json" 
                    minHeight="30vh" 
                    wordWrap={true} 
                />
            </LegacyCard.Section>
        </LegacyCard>
    </Collapsible>
)}

Copilot uses AI. Check for mistakes.
</Collapsible>
)}
</VerticalStack>
)
Copy link

Copilot AI Dec 9, 2025

Choose a reason for hiding this comment

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

Avoid automated semicolon insertion (90% of all statements in the enclosing function have an explicit semicolon).

Suggested change
)
);

Copilot uses AI. Check for mistakes.
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.

1 participant