Skip to content

Commit

Permalink
Merge branch 'develop' into crasm-791
Browse files Browse the repository at this point in the history
  • Loading branch information
Janson Bunce committed Oct 30, 2024
2 parents b791c79 + 1805b30 commit 5b5f351
Show file tree
Hide file tree
Showing 13 changed files with 154 additions and 56 deletions.
6 changes: 6 additions & 0 deletions backend/src/api/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,12 @@ app.use(
})
);

//Middleware to set Cache-Control headers
app.use((req, res, next) => {
res.setHeader('Cache-Control', 'no-cache, no-store, must-revalidate');
next();
});

app.use((req, res, next) => {
res.setHeader('X-XSS-Protection', '0');
// Okta header
Expand Down
18 changes: 17 additions & 1 deletion frontend/scripts/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,14 +65,30 @@ app.use(
})
);

//Middleware to set Cache-Control headers
app.use((req, res, next) => {
res.setHeader('Cache-Control', 'no-cache, no-store, must-revalidate');
next();
});

app.use((req, res, next) => {
res.setHeader('X-XSS-Protection', '0');
next();
});

app.use(express.static(path.join(__dirname, '../build')));
app.use(
express.static(path.join(__dirname, '../build'), {
setHeaders: (res, path) => {
if (path.endsWith('.js')) {
res.setHeader('Content-Type', 'application/javascript');
}
},
maxAge: 'no-cache, no-store, must-revalidate'
})
);

app.use((req, res) => {
res.setHeader('Content-Type', 'text/html');
res.sendFile(path.join(__dirname, '../build/index.html'));
});

Expand Down
6 changes: 6 additions & 0 deletions frontend/scripts/docs.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,12 @@ app.use(
})
);

//Middleware to set Cache-Control headers
app.use((req, res, next) => {
res.setHeader('Cache-Control', 'private, max-age=3600');
next();
});

app.use((req, res, next) => {
res.setHeader('X-XSS-Protection', '0');
next();
Expand Down
19 changes: 6 additions & 13 deletions frontend/src/components/DomainDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ import { DefinitionList } from './DefinitionList';
import { differenceInCalendarDays, parseISO } from 'date-fns';
import { Webpage } from 'types';
import { useAuthContext } from 'context';
import { Stack } from '@mui/system';

const PREFIX = 'DomainDetails';

Expand Down Expand Up @@ -336,21 +335,15 @@ export const DomainDetails: React.FC<Props> = (props) => {
const webpageTree = generateWebpageTree(webpages);
const webpageList = generateWebpageList(webpageTree);

const backToResults = () => {
history.push('/inventory');
};

return (
<>
<Stack
direction="row"
spacing={1}
alignItems="center"
onClick={backToResults}
<Button
onClick={() => history.goBack()}
startIcon={<KeyboardBackspace />}
>
<KeyboardBackspace color="primary" />
<Button>Back To Results</Button>
</Stack>
Back To Results
</Button>
{/* </Stack> */}

<StyledPaper classes={{ root: classes.root }}>
<div className={classes.title}>
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/components/Logs/Logs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ import {
Dialog,
DialogContent,
DialogTitle,
Icon,
IconButton,
Paper
} from '@mui/material';
import OpenInNewIcon from '@mui/icons-material/OpenInNew';
import { Box } from '@mui/system';
import {
DataGrid,
Expand Down Expand Up @@ -149,7 +149,7 @@ export const Logs: FC<LogsProps> = () => {
setDialogDetails(cellValues.row);
}}
>
<Icon>info</Icon>
<OpenInNewIcon />
</IconButton>
);
}
Expand Down
19 changes: 19 additions & 0 deletions frontend/src/components/RegionAndOrganizationFilters.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,25 @@ export const RegionAndOrganizationFilters: React.FC<
const sortedOrgs = filteredOrgs.sort((a, b) =>
a.name.localeCompare(b.name)
);

// Utility function to replce HTML encodings
const decodeHtml = (orgName: string): string => {
const encodings: { [key: string]: string } = {
'&amp;': '&',
'&lt;': '<',
'&gt;': '>',
'&quot;': '"',
'&#039;': "'"
};
return orgName.replace(/&amp;|&lt;|&gt;|&quot;|&#039;/g, (m) => {
return encodings[m];
});
};
// Decode HTML encodings in org names
sortedOrgs.forEach((org) => {
org.name = decodeHtml(org.name);
});

setOrgResults(sortedOrgs);
} catch (e) {
console.log(e);
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/hooks/useUserTypeFilters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ export const useUserTypeFilters: UseUserTypeFilters = (
},
{
field: 'organizationId',
values: userOrgs,
values: [],
type: 'any'
}
];
Expand Down
6 changes: 5 additions & 1 deletion frontend/src/pages/RegionUsers/RegionUsers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import DoneIcon from '@mui/icons-material/Done';
import { CheckCircleOutline as CheckIcon } from '@mui/icons-material';
import CloseIcon from '@mui/icons-material/Close';
import { useUserLevel } from 'hooks/useUserLevel';
import { formatDate, parseISO } from 'date-fns';

