preflight helps you verify scripts and executables to mitigate chain of supply attacks such as the recent Codecov hack.






💣 Mitigate chain of supply attacks
👌 Verify your curl scripts and executables


🤔 What is it?

preflight helps you verify scripts and executables to mitigate chain of supply attacks such as the recent Codecov hack.

🎁 Getting Preflight

First of all, it's the chicken and the egg. How do you pull a legit preflight binary from us without verifying it with preflight? having that preflight is solving this exact problem?

The best way, is that you grab the source, compile it yourself, and use your own binary which you put in a place that you trust. People usually have several options of how to do that safely:

  • Put it on your own S3 bucket
  • Drop it on your own Artifactory or similar
  • Push it directly into your repos (it should be as small as 4mb, and almost never change so, Git should work nicely with it)

If you want to just get started quickly on your workstation, you can download a release or install preflight with homebrew:

$ brew tap spectralops/tap && brew install preflight

🚀 Quick Run

Someone changed the script or binary you're running. Abort!

$ curl -L https://XXX | preflight run sha256=1ce...2244a6e86
⌛️ Preflight starting
❌ Preflight failed:
   Digest does not match.
     Expected: <...>
     Actual: <...>
  
   Information:
   It is recommended to inspect the modified file contents.

A hash is verified, but it is actually vulnerable. Abort!

$ curl -L https://XXX | preflight run sha256=1ce...2244a6e86
⌛️ Preflight starting using file lookup: malshare.current.sha256.txt
❌ Preflight failed: Digest matches but marked as vulnerable.
   Digest matches but marked as vulnerable.

Information:
  Vulnerability: Hash was found in a vulnerable digest list
  More: malshare.current.sha256.txt

All ok, let's fly.

$ curl -L https://XXX | preflight run sha256=1ce...2244a6e86
⌛️ Preflight starting
✅ Preflight verified

... actual script output ...

Examples

Running codecov safely in your CI

First, let's create a hash (before creating it, review the script manually and see that it's not doing anything funny):

$ curl -s https://codecov.io/bash | ./preflight create
sha256=d6aa3207c4908d123bd8af62ec0538e3f2b9f257c3de62fad4e29cd3b59b41d9

Now, we're going to take

sha256=d6aa3207c4908d123bd8af62ec0538e3f2b9f257c3de62fad4e29cd3b59b41d9

And use this to secure our pulls from Codecov. In this case, preflight is checked safely into your repo under ci/preflight.


BEFORE (insecure):

steps:
   - curl -s https://codecov.io/bash | sh

AFTER (safe, yay!):

steps:
   - curl -s https://codecov.io/bash | ./ci/preflight run sha256=d6aa3207c4908d123bd8af62ec0538e3f2b9f257c3de62fad4e29cd3b59b41d9

🏃 Running scripts and binaries

Piping:

$ curl -s https://example.com/some-script | preflight run sha256=d6aa3207c4<...>b4

Executables:

$ preflight run sha256=d6aa3207c4<...>b4 ./my-script.sh

🔎 Checking scripts and binaries

Piping:

$ curl -s https://example.com/some-script | preflight check sha256=d6aa3207c4<...>b4 | sh

Not that preflight check is built in a way that you could continue to pipe to the next process:

  • If a check passes, the checked script or binary content will be dumped to STDOUT
  • If a check fails, you'll get an exit(1), and an error message

Executables:

$ preflight check sha256=d6aa3207c4<...>b4 ./my-script.sh

In this case:

  • If a check passes, you'll get an exit(0) and no output (so you can compose with other tooling)
  • If a check fails, you'll get an exit(1) and an error message

📍 Creating new hashes

You can easily create new hashes with preflight. The default is a SHA256 hash, but you could also create a sha256, sha1, and md5 hash.

$ preflight create test.sh
sha256=fe6d02cf15642ff8d5f61cad6d636a62fd46a5e5a49c06733fece838f5fa9d85

