<!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/1.0.3/css/bulma.min.css" integrity="sha512-4EnjWdm80dyWrJ7rh/tlhNt6fJL52dSDSHNEqfdVmBLpJLPrRYnFa+Kn4ZZL+FRkDL5/7lAXuHylzJkpzkSM2A==" crossorigin="anonymous"/> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.11.1/styles/default.min.css" integrity="sha512-hasIneQUHlh06VNBe7f6ZcHmeRTLIaQWFd43YriJ0UND19bvYRauxthDg8E4eVNPm9bRUhr5JGeqH7FRFXQu5g==" crossorigin="anonymous"/> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.11.1/highlight.min.js" integrity="sha512-EBLzUL8XLl+va/zAsmXwS7Z2B1F9HUHkZwyS/VKwh3S7T/U0nF4BaU29EP/ZSf6zgiIxYAnKLu6bJ8dqpmX5uw==" crossorigin="anonymous"></script> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.11.1/languages/go.min.js" integrity="sha512-weC0VNVf2qQR6OY675qO0AEL92gt3h5f2VGjhMUvi/UqFHaWzIEL5S/8Dt763fWfKftchzb7GryvEj/2HC9Exw==" 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.26.4/babel.min.js" integrity="sha512-hX7KzoYtNHhNJsz8TAHyddcegokOwhmYiFWCDHqFkcoNVsYwCziO+NISSRlNKpfOYaqyQxm2+MTCJqSaHssJTA==" crossorigin="anonymous"></script> <style> .field-label { min-width: 80px; } .break-word { word-wrap: break-word; } .help { white-space: pre-wrap; } .tag { width: 80px; } .summary-first { padding: .75rem .75rem .1rem .75rem; } .summary-last { padding: .1rem .75rem .75rem .75rem; } .summary { padding: .1rem .75rem ; } </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() { var level = "tag" if (this.props.level === "HIGH") { level += " is-danger"; } else if (this.props.level === "MEDIUM") { level += " is-warning"; } else if (this.props.level === "LOW") { level += " is-info"; } else if (this.props.level === "WAIVED") { level += " is-success"; } level +=" is-rounded"; return ( <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> </div> ); } }); 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> ); } }); var Issue = React.createClass({ render: function() { return ( <div className="issue box"> <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> </div> <div className="column is-one-quarter"> <div className="field is-grouped is-grouped-multiline"> {this.props.data.nosec && <IssueTag label="NoSec" level="WAIVED"/>} <IssueTag label="Severity" level={ this.props.data.severity }/> <IssueTag label="Confidence" level={ this.props.data.confidence }/> </div> </div> </div> <div className="highlight"> <Highlight key={ this.props.data.file + this.props.data.line } code={ this.props.data.code }/> </div> </div> ); } }); var Stats = React.createClass({ render: function() { return ( <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.' : ''} </p> ); } }); var Issues = React.createClass({ render: function() { if (this.props.data.Stats.files === 0) { return ( <div className="notification"> No source files found. Do you even Go? </div> ); } if (this.props.data.Issues.length === 0) { return ( <div> <div className="notification"> Awesome! No issues found! </div> <Stats data={ this.props.data } /> </div> ); } var issues = this.props.data.Issues .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). </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); return ( <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> ); } }); 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 return ( <option value={ it } selected={ matches }> { it } </option> ); }.bind(this)); return ( <div> <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> </nav> <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> ); } }); 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); this.setState({severity: val}); }, handleConfidence: function(val) { this.updateIssueTypes(this.props.data.Issues, this.state.severity, val); 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 .map(function(issue) { return issue.severity }) .sort() .filter(function(item, pos, ary) { return !pos || item != ary[pos - 1]; }); var allConfidences = data.Issues .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); 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 data={ this.props.data } 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> </html>