Skip to content

Commit

Permalink
Deploying to gh-pages from @ 1669abc 🚀
Browse files Browse the repository at this point in the history
  • Loading branch information
ericcornelissen committed Oct 14, 2024
0 parents commit 4e2be00
Show file tree
Hide file tree
Showing 10 changed files with 2,267 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
ignore-scripts=true
lockfile-version=3
save-exact=true
674 changes: 674 additions & 0 deletions COPYING.txt

Large diffs are not rendered by default.

121 changes: 121 additions & 0 deletions ades.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
// Copyright (C) 2024 Eric Cornelissen
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

//go:build wasm

package main

import (
"syscall/js"

"github.com/ericcornelissen/ades"
)

var window = js.Global().Get("window")

type options struct {
conservative bool
}

func parseOptions(opts js.Value) options {
return options{
conservative: opts.Get("conservative").Bool(),
}
}

func fail(description string, err error) {
window.Call("showError", description, err.Error())
}

func succeed(result []any) {
window.Call("showResult", js.ValueOf(result))
}

func encodeErrorAsMap(violation *ades.Violation) map[string]any {
obj := make(map[string]any, 4)
obj["job"] = violation.JobId
obj["step"] = violation.StepId
obj["problem"] = violation.Problem
obj["ruleId"] = violation.RuleId
return obj
}

func lintWorkflow(source string, opts *options) ([]ades.Violation, error) {
workflow, err := ades.ParseWorkflow([]byte(source))
if err != nil {
return nil, err
}

var matcher ades.ExprMatcher = ades.AllMatcher
if opts.conservative {
matcher = ades.ConservativeMatcher
}

return ades.AnalyzeWorkflow(&workflow, matcher), nil
}

func lintManifest(source string, opts *options) ([]ades.Violation, error) {
manifest, err := ades.ParseManifest([]byte(source))
if err != nil {
return nil, err
}

var matcher ades.ExprMatcher = ades.AllMatcher
if opts.conservative {
matcher = ades.ConservativeMatcher
}

return ades.AnalyzeManifest(&manifest, matcher), nil
}

func analyze(source string, opts *options) {
violations, err := lintWorkflow(source, opts)
if err != nil || len(violations) == 0 {
violations, err = lintManifest(source, opts)
}

if err != nil {
fail("Parsing failure", err)
return
}

result := make([]any, 0, len(violations))
for _, violation := range violations {
result = append(result, encodeErrorAsMap(&violation))
}

succeed(result)
return
}

func runAdes(_this js.Value, args []js.Value) any {
source := args[0].String()
opts := parseOptions(args[1])
analyze(source, &opts)

return nil
}

func main() {
window.Set("ades", js.FuncOf(runAdes))

initialSource := window.Call("getSource").String()
rawOpts := window.Call("getOptions")
opts := parseOptions(rawOpts)
analyze(initialSource, &opts)

// Keep the program alive
select {}
}
Binary file added ades.wasm
Binary file not shown.
74 changes: 74 additions & 0 deletions index.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/**
* Copyright (C) 2024 Eric Cornelissen
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

html {
min-height: 100%;
}

body {
box-sizing: border-box;
font-size: 14px;
font-family: sans-serif;
height: 100vh;
margin: 0;
max-width: 980px;
padding: 2rem 2rem 0 ;
position: relative;
}
p {
margin: .25rem 0;
padding: 0;
}

textarea.code {
font-family: monospace;
}

.working {
font-style: italic;
}

.result ul {
list-style: none;
margin: .5rem 0;
padding: 0;
}

.error .title {
display: inline-block;
font-weight: bold;
}
.error .what {
display: inline-block;
font-style: italic;
}
.error .details {
display: block;
font-size: bold;
margin-top: .25rem;
}

footer {
margin-top: 2rem;
padding-bottom: 2rem;
position: sticky;
top: 100%;
width: 100%;
}
footer hr {
margin-bottom: .8rem;
}
109 changes: 109 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
<!--
Copyright (C) 2024 Eric Cornelissen
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
-->

<!DOCTYPE html>
<html lang="en">

<head>
<title>ades</title>
<meta charset="utf-8" />

<meta
http-equiv="Content-Security-Policy"
content="base-uri 'none'; connect-src 'self'; default-src 'none'; object-src 'none'; script-src 'self' 'wasm-unsafe-eval'; style-src 'self'; trusted-types 'none'; require-trusted-types-for 'script';"
/>

<link rel="stylesheet" href="index.css">
<script src="wasm_exec.js"></script>
</head>

<body>
<noscript>
This website requires JavaScript and WebAssembly to run. The website's source code is
available on
<a
href="https://github.com/ericcornelissen/ades"
rel="noopener"
>GitHub</a>
, where the tool is also available as a standalone application.
</noscript>

<main>
<h1>Actions Dangerous Expressions Scanner</h1>
<div>
<p>
Paste your GitHub Actions workflow or manifest below and get a report of dangerous uses of
<a
href="https://docs.github.com/en/actions/learn-github-actions/expressions"
rel="noopener"
>expressions</a>
in it.</p>
<div>
<label>
<input
id="option-conservative"
type="checkbox"
> Only expressions known to be controllable by attackers.
</label>
</div>
<textarea
class="code"
id="workflow-input"
rows="24" cols="100"
>
name: Example
on: [push]

jobs:
example:
name: example
runs-on: ubuntu-latest
steps:
- name: Safe run
run: echo 'Hello world!'
- name: Unsafe run
run: echo 'Hello ${{ inputs.name }}'
</textarea>
</div>
<div>
<h2>Report</h2>
<div id="results">
<i>Working...</i>
</div>
</div>
</main>

<footer>
<hr/>
<p>
Code available on
<a
href="https://github.com/ericcornelissen/ades"
rel="noopener"
>GitHub</a>
by
<a
href="https://ericcornelissen.dev/"
rel="noopener"
>@ericcornelissen</a>.
</p>
</footer>

<script src="index.js"></script>
</body>

</html>
Loading

0 comments on commit 4e2be00

Please sign in to comment.