type DialogStates = {
isOrgDialogOpen: boolean;
Expand All @@ -37,7 +38,10 @@ const transformData = (data: User[]): User[] => {
return data.map(({ roles, ...user }) => ({
...user,
roles,
organizations: roles.map((role) => ' ' + role.organization.name)
organizations: roles.map((role) => ' ' + role.organization.name),
lastLoggedIn: user.lastLoggedIn
? formatDate(parseISO(user.lastLoggedIn), 'MM/dd/yyyy hh:mm a')
: 'None'
}));
};
export const RegionUsers: React.FC = () => {
Expand Down
30 changes: 28 additions & 2 deletions frontend/src/pages/Risk/Risk.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { useCallback, useState, useEffect, useMemo } from 'react';
import classes from './Risk.module.scss';
import { Card, CardContent, Grid, Paper, Typography } from '@mui/material';
import { Box, Card, CardContent, Grid, Paper, Typography } from '@mui/material';
import VulnerabilityCard from './VulnerabilityCard';
import TopVulnerablePorts from './TopVulnerablePorts';
import TopVulnerableDomains from './TopVulnerableDomains';
Expand All @@ -26,6 +26,7 @@ import {
REGION_FILTER_KEY
} from 'components/RegionAndOrganizationFilters';
import { withSearch } from '@elastic/react-search-ui';
import { FilterTags } from 'pages/Search/FilterTags';

export interface Point {
id: string;
Expand Down Expand Up @@ -53,7 +54,12 @@ let colorScale = scaleLinear<string>()
.domain([0, 1])
.range(['#c7e8ff', '#135787']);

const Risk: React.FC<ContextType & {}> = ({ filters, addFilter }) => {
const Risk: React.FC<ContextType & {}> = ({
filters,
removeFilter,
searchTerm,
setSearchTerm
}) => {
const { showMaps, user, apiPost } = useAuthContext();

const [stats, setStats] = useState<Stats | undefined>(undefined);
Expand Down Expand Up @@ -88,6 +94,20 @@ const Risk: React.FC<ContextType & {}> = ({ filters, addFilter }) => {
};
}, [filters]);

const filtersToDisplay = useMemo(() => {
if (searchTerm !== '') {
return [
...filters,
{
field: 'query',
values: [searchTerm],
onClear: () => setSearchTerm('', { shouldClearFilters: false })
}
];
}
return filters;
}, [filters, searchTerm, setSearchTerm]);

const fetchStats = useCallback(
async (orgId?: string) => {
const { result } = await apiPost<ApiResponse>('/stats', {
Expand Down Expand Up @@ -264,6 +284,12 @@ const Risk: React.FC<ContextType & {}> = ({ filters, addFilter }) => {
<Grid item sm={11} lg={10} xl={8} sx={{ maxWidth: '1500px' }}>
<RiskRoot className={classes.root}>
<div id="wrapper" className={contentWrapper}>
<Box sx={{ px: '1rem', pb: '2rem' }}>
<FilterTags
filters={filtersToDisplay}
removeFilter={removeFilter}
/>
</Box>
{stats && (
<Grid container>
<Grid item xs={12} sm={12} md={12} lg={6} xl={6} mb={-4}>
Expand Down
61 changes: 50 additions & 11 deletions frontend/src/pages/Risk/VulnerabilityBarChart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,18 +73,52 @@ const VulnerabilityBarChart = (props: {
</>
);

// Map data to BarData structure
const mappedData: BarData[] = data.map((d) => ({
id: d.id,
value: d.value
}));

// Sort the data to ensure "Low", "Medium", and "High" appear in the desired order
const sortedData = [...mappedData].sort((a, b) => {
const order = ['Low', 'Medium', 'High'];
return order.indexOf(a.id) - order.indexOf(b.id);
// Place null values in "N/A" and capitalize the first letter of each word in the data.
const titleCaseData: BarData[] = data.map((d) => {
if (d.id === 'null') {
return { id: 'N/A', value: d.value };
} else {
return {
id: d.id[0].toUpperCase() + d.id.slice(1).toLowerCase(),
value: d.value
};
}
});

// Group the data by severity level and "Other". Sum the values for each group.
const groupedData = titleCaseData
.map((d) => {
const severityLevels = [
'N/A',
'Low',
'Medium',
'High',
'Critical',
'Other'
];
if (severityLevels.includes(d.id)) {
return d;
} else {
return { id: 'Other', value: d.value };
}
})
.reduce((acc: { [key: string]: number }, curr) => {
if (acc[curr.id]) {
acc[curr.id] += curr.value;
} else {
acc[curr.id] = curr.value;
}
return acc;
}, {});

// Sort the data to ensure "N/A", "Low", "Medium", "High", and "Critical" appear in the desired order
const sortedData = Object.entries(groupedData)
.map(([id, value]) => ({ id, value }))
.sort((a, b) => {
const order = ['N/A', 'Low', 'Medium', 'High', 'Critical', 'Other'];
return order.indexOf(a.id) - order.indexOf(b.id);
});

useEffect(() => {
const label =
`${title} bar chart. ` +
Expand All @@ -105,7 +139,12 @@ const VulnerabilityBarChart = (props: {
const severityColor = getSeverityColor({ id: indexValue });
const serviceColor = getServicesColor({ id: indexValue });
const color =
indexValue === 'Low' || indexValue === 'Medium' || indexValue === 'High'
indexValue === 'N/A' ||
indexValue === 'Low' ||
indexValue === 'Medium' ||
indexValue === 'High' ||
indexValue === 'Critical' ||
indexValue === 'Other'
? severityColor
: serviceColor;
return color;
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/pages/Risk/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,11 @@ export const getAllVulnColor = () => {
return '#ce80ed';
};
export const getSeverityColor = ({ id }: { id: string }) => {
if (id === 'null' || id === '') return '#EFF1F5';
if (id === 'N/A' || id === '') return '#EFF1F5';
else if (id === 'Low') return '#ffe100';
else if (id === 'Medium') return '#f66e1f';
else if (id === 'High') return '#ed240e';
else if (id === 'Other') return '#6BA7F5';
else return '#540C03';
};
export const getCVSSColor = (score: number) => {
Expand Down
8 changes: 2 additions & 6 deletions frontend/src/pages/Search/FilterTags.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -159,18 +159,14 @@ export const FilterTags: React.FC<Props> = ({ filters, removeFilter }) => {
}, [filters]);

return (
<Root>
<Root aria-live="polite" aria-atomic="true">
{filtersByColumn.map((filter, idx) => (
<Chip
key={idx}
disabled={disabledFilters?.includes(filter.label)}
color={'primary'}
classes={{ root: classes.chip }}
label={
<>
<strong>{filter.label}:</strong> {filter.value}
</>
}
label={`${filter.label}: ${filter.value}`}
onDelete={() => {
if (filter.onClear) {
console.log('custom clear');
Expand Down
28 changes: 10 additions & 18 deletions frontend/src/pages/Vulnerability/Vulnerability.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import React, { useCallback, useEffect, useState } from 'react';
import { Link, useParams, useHistory } from 'react-router-dom';
import { differenceInCalendarDays, parseISO } from 'date-fns';
import { ChevronLeft, OpenInNew } from '@mui/icons-material';
import { KeyboardBackspace, OpenInNew } from '@mui/icons-material';
import {
AppBar,
Box,
Button,
Grid,
IconButton,
Link as LinkMui,
Expand Down Expand Up @@ -446,25 +447,16 @@ export const Vulnerability: React.FC = () => {
};

return (
<React.Fragment>
<Box ml={2} mt={2}>
<Link to="# " onClick={() => history.goBack()}>
<ChevronLeft
sx={{
height: '100%',
verticalAlign: 'middle',
marginTop: '-2px'
}}
></ChevronLeft>
Go back
</Link>
</Box>
<Box py={'2rem'} px={'1.5rem'}>
<Grid container>
<Grid item xs={1} xl={2} />
<Grid item xs={10} xl={8}>
<Typography variant="h4" gutterBottom mt={2}>
Vulnerability Details
</Typography>
<Button
onClick={() => history.goBack()}
startIcon={<KeyboardBackspace />}
>
Back to Results
</Button>
<OverviewSection />
</Grid>
<Grid item xs={1} xl={2} />
Expand Down Expand Up @@ -518,6 +510,6 @@ export const Vulnerability: React.FC = () => {
</Grid>
<Grid item xs={12} sx={{ height: '400px' }} />
</Grid>
</React.Fragment>
</Box>
);
};

0 comments on commit 5b5f351

Please sign in to comment.