Though not recommended, you can create other kinds (weaker kinds) of hashes for legacy/compatibility reasons:

$ preflight create test.sh --digest md5
md5=cb62874fea06458b2b0cabf2322c9d55

🙈 Using optional malware lookup

preflight comes with lookup providers, which is optional -- you can enable them by using environment variables:

File Lookup

You can download a daily list of malware signatures from malshare.com or any equivalent service. Here is a direct link to such a list.

Then:

  • Set PF_FILE_LOOKUP=./path/to/text/file

With this configured preflight will search for all digest types in this file before approving.

Here is a full example for your CI, combining preflight with Malshare:

env:
   PF_FILE_LOOKUP: malshare.current.sha256.txt

steps: 
- wget https://www.malshare.com/daily/malshare.current.sha256.txt
- curl https://... | preflight <sha>

Result:

$ PF_FILE_LOOKUP=malshare.current.sha256.txt preflight run fe6d02cf15642ff8d5f61cad6d636a62fd46a5e5a49c06733fece838f5fa9d85 test.sh
⌛️ Preflight starting using file lookup: malshare.current.sha256.txt
❌ Preflight failed: Digest matches but marked as vulnerable.

Information:
  Vulnerability: Hash was found in a vulnerable digest list
  More: malshare.current.sha256.txt

Other lookup types?

We've established that a file lookup is universal and general enough to be useful to everyone. However, you might prefer your own vendor, or a service such as VirusTotal -- preflight's architecture is pluggable and we're accepting pull requests.

Thanks

To all Contributors - you make this happen, thanks!

Copyright

Copyright (c) 2021 @jondot. See LICENSE for further details.

Similar Resources

Use this program to embed sh scripts in binaries

sh2bin Use this program to embed sh scripts in binaries. Feel free to fork this

Jan 4, 2023

The Oracle Database Operator for Kubernetes (a.k.a. OraOperator) helps developers, DBAs, DevOps and GitOps teams reduce the time and complexity of deploying and managing Oracle Databases

The Oracle Database Operator for Kubernetes (a.k.a. OraOperator) helps developers, DBAs, DevOps and GitOps teams reduce the time and complexity of deploying and managing Oracle Databases. It eliminates the dependency on a human operator or administrator for the majority of database operations.

Dec 14, 2022

LinkPage is a FOSS self-hosted alternative to link listing websites such as LinkTree and Campsite.bio

LinkPage is a FOSS self-hosted alternative to link listing websites such as LinkTree and Campsite.bio

LinkPage LinkPage is a FOSS self-hosted alternative to link listing websites such as LinkTree and Campsite.bio Features Self hostable and open source

Dec 22, 2022

Audit your egress connections and finally populate this OUTPUT chain !

egress-auditor Audit your egress connections and finally populate this OUTPUT chain ! Summary egress-auditor will monitor new outbound connections and

Aug 9, 2022

The Coherence command line interface (CLI) is a lightweight tool, in the tradition of tools such as kubectl

The Coherence command line interface (CLI) is a lightweight tool, in the tradition of tools such as kubectl

Coherence Command Line Interface (CLI) Contents Overview Why use the Coherence C

Dec 15, 2022

A simple go application that uses Youtube Data API V3 to show the real-time stats for a youtube channel such as the subs, views, avg. earnings etc.

A simple go application that uses Youtube Data API V3 to show the real-time stats for a youtube channel such as the subs, views, avg. earnings etc.

Youtube-channel-monitor A simple go application that uses Youtube Data API V3 to show the real-time stats for a youtube channel such as the subs, view

Dec 30, 2021

Generic inquiry tool to OPA server for CI process, such as GitHub Actions

opaq opaq is a generic inquiry tool to OPA server. A major purpose of this tool is for inquiry in GitHub Actions. Features Data formatting: OPA server

Jan 20, 2022

Valse is an kubernetes exporter application that discovers resources such as version

