mirror of
https://github.com/Lissy93/web-check.git
synced 2025-02-17 02:40:46 +01:00
Merge pull request #12 from Lissy93/FEAT/security-txt
Adds support for fetching, parsing and displaying the security.txt file Fixes #7
This commit is contained in:
commit
c8d29c78a2
@ -38,6 +38,7 @@
|
||||
"axios": "^1.4.0",
|
||||
"chrome-aws-lambda": "^10.1.0",
|
||||
"flatted": "^3.2.7",
|
||||
"follow-redirects": "^1.15.2",
|
||||
"got": "^13.0.0",
|
||||
"jest-styled-components": "^7.1.1",
|
||||
"netlify-cli": "^15.9.1",
|
||||
|
@ -34,7 +34,7 @@ const StyledExpandableRow = styled(StyledRow).attrs({
|
||||
as: "summary"
|
||||
})``;
|
||||
|
||||
const Details = styled.details`
|
||||
export const Details = styled.details`
|
||||
transition: all 0.2s ease-in-out;
|
||||
summary {
|
||||
padding-left: 1rem;
|
||||
|
67
src/components/Results/SecurityTxt.tsx
Normal file
67
src/components/Results/SecurityTxt.tsx
Normal file
@ -0,0 +1,67 @@
|
||||
|
||||
import { Card } from 'components/Form/Card';
|
||||
import Row, { Details } from 'components/Form/Row';
|
||||
import colors from 'styles/colors';
|
||||
|
||||
const cardStyles = `
|
||||
small {
|
||||
margin-top: 1rem;
|
||||
opacity: 0.5;
|
||||
display: block;
|
||||
a { color: ${colors.primary}; }
|
||||
}
|
||||
summary {
|
||||
padding: 0.5rem 0 0 0.5rem !important;
|
||||
cursor: pointer;
|
||||
font-weight: bold;
|
||||
}
|
||||
pre {
|
||||
background: ${colors.background};
|
||||
padding: 0.5rem 0.25rem;
|
||||
border-radius: 4px;
|
||||
overflow: auto;
|
||||
}
|
||||
`;
|
||||
|
||||
const getPagePath = (url: string): string => {
|
||||
try {
|
||||
return new URL(url).pathname;
|
||||
} catch (error) {
|
||||
return url;
|
||||
}
|
||||
}
|
||||
|
||||
const SecurityTxtCard = (props: {data: any, title: string, actionButtons: any }): JSX.Element => {
|
||||
const securityTxt = props.data;
|
||||
return (
|
||||
<Card heading={props.title} actionButtons={props.actionButtons} styles={cardStyles}>
|
||||
<Row lbl="Present" val={securityTxt.isPresent ? '✅ Yes' : '❌ No'} />
|
||||
{ securityTxt.isPresent && (
|
||||
<>
|
||||
<Row lbl="File Location" val={securityTxt.foundIn} />
|
||||
<Row lbl="PGP Signed" val={securityTxt.isPgpSigned ? '✅ Yes' : '❌ No'} />
|
||||
{securityTxt.fields && Object.keys(securityTxt.fields).map((field: string, index: number) => {
|
||||
if (securityTxt.fields[field].includes('http')) return (
|
||||
<Row lbl="" val="" key={`policy-url-row-${index}`}>
|
||||
<span className="lbl">{field}</span>
|
||||
<span className="val"><a href={securityTxt.fields[field]}>{getPagePath(securityTxt.fields[field])}</a></span>
|
||||
</Row>
|
||||
);
|
||||
return (
|
||||
<Row lbl={field} val={securityTxt.fields[field]} key={`policy-row-${index}`} />
|
||||
);
|
||||
})}
|
||||
<Details>
|
||||
<summary>View Full Policy</summary>
|
||||
<pre>{securityTxt.content}</pre>
|
||||
</Details>
|
||||
</>
|
||||
)}
|
||||
{!securityTxt.isPresent && (<small>
|
||||
Having a security.txt ensures security researchers know how and where to safely report vulnerabilities.
|
||||
</small>)}
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
export default SecurityTxtCard;
|
@ -201,6 +201,7 @@ const jobNames = [
|
||||
'txt-records',
|
||||
'sitemap',
|
||||
'hsts',
|
||||
'security-txt',
|
||||
// 'whois',
|
||||
'features',
|
||||
'carbon',
|
||||
|
@ -39,8 +39,10 @@ import SitemapCard from 'components/Results/Sitemap';
|
||||
import DomainLookup from 'components/Results/DomainLookup';
|
||||
import DnsServerCard from 'components/Results/DnsServer';
|
||||
import TechStackCard from 'components/Results/TechStack';
|
||||
import SecurityTxtCard from 'components/Results/SecurityTxt';
|
||||
import SelfScanMsg from 'components/misc/SelfScanMsg';
|
||||
|
||||
|
||||
import ProgressBar, { LoadingJob, LoadingState, initialJobs } from 'components/misc/ProgressBar';
|
||||
import ActionButtons from 'components/misc/ActionButtons';
|
||||
import keys from 'utils/get-keys';
|
||||
@ -351,6 +353,14 @@ const Results = (): JSX.Element => {
|
||||
fetchRequest: () => fetch(`${api}/screenshot?url=${address}`).then(res => parseJson(res)),
|
||||
});
|
||||
|
||||
// Get a websites listed pages, from sitemap
|
||||
const [securityTxtResults, updateSecurityTxtResults] = useMotherHook({
|
||||
jobId: 'security-txt',
|
||||
updateLoadingJobs,
|
||||
addressInfo: { address, addressType, expectedAddressTypes: urlTypeOnly },
|
||||
fetchRequest: () => fetch(`${api}/security-txt?url=${address}`).then(res => parseJson(res)),
|
||||
});
|
||||
|
||||
// Get site features from BuiltWith
|
||||
const [siteFeaturesResults, updateSiteFeaturesResults] = useMotherHook({
|
||||
jobId: 'features',
|
||||
@ -432,6 +442,7 @@ const Results = (): JSX.Element => {
|
||||
{ id: 'dnssec', title: 'DNSSEC', result: dnsSecResults, Component: DnsSecCard, refresh: updateDnsSecResults },
|
||||
{ id: 'status', title: 'Server Status', result: serverStatusResults, Component: ServerStatusCard, refresh: updateServerStatusResults },
|
||||
{ id: 'ports', title: 'Open Ports', result: portsResults, Component: OpenPortsCard, refresh: updatePortsResults },
|
||||
{ id: 'security-txt', title: 'Security.Txt', result: securityTxtResults, Component: SecurityTxtCard, refresh: updateSecurityTxtResults },
|
||||
{ id: 'screenshot', title: 'Screenshot', result: screenshotResult || lighthouseResults?.fullPageScreenshot?.screenshot, Component: ScreenshotCard, refresh: updateScreenshotResult },
|
||||
{ id: 'txt-records', title: 'TXT Records', result: txtRecordResults, Component: TxtRecordCard, refresh: updateTxtRecordResults },
|
||||
{ id: 'hsts', title: 'HSTS Check', result: hstsResults, Component: HstsCard, refresh: updateHstsResults },
|
||||
|
@ -3,7 +3,7 @@ interface Doc {
|
||||
title: string;
|
||||
description: string;
|
||||
use: string;
|
||||
resources: string[];
|
||||
resources: string[] | { title: string, link: string}[];
|
||||
screenshot?: string;
|
||||
}
|
||||
|
||||
@ -342,6 +342,26 @@ const docs: Doc[] = [
|
||||
],
|
||||
screenshot: 'https://i.ibb.co/GtrCQYq/Screenshot-from-2023-07-21-12-28-38.png',
|
||||
},
|
||||
{
|
||||
id: 'security-txt',
|
||||
title: 'Security.txt',
|
||||
description: "The security.txt file tells researchers how they can responsibly disclose any security issues found on your site. "
|
||||
+ "The standard was proposed in RFC 9116, and specifies that this file should include a point of contact (email address), "
|
||||
+ "as well as optionally other info, like a link to the security disclosure policy, PGP key, proffered language, policy expiry and more. "
|
||||
+ "The file should be located at the root of your domain, either at /security.txt or /.well-known/security.txt.",
|
||||
use: "This is important, as without a defined point of contact a security researcher may be unable to report a critical security issue, "
|
||||
+ "or may use insecure or possibly public channels to do so. From an OSINT perspective, you may also glean info about a site including "
|
||||
+ "their posture on security, their CSAF provider, and meta data from the PGP public key.",
|
||||
resources: [
|
||||
{ title: 'securitytxt.org', link: 'https://securitytxt.org/'},
|
||||
{ title: 'RFC-9116 Proposal', link: 'https://datatracker.ietf.org/doc/html/rfc9116'},
|
||||
{ title: 'RFC-9116 History', link: 'https://datatracker.ietf.org/doc/rfc9116/'},
|
||||
{ title: 'Security.txt (Wikipedia)', link: 'https://en.wikipedia.org/wiki/Security.txt'},
|
||||
{ title: 'Example security.txt (Cloudflare)', link: 'https://www.cloudflare.com/.well-known/security.txt'},
|
||||
{ title: 'Tutorial for creating security.txt (Pieter Bakker)', link: 'https://pieterbakker.com/implementing-security-txt/'},
|
||||
],
|
||||
screenshot: 'https://i.ibb.co/tq1FT5r/Screenshot-from-2023-07-24-20-31-21.png',
|
||||
},
|
||||
];
|
||||
|
||||
export const about = [
|
||||
|
@ -7802,7 +7802,7 @@ folder-walker@3.2.0:
|
||||
dependencies:
|
||||
from2 "^2.1.0"
|
||||
|
||||
follow-redirects@^1.0.0, follow-redirects@^1.15.0:
|
||||
follow-redirects@^1.0.0, follow-redirects@^1.15.0, follow-redirects@^1.15.2:
|
||||
version "1.15.2"
|
||||
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13"
|
||||
integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==
|
||||
|
Loading…
Reference in New Issue
Block a user