Skip to content

Commit

Permalink
Merge pull request #1010 from lunasec-io/1009-cwe-common-names-for-gi…
Browse files Browse the repository at this point in the history
…thub-advisories

cwe common names and cwe viewer
  • Loading branch information
breadchris authored Nov 30, 2022
2 parents 8839f02 + 9291117 commit 4b1bd82
Show file tree
Hide file tree
Showing 27 changed files with 957 additions and 201 deletions.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions lunatrace/bsl/backend/src/graphql-yoga/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ type BuildData_Cwe {
id: Int!
name: String!
description: String!
common_name: String
}

type BuildData_Guide_Vulnerability {
Expand Down
95 changes: 53 additions & 42 deletions lunatrace/bsl/backend/src/hasura-api/generated.ts

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ query GetTreeFromBuild($build_id: uuid!, $analysis_results_where: analysis_manif
id
name
description
common_name
}
}
}
Expand Down
108 changes: 72 additions & 36 deletions lunatrace/bsl/frontend/src/api/generated.ts

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ query GetCweDetails($id: Int!) {
extended_description
id
name
common_name
}
}
9 changes: 9 additions & 0 deletions lunatrace/bsl/frontend/src/api/graphql/getCwes.graphql
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
query GetCwes($limit: Int!, $offset: Int!, $where: vulnerability_cwe_bool_exp = {}) {
vulnerability_cwe(limit: $limit, offset: $offset, where: $where, order_by: {id: desc}) {
id
name
description
extended_description
common_name
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ query GetVulnerableReleasesFromBuild($buildId: uuid!, $minimumSeverity: String!)
id
name
description
common_name
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
*
*/
import { useContext } from 'react';
import { AlertOctagon, LogIn, Plus, User } from 'react-feather';
import { AlertOctagon, Aperture, LogIn, Plus, User } from 'react-feather';
import { AiFillGithub } from 'react-icons/ai';
import { BiUnlink } from 'react-icons/bi';
import { BsChatSquareText } from 'react-icons/bs';
Expand Down Expand Up @@ -101,6 +101,11 @@ export function generateSidebarItems(data: GetSidebarInfoQuery | undefined, isAu
icon: AlertOctagon,
title: 'Vulnerabilities Reference Database',
},
{
href: '/cwes',
icon: Aperture,
title: 'Common Weakness Enumerations Database',
},
];

const accountSection: SidebarItem[] = [
Expand Down
39 changes: 39 additions & 0 deletions lunatrace/bsl/frontend/src/pages/cwes/CweList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* Copyright by LunaSec (owned by Refinery Labs, Inc)
*
* Licensed under the Business Source License v1.1
* (the "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* https://github.com/lunasec-io/lunasec/blob/master/licenses/BSL-LunaTrace.txt
*
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
import React from 'react';
import { Container, Row, Spinner } from 'react-bootstrap';

import { CweListItem } from './CweListItem';
import { GetCwes } from './types';

interface ListProps {
cwes: GetCwes[];
isLoading: boolean;
}

export const CweList: React.FunctionComponent<ListProps> = ({ cwes, isLoading }) => {
const vulnCards = cwes.map((cwe) => {
return (
<Row key={cwe.id}>
<CweListItem cwe={cwe} />
</Row>
);
});
return (
<Container className="cwe-list">
{vulnCards}
{isLoading ? <Spinner animation="border" variant="primary" /> : null}
</Container>
);
};
66 changes: 66 additions & 0 deletions lunatrace/bsl/frontend/src/pages/cwes/CweListItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*
* Copyright by LunaSec (owned by Refinery Labs, Inc)
*
* Licensed under the Business Source License v1.1
* (the "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* https://github.com/lunasec-io/lunasec/blob/master/licenses/BSL-LunaTrace.txt
*
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
import React from 'react';
import { Card, Col, Container, Row } from 'react-bootstrap';
import { useNavigate } from 'react-router-dom';

import { GetCwes } from './types';

interface ListItemProps {
cwe: GetCwes;
}

export const CweListItem: React.FunctionComponent<ListItemProps> = ({ cwe }) => {
const navigate = useNavigate();

return (
<>
<Card
onClick={() => navigate(`/cwes/${cwe.id.toString()}`)}
className="flex-fill w-100 vulnerability clickable-card"
>
<Card.Header>
<Container fluid>
<Row>
<Col sm="6">
<Card.Title>
<h3>{cwe.name}</h3>
</Card.Title>
</Col>
<Col sm={{ span: 6 }} className="mt-xs-2 mt-sm-0">
<div>
<Card.Title className="text-right">
<span className="darker h4"> ID: </span>
<div style={{ display: 'inline-block' }}>
<h4 style={{ display: 'inline' }}>{`CWE-${cwe.id}`}</h4>
</div>
</Card.Title>
</div>
</Col>
</Row>
</Container>
</Card.Header>
<Card.Body className="d-flex">
<Container>
<Row>
<Col md={12}>
<p>{cwe.description}</p>
</Col>
</Row>
</Container>
</Card.Body>
</Card>
</>
);
};
86 changes: 86 additions & 0 deletions lunatrace/bsl/frontend/src/pages/cwes/Main.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import React, { useState } from 'react';
import { Button, Col, Container, Form, InputGroup, Row, Spinner } from 'react-bootstrap';
import { useBottomScrollListener } from 'react-bottom-scroll-listener';
import { Search } from 'react-feather';
import { Helmet } from 'react-helmet-async';

import api from '../../api';
import { Vulnerability_Cwe_Bool_Exp } from '../../api/generated';

import { CweList } from './CweList';

export const CwesMain: React.FunctionComponent = () => {
const [search, setSearch] = useState('');
const [cweLimit, setCweLimit] = useState(20);
const submitSearch = (search: string) => {
setSearch(search);
};

const parsedSearch = parseInt(search.toLowerCase().replace('cwe-', ''), 10);
const searchIsNumber = !isNaN(parsedSearch);

const searchConditions: Vulnerability_Cwe_Bool_Exp[] = [{ name: { _ilike: `%${search}%` } }];

if (searchIsNumber) {
searchConditions.push({ id: { _eq: parsedSearch } });
}

const where: Vulnerability_Cwe_Bool_Exp = {
_or: searchConditions,
};

const { data, isFetching, refetch } = api.useGetCwesQuery({
limit: cweLimit,
offset: 0,
where,
});

// lazy loading. Reloads all the old vulns when expanding the batch size but..it works fine
useBottomScrollListener(
() => {
if (data && data.vulnerability_cwe) {
const cweCount = data.vulnerability_cwe.length;
if (cweCount === cweLimit) {
setCweLimit(cweLimit + 20);
refetch();
}
}
},
{ offset: 200 }
);

return (
<>
<Helmet title="Common Weakness Enumeration (CWE) Index" />
<Container>
<Row className="mb-2 mb-xl-3">
<Col sm="6" md="4">
<form
onSubmit={(e) => {
e.preventDefault();
submitSearch(search);
}}
>
<InputGroup>
<Form.Control
placeholder="Search CWEs"
aria-label="Search CWEs"
value={search}
onChange={(e) => setSearch(e.target.value)}
/>
<Button type="submit" variant="">
{isFetching ? (
<Spinner as="span" animation="border" size="sm" role="status" aria-hidden="true" />
) : (
<Search className="feather" />
)}
</Button>
</InputGroup>
</form>
</Col>
</Row>
<CweList cwes={data?.vulnerability_cwe || []} isLoading={isFetching} />
</Container>
</>
);
};
41 changes: 41 additions & 0 deletions lunatrace/bsl/frontend/src/pages/cwes/detail/CweDetailMain.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import React from 'react';
import { Spinner } from 'react-bootstrap';
import { Helmet } from 'react-helmet-async';
import { useParams } from 'react-router-dom';

import api from '../../../api';

import { CweDetails } from './CweDetails';

export const CweDetailMain: React.FC = () => {
const { cwe_id } = useParams();

if (!cwe_id) {
return <p>Missing CWE ID in url.</p>;
}

const parsedCweId = parseInt(cwe_id, 10);

const cweIdIsNotANumber = isNaN(parsedCweId);
if (cweIdIsNotANumber) {
return <p>CWE ID is not a number: ${cwe_id}.</p>;
}

const { data, isFetching } = api.useGetCweDetailsQuery({ id: parsedCweId });
if (!data) {
return <Spinner animation="border" />;
}

return (
<>
{data && data.vulnerability_cwe_by_pk && !isFetching ? (
<>
<Helmet title={`CWE-${data.vulnerability_cwe_by_pk.id}`} />
<CweDetails cwe={data.vulnerability_cwe_by_pk} sideBySideView={false} />
</>
) : (
<Spinner animation="border" />
)}
</>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,14 @@ import React from 'react';
import { Card, Col, Container, Modal, Row, Table } from 'react-bootstrap';
import { ExternalLink } from 'react-feather';

import { CweInfoDetails } from './types';
import { CweInfoDetails } from '../../project/builds/types';

interface CweDetailBodyProps {
cwe: CweInfoDetails;
isEmbedded?: boolean;
sideBySideView?: boolean;
}

export const CweDetails: React.FunctionComponent<CweDetailBodyProps> = ({
isEmbedded = false,
sideBySideView = false,
cwe,
}) => {
export const CweDetails: React.FunctionComponent<CweDetailBodyProps> = ({ sideBySideView = false, cwe }) => {
return (
<>
<Container className="vulnerability-detail-page">
Expand All @@ -45,13 +40,19 @@ export const CweDetails: React.FunctionComponent<CweDetailBodyProps> = ({
</a>
</Col>
<hr />
<Col md={sideBySideView ? '12' : '8'} xs="12">
<Col md="12">
<Card>
<Card.Header>
<span className="lighter">{cwe.name}</span>
</Card.Header>
<Card.Body>
{cwe.common_name ? (
<p>
<span className={'lighter'}>Common Name:</span> {cwe.common_name}
</p>
) : null}
{cwe.description}
<hr />
{cwe.extended_description}
</Card.Body>
</Card>
Expand Down
3 changes: 3 additions & 0 deletions lunatrace/bsl/frontend/src/pages/cwes/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { GetCwesQuery } from '../../api/generated';

export type GetCwes = GetCwesQuery['vulnerability_cwe'][number];
4 changes: 2 additions & 2 deletions lunatrace/bsl/frontend/src/pages/project/builds/QuickView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ import { ArrowLeft } from 'react-feather';

import api from '../../../api';
import { StickyScrollableElement } from '../../../components/utils/StickyScrollableElement';
import { CweDetails } from '../../cwes/detail/CweDetails';
import { VulnerabilityDetailBody } from '../../vulnerabilities/detail/DetailBody';

import { CweDetails } from './CweDetails';
import { QuickViewCwe, QuickViewProps, QuickViewState, QuickViewVulnerability } from './types';

interface VulnQuickViewProps {
Expand All @@ -43,7 +43,7 @@ const CweQuickView: React.FC<CweQuickViewProps> = ({ cweState, sideBySideView })
return (
<>
{data && data.vulnerability_cwe_by_pk && !isFetching ? (
<CweDetails cwe={data.vulnerability_cwe_by_pk} isEmbedded={true} sideBySideView={sideBySideView} />
<CweDetails cwe={data.vulnerability_cwe_by_pk} sideBySideView={sideBySideView} />
) : (
<Spinner animation="border" />
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,14 @@ export const VulnInfoTableRow: React.FC<VulnerabilityTableItemProps> = ({ vulnMe
</OverlayTrigger>,
<div key={vulnMeta.vulnerability.id}>
{vulnMeta.vulnerability.cwes.map((c) => (
<CweBadge key={c.id} id={c.cwe.id} name={c.cwe.name} quickView={quickView} tooltipDescription={true} />
<CweBadge
key={c.id}
id={c.cwe.id}
name={c.cwe.name}
common_name={c.cwe.common_name}
quickView={quickView}
tooltipDescription={true}
/>
))}
</div>,
vulnMeta.vulnerability.severity_name,
Expand Down
Loading

0 comments on commit 4b1bd82

Please sign in to comment.