Valse is an kubernetes exporter application that discovers resources such as version

What is the Valse? Valse is an kubernetes exporter application that discovers resources such as version, namespaces, node, pod, deployment, daemonset,

Jul 22, 2022

webhook forward, such as: synology

webhook forward, such as: synology

Webhook-Forward Usage docker pull starudream/webhook-forward docker run -d starudream/webhook-forward Env ADDR=127.0.0.1:9988 DEBUG=true PROXY=http:/

Jun 10, 2022
Comments
  • CVE-2022-29526

    CVE-2022-29526

    I am building a minimal base image FROM cgr.dev/chainguard/static:latest

    I download the latest preflight binary and copy it into the container. When I scanned my build container I see one CVE reported by Trivy

    I don't know too much about golang, but maybe the dependencies just need an update to pull in the fixed package?

    Scanned with aquasec/trivy:0.34.0

    cgpf:latest (alpine 3.16)
    
    Total: 0 (UNKNOWN: 0, LOW: 0, MEDIUM: 0, HIGH: 0, CRITICAL: 0)
    
    
    usr/bin/preflight (gobinary)
    
    Total: 1 (UNKNOWN: 0, LOW: 0, MEDIUM: 1, HIGH: 0, CRITICAL: 0)
    
    ┌──────────────────┬────────────────┬──────────┬────────────────────────────────────┬───────────────────────────────────┬───────────────────────────────────────────────┐
    │     Library      │ Vulnerability  │ Severity │         Installed Version          │           Fixed Version           │                     Title                     │
    ├──────────────────┼────────────────┼──────────┼────────────────────────────────────┼───────────────────────────────────┼───────────────────────────────────────────────┤
    │ golang.org/x/sys │ CVE-2022-29526 │ MEDIUM   │ v0.0.0-20210228012217-479acdf4ea46 │ 0.0.0-20220412211240-33da011f77ad │ golang: syscall: faccessat checks wrong group │
    │                  │                │          │                                    │                                   │ https://avd.aquasec.com/nvd/cve-2022-29526    │
    └──────────────────┴────────────────┴──────────┴────────────────────────────────────┴───────────────────────────────────┴───────────────────────────────────────────────┘
    

    Here is the Dockerfile I am creating

    FROM cgr.dev/chainguard/alpine-base:latest AS preflight_builder
    ARG PREFLIGHT_VERSION=1.1.4
    ADD https://github.com/SpectralOps/preflight/releases/download/v${PREFLIGHT_VERSION}/preflight_${PREFLIGHT_VERSION}_Linux_x86_64.tar.gz /tools/
    ADD https://github.com/SpectralOps/preflight/releases/download/v${PREFLIGHT_VERSION}/checksums.txt /tools/
    WORKDIR /tools
    RUN cat checksums.txt | grep preflight_${PREFLIGHT_VERSION}_Linux_x86_64.tar.gz | sha256sum -c -
    RUN tar -xzf preflight_${PREFLIGHT_VERSION}_Linux_x86_64.tar.gz preflight -C /usr/bin
    RUN preflight version
    
    FROM cgr.dev/chainguard/static:latest
    COPY --from=preflight_builder /usr/bin/preflight /usr/bin/
    ENTRYPOINT [ "/usr/bin/preflight" ]
    
  • Report errors to client on `run` command

    Report errors to client on `run` command

    In preflight commands there are 2 types of errors output:

    1. Check failure errors (digest mismatch / vulnerable digest).
    2. Processing errors / exceptions (bad hash source URL, bad hash set structure etc.).

    Currently, the run command is not presenting error messages resulting from processing errors. If such an error has occurred the only display is ⌛️ Preflight starting and the program exits. The rest of the commands do present error messages. The check failure errors are displaying well.

    run command Output example after processing error: image

    The same output for the same input to check command: image

    I think that the reason that errors are not presented is because during run command if the check has failed, both a.Porcelain.CheckFailed(check) and check.Error() are being called:

    1. a.Porcelain.CheckFailed(check) - prints a friendly message with the failure reason and details.
    2. check.Error() - creates an exception with an error message which being returned to main.go from Exec & ExecPiped methods.

    main.go not prints the any error message (both check failure & processing errors) returned from Exec & ExecPiped methods probably in order to prevent a duplicate reporting of a check failure message, and therefore processing error message are not being reported as well.

    My suggestion is:

    1. Remove check.Error() completely since the errors returned from this function have no effect and already friendly reported by a.Porcelain.CheckFailed(check).
    2. In main.go - if an error returned - print the error message (errors can be bad hash source URL, bad hash set structure etc.).
    3. In case the check has failed (digest mismatch / vulnerable digest) in run command - return nil to not print the check failure message because a.Porcelain.CheckFailed(check) already reported a friendly message of the check failure.

    This way we are creating a separation between reporting of check failures by CheckFailed method, and reporting of processing errors by main.go as all other commands does.

    run command output with an error after this change: image

    Let me know your thoughts 😄

  • Add Go 1.16 to action workflow

    Add Go 1.16 to action workflow

    Sneaking into the contributor's list with a simple CI change since the README instructions use golang:1.16-alpine as the Dockerfile builder. although go.mod specifies 1.15.

