Skip to content

Commit

Permalink
new logic changes support for multiline body
Browse files Browse the repository at this point in the history
  • Loading branch information
avzz-19 committed Sep 5, 2024
1 parent 6be02b0 commit dfe1e3a
Show file tree
Hide file tree
Showing 3 changed files with 134 additions and 151 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,20 +26,11 @@

{{#if @currentVulnerability.request.body}}
{{#unless this.isRequestBodyEmpty}}
<AkTypography @color='textSecondary'>
{{t 'requestBody'}}:
</AkTypography>

<div local-class='vulnerability-finding-container'>
<pre
local-class='vulnerability-finding-description {{if
@analysis.isOverriddenAsPassed
"analysis-overridded-passed"
}}'
>
{{@currentVulnerability.request.body}}
</pre>
</div>
<FileDetails::VulnerabilityAnalysisDetails::Findings::CodeBox
@title={{t 'requestBody'}}
@markedAsPassed={{@analysis.isOverriddenAsPassed}}
>{{@currentVulnerability.request.body}}
</FileDetails::VulnerabilityAnalysisDetails::Findings::CodeBox>
{{/unless}}
{{/if}}

Expand Down Expand Up @@ -85,7 +76,6 @@
{{#unless this.isResponseBodyEmpty}}
<FileDetails::VulnerabilityAnalysisDetails::Findings::CodeBox
@title={{t 'responseBody'}}
@copyIcon={{true}}
@markedAsPassed={{@analysis.isOverriddenAsPassed}}
>{{@currentVulnerability.response.text}}
</FileDetails::VulnerabilityAnalysisDetails::Findings::CodeBox>
Expand Down
257 changes: 125 additions & 132 deletions app/utils/parse-vulnerable-api-finding.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,11 @@ export interface VulnerableApiResponse {
url: string;
}

type VulnerableApiFindingSection =
| 'request'
| 'response'
| 'request-headers'
| 'response-headers'
| 'params'
| 'other';
type NestedKeyOf<ObjectType extends object> = {
[Key in keyof ObjectType & (string | number)]: ObjectType[Key] extends object
? `${Key}` | `${Key}.${NestedKeyOf<ObjectType[Key]>}`
: Key;
}[keyof ObjectType & (string | number)];

/**
* Represents a finding of a vulnerability in an API.
Expand Down Expand Up @@ -68,6 +66,46 @@ function initializeVulnerableApiFinding(): VulnerableApiFinding {
};
}

function updateSection(
key: string,
currentSection: NestedKeyOf<VulnerableApiFinding>
): NestedKeyOf<VulnerableApiFinding> {
if (key === 'request') {
return 'request';
} else if (key === 'response') {
return 'response';
} else if (key === 'headers') {
return currentSection.startsWith('response')
? 'response.headers'
: 'request.headers';
} else if (key === 'params') {
return 'request.params';
} else if (key === 'severity') {
return 'severity';
} else if (key === 'confidence') {
return 'confidence';
} else if (key === 'url') {
return currentSection.startsWith('response')
? 'response.url'
: 'request.url';
} else if (key === 'method') {
return 'request.method';
} else if (key === 'body') {
return 'request.body';
} else if (key === 'text') {
return 'response.text';
} else if (key === 'status_code') {
return 'response.status_code';
} else if (key === 'reason') {
return 'response.reason';
} else if (key === 'key') {
return 'request.params.key';
} else if (key === 'token') {
return 'request.params.token';
}
return currentSection; // Default case if no section match
}

/**
* Determines if a given content string contains information indicative of a vulnerable API finding.
* @param content - The content string to check.
Expand Down Expand Up @@ -142,9 +180,12 @@ function parseVulnerableApiFindingBlock(block: string): VulnerableApiFinding {
const lines = block.split('\n');
const finding = initializeVulnerableApiFinding();

let currentSection: VulnerableApiFindingSection = 'other';
let currentSection: NestedKeyOf<VulnerableApiFinding> = 'confidence';
let currentHeaders: Record<string, string> | null = null;
let currentBuffer: string | null = null;
let currentKey: string | null = null;

// Process the first line separately to handle initial URL or description
processFirstLine(lines, finding);

lines.forEach((line) => {
Expand All @@ -153,20 +194,48 @@ function parseVulnerableApiFindingBlock(block: string): VulnerableApiFinding {
if (parsedLine) {
const [key, value] = parsedLine;

const { updatedSection, updatedHeaders } = updateVulnerableApiFinding(
finding,
key,
value,
currentSection,
currentHeaders
);

// update the current section and headers
currentSection = updatedSection;
currentHeaders = updatedHeaders;
if (currentKey && currentBuffer) {
// If a previous key exists, update it with the accumulated buffer
updateFindingField(finding, currentKey, currentBuffer, currentSection);
currentBuffer = null; // Reset buffer after updating
currentKey = null; // Reset key after updating
}

if (key) {
if (currentKey && currentBuffer) {
// Continue accumulating the value if the same key is detected
currentBuffer += `\n${value}`;
} else {
// If a new key is detected, update section and headers
const { updatedSection, updatedHeaders } = updateVulnerableApiFinding(
finding,
key,
value,
currentSection,
currentHeaders
);

// Update current section and headers
if (updatedSection !== currentSection) {
currentSection = updatedSection;
}

currentHeaders = updatedHeaders;
currentKey = key; // Track the current key
currentBuffer = value; // Start accumulating value
}
}
} else if (currentBuffer) {
// Continue accumulating the value if no new key is detected
currentBuffer += `\n${line}`;
}
});

// Finalize any remaining buffer
if (currentBuffer && currentKey) {
updateFindingField(finding, currentKey, currentBuffer, currentSection);
}

return finding;
}

Expand All @@ -182,6 +251,14 @@ function parseLine(line: string): [string, string] | null {
return null;
}

// Split the line into key and value parts based on the first colon
const colonIndex = line.indexOf(':');

// If there's no colon, return null as it's not a valid key-value pair
if (colonIndex === -1) {
return null;
}

const value = valueParts.join(':').trim();

return [key.trim().toLowerCase(), value];
Expand Down Expand Up @@ -220,62 +297,6 @@ function processFirstLine(
}
}

/**
* Updates the severity and confidence fields of the finding based on the key-value pair.
* @param finding - The `VulnerableApiFinding` object to update.
* @param key - The key indicating the type of information (`severity` or `confidence`).
* @param value - The value to set.
*/
function updateFindingSeverityAndConfidence(
finding: VulnerableApiFinding,
key: string,
value: string
): void {
if (key === 'severity') {
finding.severity = value;
} else if (key === 'confidence') {
finding.confidence = value;
}
}

/**
* Updates the current section of the finding based on the key.
* @param key - The key indicating the section to update.
* @param currentSection - The current section of the finding.
* @returns The updated section of the finding.
*/
function updateSection(
key: string,
currentSection: VulnerableApiFindingSection
): VulnerableApiFindingSection {
switch (key) {
case 'request':
case 'method':
return 'request';

case 'response':
case 'reason':
case 'text':
case 'status_code':
return 'response';

case 'headers':
return currentSection === 'response'
? 'response-headers'
: 'request-headers';

case 'params':
return 'params';

case 'severity':
case 'confidence':
return 'other';

default:
return currentSection;
}
}

/**
* Updates a specific field in the `VulnerableApiFinding` based on the current section.
* @param finding - The `VulnerableApiFinding` object to update.
Expand All @@ -287,18 +308,14 @@ function updateFindingField(
finding: VulnerableApiFinding,
key: string,
value: string,
currentSection: VulnerableApiFindingSection
currentSection: NestedKeyOf<VulnerableApiFinding>
): void {
const isRequestSection = currentSection === 'request';
const isResponseSection = currentSection === 'response';
const isParamsSection = currentSection === 'params';
const isRequestSection = currentSection.startsWith('request');
const isResponseSection = currentSection.startsWith('response');
const isParamsSection = currentSection.startsWith('request.params');

if (key === 'body') {
if (isRequestSection) {
finding.request.body = value;
} else if (isResponseSection) {
finding.response.text = value;
}
if (key === 'body' && isRequestSection) {
finding.request.body = value;
} else if (key === 'url') {
if (isRequestSection || isParamsSection) {
finding.request.url = value;
Expand All @@ -311,15 +328,19 @@ function updateFindingField(
finding.response.status_code = Number(value);
} else if (key === 'reason' && isResponseSection) {
finding.response.reason = value;
} else if (key === 'text' && isResponseSection) {
finding.response.text = value;
} else if (key === 'severity') {
finding.severity = value;
} else if (key === 'confidence') {
finding.confidence = value;
} else if (key === 'key' && isParamsSection) {
finding.request.params.key = value;
} else if (key === 'token' && isParamsSection) {
finding.request.params.token = value;
}
}

/**
* Updates the headers of the finding based on the current section.
* @param currentHeaders - The current headers to update.
* @param key - The key of the header.
* @param value - The value of the header.
*/
function updateFindingHeaders(
currentHeaders: Record<string, string> | null,
key: string,
Expand All @@ -330,59 +351,31 @@ function updateFindingHeaders(
}
}

/**
* Updates the parameters of the finding.
* @param paramKey - The key of the parameter.
* @param paramValue - The value of the parameter.
* @param finding - The `VulnerableApiFinding` object to update.
*/
function updateFindingParams(
paramKey: string,
paramValue: string | undefined,
finding: VulnerableApiFinding
): void {
if (paramKey === 'key' || paramKey === 'token') {
finding.request.params[paramKey] = paramValue || '';
}
}

/**
* Updates a `VulnerableApiFinding` based on the key-value pair and current section.
* @param finding - The `VulnerableApiFinding` object to update.
* @param key - The key indicating what to update.
* @param value - The value to set.
* @param currentSection - The current section of the finding.
* @param currentHeaders - The current headers being processed.
* @returns The updated section and headers.
*/
function updateVulnerableApiFinding(
finding: VulnerableApiFinding,
key: string,
value: string,
currentSection: VulnerableApiFindingSection,
currentSection: NestedKeyOf<VulnerableApiFinding>,
currentHeaders: Record<string, string> | null
): {
updatedSection: VulnerableApiFindingSection;
updatedSection: NestedKeyOf<VulnerableApiFinding>;
updatedHeaders: Record<string, string> | null;
} {
updateFindingSeverityAndConfidence(finding, key, value);

currentSection = updateSection(key, currentSection);

updateFindingField(finding, key, value, currentSection);

if (key === 'headers' && currentSection === 'request-headers') {
currentHeaders = finding.request.headers;
} else if (key === 'headers' && currentSection === 'response-headers') {
currentHeaders = finding.response.headers;
} else if (key === 'params') {
currentSection = 'params';
} else if (currentSection === 'params') {
updateFindingParams(key, value, finding);
} else if (
currentSection === 'request-headers' ||
currentSection === 'response-headers'
) {
if (key === 'headers' && value === '') {
return { updatedSection: currentSection, updatedHeaders: currentHeaders };
}

// Handle headers separately based on the current section
if (currentSection.endsWith('headers')) {
if (currentSection === 'request.headers') {
currentHeaders = finding.request.headers;
} else if (currentSection === 'response.headers') {
currentHeaders = finding.response.headers;
}
updateFindingHeaders(currentHeaders, key, value);
}

Expand Down
Loading

0 comments on commit dfe1e3a

Please sign in to comment.