gosec/report/html/template.html

440 lines
17 KiB
HTML
Raw Normal View History

2016-10-18 06:36:35 +01:00
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Golang Security Checker</title>
<link rel="shortcut icon" type="image/png" href="https://securego.io/img/favicon.png">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.9.4/css/bulma.min.css" integrity="sha512-HqxHUkJM0SYcbvxUw5P60SzdOTy/QVwA1JJrvaXJv4q7lmbDZCmZaqz01UPOaQveoxfYRv1tHozWGPMcuTBuvQ==" crossorigin="anonymous"/>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.8.0/styles/default.min.css" integrity="sha512-hasIneQUHlh06VNBe7f6ZcHmeRTLIaQWFd43YriJ0UND19bvYRauxthDg8E4eVNPm9bRUhr5JGeqH7FRFXQu5g==" crossorigin="anonymous"/>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.8.0/highlight.min.js" integrity="sha512-rdhY3cbXURo13l/WU9VlaRyaIYeJ/KBakckXIvJNAQde8DgpOmE+eZf7ha4vdqVjTtwQt69bD2wH2LXob/LB7Q==" crossorigin="anonymous"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.8.0/languages/go.min.js" integrity="sha512-Ea+IN1qMvgwTqOnwxM38Hn54IaDS2buEvMJNTdSB5JOT4njx3RvPij353zbUMpT+zYjDqQDr2UbrbnW5+wE54A==" crossorigin="anonymous"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/react/15.7.0/react.min.js" integrity="sha512-+TFn1Gqbwx/qgwW3NU1/YtFYTfHGeD1e/8YfJZzkb6TFEZP4SUwp1Az9DMeWh3qC0F+YPKXbV3YclMUwBTvO3g==" crossorigin="anonymous"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/react/15.6.1/react-dom.min.js" integrity="sha512-8C49ZG/SaQnWaUgCHTU1o8uIQNYE6R8me38SwF26g2Q0byEXF4Jlvm+T/JAMHMeTBiEVPslSZRv9Xt4AV0pfmw==" crossorigin="anonymous"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/7.21.8/babel.min.js" integrity="sha512-DRxICTZtxfvZvBxkTUxZdZ5WFmRZxZek7VLed4uhb+lhO5NQO+FidA81LX9lO3YnLKQLTx5S37Ut6+yWR9W5AQ==" crossorigin="anonymous"></script>
2016-10-18 06:36:35 +01:00
<style>
2021-05-25 09:10:42 +01:00
.field-label {
min-width: 80px;
}
.break-word {
word-wrap: break-word;
}
.help {
white-space: pre-wrap;
}
.tag {
width: 80px;
}
2021-08-19 13:53:39 +01:00
.summary-first {
padding: .75rem .75rem .1rem .75rem;
}
.summary-last {
padding: .1rem .75rem .75rem .75rem;
}
.summary {
padding: .1rem .75rem ;
}
2016-10-18 06:36:35 +01:00
</style>
</head>
<body>
<section class="section">
<div class="container">
<div id="content"></div>
</div>
</section>
<script>
var data = {{ . }};
</script>
<script type="text/babel">
var IssueTag = React.createClass({
render: function() {
2021-05-25 09:10:42 +01:00
var level = "tag"
2016-10-18 06:36:35 +01:00
if (this.props.level === "HIGH") {
2021-05-25 09:10:42 +01:00
level += " is-danger";
2021-05-21 07:13:20 +01:00
} else if (this.props.level === "MEDIUM") {
2021-05-25 09:10:42 +01:00
level += " is-warning";
} else if (this.props.level === "LOW") {
level += " is-info";
} else if (this.props.level === "WAIVED") {
level += " is-success";
2016-10-18 06:36:35 +01:00
}
2021-05-25 09:10:42 +01:00
level +=" is-rounded";
2016-10-18 06:36:35 +01:00
return (
2021-05-25 09:10:42 +01:00
<div className="control">
<div className="tags has-addons">
<span className="tag is-dark is-rounded">{ this.props.label }</span>
<span className={ level }>{ this.props.level }</span>
</div>
2016-10-18 06:36:35 +01:00
</div>
);
}
});
2021-05-25 09:10:42 +01:00
var Highlight = React.createClass({
componentDidMount: function(){
var current = ReactDOM.findDOMNode(this);
hljs.highlightElement(current);
},
render: function() {
return (
<pre className="go"><code >{ this.props.code }</code></pre>
);
}
});
2016-10-18 06:36:35 +01:00
var Issue = React.createClass({
render: function() {
return (
<div className="issue box">
2021-05-25 09:10:42 +01:00
<div className="columns">
<div className="column is-three-quarters">
<strong className="break-word">{ this.props.data.file } (line { this.props.data.line })</strong>
<p>{this.props.data.rule_id} (CWE-{this.props.data.cwe.id}): { this.props.data.details }</p>
2021-05-25 09:10:42 +01:00
</div>
<div className="column is-one-quarter">
<div className="field is-grouped is-grouped-multiline">
{this.props.data.nosec && <IssueTag label="NoSec" level="WAIVED"/>}
2021-05-25 09:10:42 +01:00
<IssueTag label="Severity" level={ this.props.data.severity }/>
<IssueTag label="Confidence" level={ this.props.data.confidence }/>
</div>
</div>
</div>
<div className="highlight">
2021-08-19 13:54:12 +01:00
<Highlight key={ this.props.data.file + this.props.data.line } code={ this.props.data.code }/>
2016-10-18 06:36:35 +01:00
</div>
</div>
);
}
});
var Stats = React.createClass({
render: function() {
return (
2021-05-25 09:10:42 +01:00
<p className="help is-pulled-right">
Gosec {this.props.data.GosecVersion} scanned { this.props.data.Stats.files.toLocaleString() } files
with { this.props.data.Stats.lines.toLocaleString() } lines of code.
{ this.props.data.Stats.nosec ? '\n' + this.props.data.Stats.nosec.toLocaleString() + ' false positives (nosec) have been waived.' : ''}
2016-10-18 06:36:35 +01:00
</p>
);
}
});
var Issues = React.createClass({
render: function() {
if (this.props.data.Stats.files === 0) {
2016-10-18 06:36:35 +01:00
return (
<div className="notification">
No source files found. Do you even Go?
</div>
);
}
if (this.props.data.Issues.length === 0) {
2016-10-18 06:36:35 +01:00
return (
<div>
<div className="notification">
Awesome! No issues found!
</div>
<Stats data={ this.props.data } />
</div>
);
}
var issues = this.props.data.Issues
2016-10-18 06:36:35 +01:00
.filter(function(issue) {
return this.props.severity.includes(issue.severity);
}.bind(this))
.filter(function(issue) {
return this.props.confidence.includes(issue.confidence);
}.bind(this))
.filter(function(issue) {
if (this.props.issueType) {
return issue.details.toLowerCase().startsWith(this.props.issueType.toLowerCase());
} else {
return true
}
}.bind(this))
.map(function(issue) {
return (<Issue data={issue} />);
}.bind(this));
if (issues.length === 0) {
return (
<div>
<div className="notification">
No issues matched given filters
(of total { this.props.data.Issues.length } issues).
2016-10-18 06:36:35 +01:00
</div>
<Stats data={ this.props.data } />
</div>
);
}
return (
<div className="issues">
{ issues }
<Stats data={ this.props.data } />
</div>
);
}
});
var LevelSelector = React.createClass({
handleChange: function(level) {
return function(e) {
var updated = this.props.selected
.filter(function(item) { return item != level; });
if (e.target.checked) {
updated.push(level);
}
this.props.onChange(updated);
}.bind(this);
},
render: function() {
var HIGH = "HIGH", MEDIUM = "MEDIUM", LOW = "LOW";
var highDisabled = !this.props.available.includes(HIGH);
var mediumDisabled = !this.props.available.includes(MEDIUM);
var lowDisabled = !this.props.available.includes(LOW);
2016-10-18 06:36:35 +01:00
return (
2021-05-25 09:10:42 +01:00
<div className="field">
<div className="control">
<label className="checkbox" disabled={ highDisabled }>
<input
type="checkbox"
checked={ this.props.selected.includes(HIGH) }
disabled={ highDisabled }
onChange={ this.handleChange(HIGH) }/> High
</label>
</div>
<div className="control">
<label className="checkbox" disabled={ mediumDisabled }>
<input
type="checkbox"
checked={ this.props.selected.includes(MEDIUM) }
disabled={ mediumDisabled }
onChange={ this.handleChange(MEDIUM) }/> Medium
</label>
</div>
<div className="control">
<label className="checkbox" disabled={ lowDisabled }>
<input
type="checkbox"
checked={ this.props.selected.includes(LOW) }
disabled={ lowDisabled }
onChange={ this.handleChange(LOW) }/> Low
</label>
</div>
</div>
2016-10-18 06:36:35 +01:00
);
}
});
var Navigation = React.createClass({
updateSeverity: function(vals) {
this.props.onSeverity(vals);
},
updateConfidence: function(vals) {
this.props.onConfidence(vals);
},
updateIssueType: function(e) {
if (e.target.value == "all") {
this.props.onIssueType(null);
} else {
this.props.onIssueType(e.target.value);
}
},
render: function() {
var issueTypes = this.props.allIssueTypes
.map(function(it) {
var matches = this.props.issueType == it
2016-10-18 06:36:35 +01:00
return (
<option value={ it } selected={ matches }>
2016-10-18 06:36:35 +01:00
{ it }
</option>
);
}.bind(this));
return (
2021-08-19 13:53:39 +01:00
<div>
2021-08-20 09:27:45 +01:00
<nav className="panel">
<div className="panel-heading">Filters</div>
<div className="panel-block">
<div className="field is-horizontal">
<div className="field-label is-normal">
<label className="label is-pulled-left">Severity</label>
</div>
<div className="field-body">
<LevelSelector selected={ this.props.severity } available={ this.props.allSeverities } onChange={ this.updateSeverity } />
</div>
</div>
</div>
<div className="panel-block">
<div className="field is-horizontal">
<div className="field-label is-normal">
<label className="label is-pulled-left">Confidence</label>
</div>
<div className="field-body">
<LevelSelector selected={ this.props.confidence } available={ this.props.allConfidences } onChange={ this.updateConfidence } />
</div>
</div>
</div>
<div className="panel-block">
<div className="field is-horizontal">
<div className="field-label is-normal">
<label className="label is-pulled-left">Issue type</label>
</div>
<div className="field-body">
<div className="field">
<div className="control">
<div className="select is-fullwidth">
<select onChange={ this.updateIssueType }>
<option value="all" selected={ !this.props.issueType }>
(all)
</option>
{ issueTypes }
</select>
</div>
</div>
</div>
</div>
</div>
</div>
2021-08-19 13:53:39 +01:00
</nav>
2021-08-20 09:27:45 +01:00
<nav className="panel">
<div className="panel-heading">Summary</div>
<div className="panel-block">
<div className="columns is-multiline">
<div className="column is-half summary-first">
<label className="label is-pulled-left">Gosec: </label>
</div>
<div className="column is-half summary-first">
{this.props.data.GosecVersion}
</div>
<div className="column is-half summary">
<label className="label is-pulled-left">Files: </label>
</div>
<div className="column is-half summary">
{this.props.data.Stats.files.toLocaleString()}
</div>
<div className="column is-half summary">
<label className="label is-pulled-left">Lines: </label>
</div>
<div className="column is-half summary">
{this.props.data.Stats.lines.toLocaleString()}
</div>
<div className="column is-half summary">
<label className="label is-pulled-left">Nosec: </label>
</div>
<div className="column is-half summary">
{this.props.data.Stats.nosec.toLocaleString()}
</div>
<div className="column is-half summary-last">
<label className="label is-pulled-left">Issues: </label>
</div>
<div className="column is-half summary-last">
{this.props.data.Stats.found.toLocaleString()}
</div>
</div>
</div>
</nav>
</div>
2016-10-18 06:36:35 +01:00
);
}
});
var IssueBrowser = React.createClass({
getInitialState: function() {
return {};
},
componentWillMount: function() {
this.updateIssues(this.props.data);
},
handleSeverity: function(val) {
this.updateIssueTypes(this.props.data.Issues, val, this.state.confidence);
2016-10-18 06:36:35 +01:00
this.setState({severity: val});
},
handleConfidence: function(val) {
this.updateIssueTypes(this.props.data.Issues, this.state.severity, val);
2016-10-18 06:36:35 +01:00
this.setState({confidence: val});
},
handleIssueType: function(val) {
this.setState({issueType: val});
},
updateIssues: function(data) {
if (!data) {
this.setState({data: data});
return;
}
var allSeverities = data.Issues
2016-10-18 06:36:35 +01:00
.map(function(issue) {
return issue.severity
})
.sort()
.filter(function(item, pos, ary) {
return !pos || item != ary[pos - 1];
});
var allConfidences = data.Issues
2016-10-18 06:36:35 +01:00
.map(function(issue) {
return issue.confidence
})
.sort()
.filter(function(item, pos, ary) {
return !pos || item != ary[pos - 1];
});
var selectedSeverities = allSeverities;
var selectedConfidences = allConfidences;
this.updateIssueTypes(data.Issues, selectedSeverities, selectedConfidences);
2016-10-18 06:36:35 +01:00
this.setState({
data: data,
severity: selectedSeverities,
allSeverities: allSeverities,
confidence: selectedConfidences,
allConfidences: allConfidences,
issueType: null
});
},
updateIssueTypes: function(issues, severities, confidences) {
var allTypes = issues
.filter(function(issue) {
return severities.includes(issue.severity);
})
.filter(function(issue) {
return confidences.includes(issue.confidence);
})
.map(function(issue) {
return issue.details;
})
.sort()
.filter(function(item, pos, ary) {
return !pos || item != ary[pos - 1];
});
if (this.state.issueType && !allTypes.includes(this.state.issueType)) {
this.setState({issueType: null});
}
this.setState({allIssueTypes: allTypes});
},
render: function() {
return (
<div className="content">
<div className="columns">
<div className="column is-one-quarter">
<Navigation
2021-08-19 13:53:39 +01:00
data={ this.props.data }
2016-10-18 06:36:35 +01:00
severity={ this.state.severity }
confidence={ this.state.confidence }
issueType={ this.state.issueType }
allSeverities={ this.state.allSeverities }
allConfidences={ this.state.allConfidences }
allIssueTypes={ this.state.allIssueTypes }
onSeverity={ this.handleSeverity }
onConfidence={ this.handleConfidence }
onIssueType={ this.handleIssueType }
/>
</div>
<div className="column is-three-quarters">
<Issues
data={ this.props.data }
severity={ this.state.severity }
confidence={ this.state.confidence }
issueType={ this.state.issueType }
/>
</div>
</div>
</div>
);
}
});
ReactDOM.render(
<IssueBrowser data={ data } />,
document.getElementById("content")
);
</script>
</body>
2021-11-15 15:17:22 +00:00
</html>