Hexagonal architecture paradigms, such as dividing adapters into primary (driver) and secondary (driven)Hexagonal architecture paradigms, such as dividing adapters into primary (driver) and secondary (driven)

authorizer Architecture In this project, I tried to apply hexagonal architecture paradigms, such as dividing adapters into primary (driver) and second

Dec 7, 2021
crud is a cobra based CLI utility which helps in scaffolding a simple go based micro-service along with build scripts, api documentation, micro-service documentation and k8s deployment manifests

crud crud is a CLI utility which helps in scaffolding a simple go based micro-service along with build scripts, api documentation, micro-service docum

Nov 29, 2021
Christmas Hack Day Project: Build an Kubernetes Operator to deploy Camunda Cloud services

Camunda Cloud Operator Christmas Hack Day Project (2021): Build an Kubernetes Operator to deploy Camunda Cloud services Motiviation / Idea We currentl

May 18, 2022
Sign Container Images with cosign and Verify signature by using Open Policy Agent (OPA)
 Sign Container Images with cosign and Verify signature by using Open Policy Agent (OPA)

Sign Container Images with cosign and Verify signature by using Open Policy Agent (OPA) In the beginning, I believe it is worth saying that this proje

Nov 30, 2022
This plugin helps you to use the AWS Command Line Interface (AWS CLI) to start and end sessions to your managed instances

Session Manager Plugin This plugin helps you to use the AWS Command Line Interface (AWS CLI) to start and end sessions to your managed instances. Sess

Dec 28, 2022
Controller-check - Run checks against K8s controllers to verify if they meets certain conventions

controller-check Run checks against K8s controllers to verify if they meets cert

Jan 4, 2022
Linux provisioning scripts + application deployment tools. Suitable for self-hosting and hobby-scale application deployments.

Apollo Linux provisioning scripts + application deployment tools. Suitable for self-hosting and hobby-scale application deployments. Philosophy Linux-

Feb 7, 2022
Making it easy to write shell-like scripts in Go
Making it easy to write shell-like scripts in Go

import github.com/bitfield/script What is script? script is a Go library for doing the kind of tasks that shell scripts are good at: reading files, ex

Jan 9, 2023
Terraform utility provider for constructing bash scripts that use data from a Terraform module

Terraform Bash Provider This is a Terraform utility provider which aims to robustly generate Bash scripts which refer to data that originated in Terra

Sep 6, 2022
toghsh translates github actions workflows to shell scripts

togsh - extracts shell commands from github actions workflows toghsh is a helper tool to translate github action workflows into equivalent shell scrip

Nov 16, 2021