Contextual Content Discovery Tool

Kiterunner

GoDoc GitHub release Go Report Card

Introduction

For the longest of times, content discovery has been focused on finding files and folders. While this approach is effective for legacy web servers that host static files or respond with 3xx’s upon a partial path, it is no longer effective for modern web applications, specifically APIs.

Over time, we have seen a lot of time invested in making content discovery tools faster so that larger wordlists can be used, however the art of content discovery has not been innovated upon.

Kiterunner is a tool that is capable of not only performing traditional content discovery at lightning fast speeds, but also bruteforcing routes/endpoints in modern applications.

Modern application frameworks such as Flask, Rails, Express, Django and others follow the paradigm of explicitly defining routes which expect certain HTTP methods, headers, parameters and values.

When using traditional content discovery tooling, such routes are often missed and cannot easily be discovered.

By collating a dataset of Swagger specifications and condensing it into our own schema, Kiterunner can use this dataset to bruteforce API endpoints by sending the correct HTTP method, headers, path, parameters and values for each request it sends.

Swagger files were collected from a number of datasources, including an internet wide scan for the 40+ most common swagger paths. Other datasources included GitHub via BigQuery, and APIs.guru.

Contents

Installation

Downloading a release

You can download a pre-built copy from https://github.com/assetnote/kiterunner/releases.

Building from source

# build the binary
make build

# symlink your binary
ln -s $(pwd)/dist/kr /usr/local/bin/kr

# compile the wordlist
# kr kb compile <input.json> <output.kite>
kr kb compile routes.json routes.kite

# scan away
kr scan hosts.txt -w routes.kite -x 20 -j 100 --ignore-length=1053

The JSON datasets can be found below:

Alternatively, it is possible to download the compile .kite files from the links below:

Usage

Quick Start

kr [scan|brute] <input> [flags]
  • <input> can be a file, a domain, or URI. we'll figure it out for you. See Input/Host Formatting for more details
# Just have a list of hosts and no wordlist
kr scan hosts.txt -A=apiroutes-210328:20000 -x 5 -j 100 --fail-status-codes 400,401,404,403,501,502,426,411

# You have your own wordlist but you want assetnote wordlists too
kr scan target.com -w routes.kite -A=apiroutes-210328:20000 -x 20 -j 1 --fail-status-codes 400,401,404,403,501,502,426,411

# Bruteforce like normal but with the first 20000 words
kr brute https://target.com/subapp/ -A=aspx-210328:20000 -x 20 -j 1

# Use a dirsearch style wordlist with %EXT%
kr brute https://target.com/subapp/ -w dirsearch.txt -x 20 -j 1 -exml,asp,aspx,ashx -D

CLI Help

Usage:
  kite scan [flags]

Flags:
  -A, --assetnote-wordlist strings    use the wordlists from wordlist.assetnote.io. specify the type/name to use, e.g. apiroutes-210228. You can specify an additional maxlength to use only the first N values in the wordlist, e.g. apiroutes-210228;20000 will only use the first 20000 lines in that wordlist
      --blacklist-domain strings      domains that are blacklisted for redirects. We will not follow redirects to these domains
      --delay duration                delay to place inbetween requests to a single host
      --disable-precheck              whether to skip host discovery
      --fail-status-codes ints        which status codes blacklist as fail. if this is set, this will override success-status-codes
      --filter-api strings            only scan apis matching this ksuid
      --force-method string           whether to ignore the methods specified in the ogl file and force this method
  -H, --header strings                headers to add to requests (default [x-forwarded-for: 127.0.0.1])
  -h, --help                          help for scan
      --ignore-length strings         a range of content length bytes to ignore. you can have multiple. e.g. 100-105 or 1234 or 123,34-53. This is inclusive on both ends
      --kitebuilder-full-scan         perform a full scan without first performing a phase scan.
  -w, --kitebuilder-list strings      ogl wordlist to use for scanning
  -x, --max-connection-per-host int   max connections to a single host (default 3)
  -j, --max-parallel-hosts int        max number of concurrent hosts to scan at once (default 50)
      --max-redirects int             maximum number of redirects to follow (default 3)
  -d, --preflight-depth int           when performing preflight checks, what directory depth do we attempt to check. 0 means that only the docroot is checked (default 1)
      --profile-name string           name for profile output file
      --progress                      a progress bar while scanning. by default enabled only on Stderr (default true)
      --quarantine-threshold int      if the host return N consecutive hits, we quarantine the host as wildcard. Set to 0 to disable (default 10)
      --success-status-codes ints     which status codes whitelist as success. this is the default mode
  -t, --timeout duration              timeout to use on all requests (default 3s)
      --user-agent string             user agent to use for requests (default "Chrome. Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36")
      --wildcard-detection            can be set to false to disable wildcard redirect detection (default true)

Global Flags:
      --config string    config file (default is $HOME/.kiterunner.yaml)
  -o, --output string    output format. can be json,text,pretty (default "pretty")
  -q, --quiet            quiet mode. will mute unecessarry pretty text
  -v, --verbose string   level of logging verbosity. can be error,info,debug,trace (default "info")

bruteforce flags (all the flags above +)

  -D, --dirsearch-compat              this will replace %EXT% with the extensions provided. backwards compat with dirsearch because shubs loves him some dirsearch
  -e, --extensions strings            extensions to append while scanning
  -w, --wordlist strings              normal wordlist to use for scanning

Input/Host Formatting

When supplied with an input, kiterunner will attempt to resolve the input in the following order:

  1. Is the input a file. If so read all the lines in the file as separate domains
  2. The input is treated as a "domain"

If you supply a "domain", but it exists as a file, e.g. google.com but google.com is also a txt file in the current directory, we'll load google.com the text file, because we found it first.

Domain Parsing

Its preferred that you provide a full URI as the input, however you can provide incomplete URIs and we'll try and guess what you mean. An example list of domains you can supply are:

one.com
two.com:80
three.com:443
four.com:9447
https://five.com:9090
http://six.com:80/api

The above list of domains will expand into the subsequent list of targets

(two targets are created for one.com, since neither port nor protocol was specified)
http://one.com (port 80 implied)
https://one.com (port 443 implied)

http://two.com (port 80 implied)
https://three.com (port 443 implied)
http://four.com:9447 (non-tls port guessed)
https://five.com:9090
http://six.com/api (port 80 implied; basepath API appended)

the rules we apply are:

  • if you supply a scheme, we use the scheme.
    • We only support http & https
    • if you don't supply a scheme, we'll guess based on the port
  • if you supply a port, we'll use the port
    • If your port is 443, or 8443, we'll assume its tls
    • if you don't supply a port, we'll guess both port 80, 443
  • if you supply a path, we'll prepend that path to all requests against that host

API Scanning

When you have a single target

# single target
kr scan https://target.com:8443/ -w routes.kite -A=apiroutes-210228:20000 -x 10 --ignore-length=34

# single target, but you want to try http and https
kr scan target.com -w routes.kite -A=apiroutes-210228:20000 -x 10 --ignore-length=34

# a list of targets
kr scan targets.txt -w routes.kite -A=apiroutes-210228:20000 -x 10 --ignore-length=34

Vanilla Bruteforcing

kr brute https://target.com -A=raft-large-words -A=apiroutes-210228:20000 -x 10 -d=0 --ignore-length=34 -ejson,txt

Dirsearch Bruteforcing

For when you have an old-school wordlist that still has %EXT% in the wordlist, you can use -D. this will only substitute the extension where %EXT% is present in the path

kr brute https://target.com -w dirsearch.txt -x 10 -d=0 --ignore-length=34 -ejson,txt -D

Technical Features

Depth Scanning

A key feature of kiterunner is depth based scanning. This attempts to handle detecting wildcards given virtual application path based routing. The depth defines how many directories deep the baseline checks are performed E.g.

~/kiterunner $ cat wordlist.txt

/api/v1/user/create
/api/v1/user/delete
/api/v2/user/
/api/v2/admin/
/secrets/v1/
/secrets/v2/
  • At depth 0, only / would have the baseline checks performed for wildcard detection
  • At depth 1, /api and /secrets would have baseline checks performed; and these checks would be used against /api and /secrets correspondingly
  • At depth 2, /api/v1, /api/v2, /secrets/v1 and /secrets/v2 would all have baseline checks performed.

By default, kr scan has a depth of 1, since from internal usage, we've often seen this as the most common depth where virtual routing has occured. kr brute has a default depth of 0, as you typically don't want this check to be performed with a static wordlist.

Naturally, increasing the depth will increase the accuracy of your scans, however this also increases the number of requests to the target. (# of baseline checks * # of depth baseline directories). Hence, we recommend against going above 1, and in rare cases going to depth 2.

Using Assetnote Wordlists

We provide inbuilt downloading and caching of wordlists from assetnote.io. You can use these with the -A flag which receives a comma delimited list of aliases, or fullnames.

You can get a full list of all the Assetnote wordlists with kr wordlist list.

The wordlists when used, are cached in ~/.cache/kiterunner/wordlists. When used, these are compiled from .txt -> .kite

+-----------------------------------+-------------------------------------------------------+----------------+---------+----------+--------+
|               ALIAS               |                       FILENAME                        |     SOURCE     |  COUNT  | FILESIZE | CACHED |
+-----------------------------------+-------------------------------------------------------+----------------+---------+----------+--------+
| 2m-subdomains                     | 2m-subdomains.txt                                     | manual.json    | 2167059 | 28.0mb   | false  |
| asp_lowercase                     | asp_lowercase.txt                                     | manual.json    |   24074 | 1.1mb    | false  |
| aspx_lowercase                    | aspx_lowercase.txt                                    | manual.json    |   80293 | 4.4mb    | false  |
| bak                               | bak.txt                                               | manual.json    |   31725 | 634.8kb  | false  |
| best-dns-wordlist                 | best-dns-wordlist.txt                                 | manual.json    | 9996122 | 139.0mb  | false  |
| cfm                               | cfm.txt                                               | manual.json    |   12100 | 260.3kb  | true   |
| do                                | do.txt                                                | manual.json    |  173152 | 4.8mb    | false  |
| dot_filenames                     | dot_filenames.txt                                     | manual.json    | 3191712 | 71.3mb   | false  |
| html                              | html.txt                                              | manual.json    | 4227526 | 107.7mb  | false  |
| apiroutes-201120                  | httparchive_apiroutes_2020_11_20.txt                  | automated.json |  953011 | 45.3mb   | false  |
| apiroutes-210128                  | httparchive_apiroutes_2021_01_28.txt                  | automated.json |  225456 | 6.6mb    | false  |
| apiroutes-210228                  | httparchive_apiroutes_2021_02_28.txt                  | automated.json |  223544 | 6.5mb    | true   |
| apiroutes-210328                  | httparchive_apiroutes_2021_03_28.txt                  | automated.json |  215114 | 6.3mb    | false  |
| aspx-201118                       | httparchive_aspx_asp_cfm_svc_ashx_asmx_2020_11_18.txt | automated.json |   63200 | 1.7mb    | false  |
| aspx-210128                       | httparchive_aspx_asp_cfm_svc_ashx_asmx_2021_01_28.txt | automated.json |   46286 | 928.7kb  | false  |
| aspx-210228                       | httparchive_aspx_asp_cfm_svc_ashx_asmx_2021_02_28.txt | automated.json |   43958 | 883.3kb  | false  |
| aspx-210328                       | httparchive_aspx_asp_cfm_svc_ashx_asmx_2021_03_28.txt | automated.json |   45928 | 926.8kb  | false  |
| cgi-201118                        | httparchive_cgi_pl_2020_11_18.txt                     | automated.json |    2637 | 44.0kb   | false  |

<SNIP>

Usage

kr scan targets.txt -A=apiroutes-210228 -x 10 --ignore-length=34
kr brute targets.txt -A=aspx-210228 -x 10 --ignore-length=34 -easp,aspx

Head Syntax

When using assetnote provided wordlists, you may not want to use the entire wordlist, so you can opt to use the first N lines in a given wordlist using the head syntax. The format is <wordlist_name>:<N lines> when specifying a wordlist.

Usage

# this will use the first 20000 lines in the api routes wordlist
kr scan targets.txt -A=apiroutes-210228:20000 -x 10 --ignore-length=34

# this will use the first 10 lines in the aspx wordlist
kr brute targets.txt -A=aspx-210228:10 -x 10 --ignore-length=34 -easp,aspx

Concurrency Settings/Going Fast

Kiterunner is made to go fast on a lot of hosts. But, just because you can run kiterunner at 20000 goroutines, doesn't mean its a good idea. Bottlenecks and performance degredation will occur at high thread counts due to more time spent scheduling goroutines that are waiting on network IO and kernel context switching.

There are two main concurrency settings for kiterunner:

  • -x, --max-connection-per-host - maximum number of open connections we can have on a host. Governed by 1 goroutine each. To avoid DOS'ing a host, we recommend keeping this in a low realm of 5-10. Depending on latency to the target, this will yield on average between 1-5 requests per second per connection (200ms - 1000ms/req) to a host.
  • -j, --max-parallel-hosts - maximum number of hosts to scan at any given time. Governed by 1 goroutine supervisor for each

Depending on the hardware you are scanning from, the "maximum" number of goroutines you can run optimally will vary. On an AWS t3.medium, we saw performance degradation going over 2500 goroutines. Meaning, 500 hosts x 5 conn per host (2500) would yield peak performance.

We recommend against running kiterunner from your macbook. Due to poor kernel optimisations for high IO counts and Epoll syscalls on macOS, we noticed substantially poorer (0.3-0.5x) performance when compared to running kiterunner on a similarly configured linux instance.

To maximise performance when scanning an individual target, or a large attack surface we recommend the following tips:

  • Spin up an EC2 instance in a similar geographic region/datacenter to the target(s) you are scanning
  • Perform some initial benchmarks aganist your target set with varying -x and -j options. We recommend having a typical starting point of around -x 5 -j 100 and moving -j upwards as your CPU usage/network performance permits

Converting between file formats

Kiterunner will also let you convert between the schema JSON, a kite file and a standard txt wordlist.

Usage

The format is decided by the filetype extension supplied by the <input> and <output> fields. We support txt, json and kite

kr kb convert wordlist.txt wordlist.kite
kr kb convert wordlist.kite wordlist.json
kr kb convert wordlist.kite wordlist.txt
❯ go run ./cmd/kiterunner kb convert -qh
convert an input file format into the specified output file format

this will determine the conversion based on the extensions of the input and the output
we support the following filetypes: txt, json, kite
You can convert any of the following into the corresponding types

-d Debug mode will attempt to convert the schema with error handling
-v=debug Debug verbosity will print out the errors for the schema

Usage:
kite kb convert <input> <output> [flags]

Flags:
-d, --debug   debug the parsing
-h, --help    help for convert

Global Flags:
--config string    config file (default is $HOME/.kiterunner.yaml)
-o, --output string    output format. can be json,text,pretty (default "pretty")
-q, --quiet            quiet mode. will mute unecessarry pretty text
-v, --verbose string   level of logging verbosity. can be error,info,debug,trace (default "info")``bigquery

Replaying requests

When you receieve a bunch of output from kiterunner, it may be difficult to immediately understand why a request is causing a specific response code/length. Kiterunner offers a method of rebuilding the request from the wordlists used including all the header and body parameters.

  • You can replay a request by copy pasting the full response output into the kb replay command.
  • You can specify a --proxy to forward your requests through, so you can modify/repeat/intercept the request using 3rd party tools if you wish
  • The golang net/http client will perform a few additional changes to your request due to how the default golang spec implementation (unfortunately).
❯ go run ./cmd/kiterunner kb replay -q --proxy=http://localhost:8080 -w routes.kite "POST    403 [    287,   10,   1] https://target.com/dedalo/lib/dedalo/publication/server_api/v1/json/thesaurus_parents 0cc39f76702ea287ec3e93f4b4710db9c8a86251"
11:25AM INF Raw reconstructed request
POST /dedalo/lib/dedalo/publication/server_api/v1/json/thesaurus_parents?ar_fields=48637466&code=66132381&db_name=08791392&lang=lg-eng&recursive=false&term_id=72336471 HTTP/1.1
Content-Type: any


11:25AM INF Outbound request
POST /dedalo/lib/dedalo/publication/server_api/v1/json/thesaurus_parents?ar_fields=48637466&code=66132381&db_name=08791392&lang=lg-eng&recursive=false&term_id=72336471 HTTP/1.1
Host: target.com
User-Agent: Go-http-client/1.1
Content-Length: 0
Content-Type: any
Accept-Encoding: gzip


11:25AM INF Response After Redirects
HTTP/1.1 403 Forbidden
Connection: close
Content-Length: 45
Content-Type: application/json
Date: Wed, 07 Apr 2021 01:25:28 GMT
X-Amzn-Requestid: 7e6b2ea1-c662-4671-9eaa-e8cd31b463f2

User is not authorized to perform this action

Technical Implementation

Intermediate Data Type (PRoutes)

We use an intermediate representation of wordlists and kitebuilder json schemas in kiterunner. This is to allow us to dynamically generate the fields in the wordlist and reconstruct request bodies/headers and query parameters from a given spec.

The PRoute type is composed of Headers, Body, Query and Cookie parameters that are encoded in pkg/proute.Crumb. The Crumb type is an interface that is implemented on types such as UUIDs, Floats, Ints, Random Strings, etc.

When performing conversions to and from txt, json and kite files, all the conversions are first done to the proute.API intermediate type. Then the corresponding encoding is written out

Kite File Format

We use a super secret kite file format for storing the json schemas from kitebuilder. These are simply protobuf encoded pkg/proute.APIS written to a file. The compilation is used to allow us to quickly deserialize the already parsed wordlist. This file format is not stable, and should only be interacted with using the inbuilt conversion tools for kiterunner.

When a new version of the kite file format is released, you may need to recompile your kite files

Comments
  • No results found on debug application

    No results found on debug application

    Hello First of all congrats for amazing tool.

    Problem: Currently i can't see the request output. only the following information is printed during and after scan:

    INF no results found/s) [3s:1h20m50s]
    Continue Scanning with full wordlist? [y/n]: y
    INF scan complete duration=13311.47994 results=0 
    

    Expected: GET STATUS-CODE [] URL ID Command: kr scan http://localhost:8080/ -w wordlist/routes-small.kite

    Can be related with configs? Thanks

  • Brute vs Scan Usage & Wordlist Usage

    Brute vs Scan Usage & Wordlist Usage

    Hi,

    First, thanks a lot for the blog post as well as the tool 👍

    I made this issue to ask a question and I apologise in advance if I have missed a documentation link answering to my question.

    I try to understand the following 2 aspects of the tool.

    Aspect 1: BRUTE vs SCAN mode behaviour. Even after reading the description in the code and perform some tests I did not achieve to understand the core difference.

    Aspect2: Parameter -A vs Parameter -w , how do they work together?

    I have made my tests against the following application REST version of Spring PetClinic Sample Application and KR never find something for any of the following command line:

    $ export TARGET=http://192.168.178.32:9966/petclinic/api
    $ kr version                   
    1.0.2 - e7a7fa6
    Built on 2021-04-11T09:51:54Z
    $ kr scan $TARGET -w routes-small.kite -q -d 5 -A=apiroutes-210328 --fail-status-codes 404
    $ kr scan $TARGET -w routes-small.kite -q -d 5 --fail-status-codes 404
    $ kr scan $TARGET -q -d 5 -A=apiroutes-210328 --fail-status-codes 404
    $ kr brute $TARGET -A=raft-large-words -A=apiroutes-210228 -x 10 -d 3
    

    I'm 100% sure that the problem is a bad use of the tool by me and it's the reason why I made this question.

    Thanks a lot in advance for your help and thanks again a lot for this tool/knowledge sharing 😃

  • Kiterunner stacktrace when running a large list of hosts with a large wordlist

    Kiterunner stacktrace when running a large list of hosts with a large wordlist

    When using the brute mode with the following command:

    732 hosts with 233617 line count wordlist.

    ulimit -n 20000
    ./kr brute epic2 -x 20 -j 50 -w ../ffuf-brute/final_wordlist.txt -D -e html --fail-status-codes 404
    

    After some time, Kiterunner exits and produces the following stacktrace:

    goroutine 1159 [chan send]:
    github.com/assetnote/kiterunner/pkg/kiterunner.handleTarget.func3(0xc005130430, 0xb, 0xc0002b2300, 0xc000079930, 0xc0003205a0, 0xc005132780, 0xc0002f6090)
            /home/runner/work/kiterunner/kiterunner/pkg/kiterunner/kiterunner.go:143 +0x4d4
    created by github.com/assetnote/kiterunner/pkg/kiterunner.handleTarget
            /home/runner/work/kiterunner/kiterunner/pkg/kiterunner/kiterunner.go:100 +0x285
    
    goroutine 1160 [sleep]:
    time.Sleep(0x2540be400)
            /opt/hostedtoolcache/go/1.15.11/x64/src/runtime/time.go:188 +0xbf
    github.com/valyala/fasthttp.(*HostClient).connsCleaner(0xc00512d380)
            /home/runner/go/pkg/mod/github.com/valyala/[email protected]/client.go:1659 +0x2ff
    created by github.com/valyala/fasthttp.(*HostClient).acquireConn
            /home/runner/go/pkg/mod/github.com/valyala/[email protected]/client.go:1549 +0x1da
    
    goroutine 2326 [sleep]:
    time.Sleep(0x2540be400)
            /opt/hostedtoolcache/go/1.15.11/x64/src/runtime/time.go:188 +0xbf
    github.com/valyala/fasthttp.(*HostClient).connsCleaner(0xc0070fcc00)
            /home/runner/go/pkg/mod/github.com/valyala/[email protected]/client.go:1659 +0x2ff
    created by github.com/valyala/fasthttp.(*HostClient).acquireConn
            /home/runner/go/pkg/mod/github.com/valyala/[email protected]/client.go:1549 +0x1da
    
    goroutine 18291443 [select]:
    net.(*netFD).connect.func2(0xdf3960, 0xc0e2ac16e0, 0xc0e2465200, 0xc0e2aa09c0, 0xc0e2aa0960)
            /opt/hostedtoolcache/go/1.15.11/x64/src/net/fd_unix.go:118 +0xc5
    created by net.(*netFD).connect
            /opt/hostedtoolcache/go/1.15.11/x64/src/net/fd_unix.go:117 +0x234
    
    goroutine 18291312 [runnable]:
    internal/poll.runtime_pollWait(0x7f27274e6080, 0x72, 0xde4420)
            /opt/hostedtoolcache/go/1.15.11/x64/src/runtime/netpoll.go:222 +0x55
    internal/poll.(*pollDesc).wait(0xc0e18a1898, 0x72, 0xde4400, 0x11ec798, 0x0)
            /opt/hostedtoolcache/go/1.15.11/x64/src/internal/poll/fd_poll_runtime.go:87 +0x45
    internal/poll.(*pollDesc).waitRead(...)
            /opt/hostedtoolcache/go/1.15.11/x64/src/internal/poll/fd_poll_runtime.go:92
    internal/poll.(*FD).Read(0xc0e18a1880, 0xc0e296e000, 0x205, 0x205, 0x0, 0x0, 0x0)
            /opt/hostedtoolcache/go/1.15.11/x64/src/internal/poll/fd_unix.go:159 +0x1a5
    net.(*netFD).Read(0xc0e18a1880, 0xc0e296e000, 0x205, 0x205, 0x203038, 0x58, 0xc042243c00)
            /opt/hostedtoolcache/go/1.15.11/x64/src/net/fd_posix.go:55 +0x4f
    net.(*conn).Read(0xc10bb4e0d8, 0xc0e296e000, 0x205, 0x205, 0x0, 0x0, 0x0)
            /opt/hostedtoolcache/go/1.15.11/x64/src/net/net.go:182 +0x8e
    crypto/tls.(*atLeastReader).Read(0xc0e29615a0, 0xc0e296e000, 0x205, 0x205, 0xc0e296e000, 0x0, 0xc00db896a8)
            /opt/hostedtoolcache/go/1.15.11/x64/src/crypto/tls/conn.go:779 +0x62
    bytes.(*Buffer).ReadFrom(0xc0e295c600, 0xde2360, 0xc0e29615a0, 0x40b725, 0xc3ab20, 0xcc3ee0)
            /opt/hostedtoolcache/go/1.15.11/x64/src/bytes/buffer.go:204 +0xb1
    crypto/tls.(*Conn).readFromUntil(0xc0e295c380, 0xde3060, 0xc10bb4e0d8, 0x5, 0xc10bb4e0d8, 0x1000000caa9a0)
            /opt/hostedtoolcache/go/1.15.11/x64/src/crypto/tls/conn.go:801 +0xf3
    crypto/tls.(*Conn).readRecordOrCCS(0xc0e295c380, 0xc0e272cd00, 0x1d7, 0x1e0)
            /opt/hostedtoolcache/go/1.15.11/x64/src/crypto/tls/conn.go:608 +0x115
    crypto/tls.(*Conn).readRecord(...)
            /opt/hostedtoolcache/go/1.15.11/x64/src/crypto/tls/conn.go:576
    crypto/tls.(*Conn).readHandshake(0xc0e295c380, 0xc0e2773516, 0xc0e2773500, 0x1d2, 0x300)
            /opt/hostedtoolcache/go/1.15.11/x64/src/crypto/tls/conn.go:992 +0x6d
    crypto/tls.(*Conn).clientHandshake(0xc0e295c380, 0x0, 0x0)
            /opt/hostedtoolcache/go/1.15.11/x64/src/crypto/tls/handshake_client.go:170 +0x2a7
    crypto/tls.(*Conn).Handshake(0xc0e295c380, 0x0, 0x0)
            /opt/hostedtoolcache/go/1.15.11/x64/src/crypto/tls/conn.go:1362 +0xc9
    github.com/valyala/fasthttp.tlsClientHandshake.func1(0xc108909260, 0xc0e295c380)
            /home/runner/go/pkg/mod/github.com/valyala/[email protected]/client.go:1896 +0x2b
    created by github.com/valyala/fasthttp.tlsClientHandshake
            /home/runner/go/pkg/mod/github.com/valyala/[email protected]/client.go:1895 +0x15b
    
    goroutine 18291356 [runnable]:
    internal/poll.runtime_pollWait(0x7f27278d4fe8, 0x72, 0xde4420)
            /opt/hostedtoolcache/go/1.15.11/x64/src/runtime/netpoll.go:222 +0x55
    internal/poll.(*pollDesc).wait(0xc0e25ce618, 0x72, 0xde4400, 0x11ec798, 0x0)
            /opt/hostedtoolcache/go/1.15.11/x64/src/internal/poll/fd_poll_runtime.go:87 +0x45
    internal/poll.(*pollDesc).waitRead(...)
            /opt/hostedtoolcache/go/1.15.11/x64/src/internal/poll/fd_poll_runtime.go:92
    internal/poll.(*FD).Read(0xc0e25ce600, 0xc0e2e1b440, 0x205, 0x205, 0x0, 0x0, 0x0)
            /opt/hostedtoolcache/go/1.15.11/x64/src/internal/poll/fd_unix.go:159 +0x1a5
    net.(*netFD).Read(0xc0e25ce600, 0xc0e2e1b440, 0x205, 0x205, 0x203038, 0x58, 0xc000600000)
            /opt/hostedtoolcache/go/1.15.11/x64/src/net/fd_posix.go:55 +0x4f
    net.(*conn).Read(0xc000506388, 0xc0e2e1b440, 0x205, 0x205, 0x0, 0x0, 0x0)
            /opt/hostedtoolcache/go/1.15.11/x64/src/net/net.go:182 +0x8e
    crypto/tls.(*atLeastReader).Read(0xc0e2e113e0, 0xc0e2e1b440, 0x205, 0x205, 0xc0e2e1b440, 0x0, 0xc00dead6a8)
            /opt/hostedtoolcache/go/1.15.11/x64/src/crypto/tls/conn.go:779 +0x62
    bytes.(*Buffer).ReadFrom(0xc0e2e12d00, 0xde2360, 0xc0e2e113e0, 0x40b725, 0xc3ab20, 0xcc3ee0)
            /opt/hostedtoolcache/go/1.15.11/x64/src/bytes/buffer.go:204 +0xb1
    crypto/tls.(*Conn).readFromUntil(0xc0e2e12a80, 0xde3060, 0xc000506388, 0x5, 0xc000506388, 0x1000000caa9a0)
            /opt/hostedtoolcache/go/1.15.11/x64/src/crypto/tls/conn.go:801 +0xf3
    crypto/tls.(*Conn).readRecordOrCCS(0xc0e2e12a80, 0xc0e23e4900, 0x1d3, 0x1e0)
            /opt/hostedtoolcache/go/1.15.11/x64/src/crypto/tls/conn.go:608 +0x115
    crypto/tls.(*Conn).readRecord(...)
            /opt/hostedtoolcache/go/1.15.11/x64/src/crypto/tls/conn.go:576
    crypto/tls.(*Conn).readHandshake(0xc0e2e12a80, 0xc0e2e2e016, 0xc0e2e2e000, 0x1ce, 0x300)
            /opt/hostedtoolcache/go/1.15.11/x64/src/crypto/tls/conn.go:992 +0x6d
    crypto/tls.(*Conn).clientHandshake(0xc0e2e12a80, 0x0, 0x0)
            /opt/hostedtoolcache/go/1.15.11/x64/src/crypto/tls/handshake_client.go:170 +0x2a7
    crypto/tls.(*Conn).Handshake(0xc0e2e12a80, 0x0, 0x0)
            /opt/hostedtoolcache/go/1.15.11/x64/src/crypto/tls/conn.go:1362 +0xc9
    github.com/valyala/fasthttp.tlsClientHandshake.func1(0xc033548060, 0xc0e2e12a80)
            /home/runner/go/pkg/mod/github.com/valyala/[email protected]/client.go:1896 +0x2b
    created by github.com/valyala/fasthttp.tlsClientHandshake
            /home/runner/go/pkg/mod/github.com/valyala/[email protected]/client.go:1895 +0x15b
    
    goroutine 3228 [sleep]:
    time.Sleep(0x2540be400)
            /opt/hostedtoolcache/go/1.15.11/x64/src/runtime/time.go:188 +0xbf
    github.com/valyala/fasthttp.(*HostClient).connsCleaner(0xc00f4e8a80)
            /home/runner/go/pkg/mod/github.com/valyala/[email protected]/client.go:1659 +0x2ff
    created by github.com/valyala/fasthttp.(*HostClient).acquireConn
            /home/runner/go/pkg/mod/github.com/valyala/[email protected]/client.go:1549 +0x1da
    
    goroutine 1484 [sleep]:
    time.Sleep(0x2540be400)
            /opt/hostedtoolcache/go/1.15.11/x64/src/runtime/time.go:188 +0xbf
    github.com/valyala/fasthttp.(*HostClient).connsCleaner(0xc00dc75380)
            /home/runner/go/pkg/mod/github.com/valyala/[email protected]/client.go:1659 +0x2ff
    created by github.com/valyala/fasthttp.(*HostClient).acquireConn
            /home/runner/go/pkg/mod/github.com/valyala/[email protected]/client.go:1549 +0x1da
    
    goroutine 18291280 [runnable]:
    internal/poll.runtime_pollWait(0x7f2726e5ce18, 0x72, 0xde4420)
            /opt/hostedtoolcache/go/1.15.11/x64/src/runtime/netpoll.go:222 +0x55
    internal/poll.(*pollDesc).wait(0xc0e1e9f118, 0x72, 0xde4400, 0x11ec798, 0x0)
            /opt/hostedtoolcache/go/1.15.11/x64/src/internal/poll/fd_poll_runtime.go:87 +0x45
    internal/poll.(*pollDesc).waitRead(...)
            /opt/hostedtoolcache/go/1.15.11/x64/src/internal/poll/fd_poll_runtime.go:92
    internal/poll.(*FD).Read(0xc0e1e9f100, 0xc0e2864fc0, 0x205, 0x205, 0x0, 0x0, 0x0)
            /opt/hostedtoolcache/go/1.15.11/x64/src/internal/poll/fd_unix.go:159 +0x1a5
    net.(*netFD).Read(0xc0e1e9f100, 0xc0e2864fc0, 0x205, 0x205, 0x203038, 0x58, 0xc000192000)
            /opt/hostedtoolcache/go/1.15.11/x64/src/net/fd_posix.go:55 +0x4f
    net.(*conn).Read(0xc00128af20, 0xc0e2864fc0, 0x205, 0x205, 0x0, 0x0, 0x0)
            /opt/hostedtoolcache/go/1.15.11/x64/src/net/net.go:182 +0x8e
    crypto/tls.(*atLeastReader).Read(0xc0e28624c0, 0xc0e2864fc0, 0x205, 0x205, 0xc0e2864fc0, 0x0, 0xc00e9796a8)
            /opt/hostedtoolcache/go/1.15.11/x64/src/crypto/tls/conn.go:779 +0x62
    bytes.(*Buffer).ReadFrom(0xc0e24d3b00, 0xde2360, 0xc0e28624c0, 0x40b725, 0xc3ab20, 0xcc3ee0)
            /opt/hostedtoolcache/go/1.15.11/x64/src/bytes/buffer.go:204 +0xb1
    crypto/tls.(*Conn).readFromUntil(0xc0e24d3880, 0xde3060, 0xc00128af20, 0x5, 0xc00128af20, 0x1000000caa9a0)
            /opt/hostedtoolcache/go/1.15.11/x64/src/crypto/tls/conn.go:801 +0xf3
    crypto/tls.(*Conn).readRecordOrCCS(0xc0e24d3880, 0xc0e24d8500, 0x1d7, 0x1e0)
            /opt/hostedtoolcache/go/1.15.11/x64/src/crypto/tls/conn.go:608 +0x115
    crypto/tls.(*Conn).readRecord(...)
            /opt/hostedtoolcache/go/1.15.11/x64/src/crypto/tls/conn.go:576
    crypto/tls.(*Conn).readHandshake(0xc0e24d3880, 0xc0e24d6f16, 0xc0e24d6f00, 0x1d2, 0x300)
            /opt/hostedtoolcache/go/1.15.11/x64/src/crypto/tls/conn.go:992 +0x6d
    crypto/tls.(*Conn).clientHandshake(0xc0e24d3880, 0x0, 0x0)
            /opt/hostedtoolcache/go/1.15.11/x64/src/crypto/tls/handshake_client.go:170 +0x2a7
    crypto/tls.(*Conn).Handshake(0xc0e24d3880, 0x0, 0x0)
            /opt/hostedtoolcache/go/1.15.11/x64/src/crypto/tls/conn.go:1362 +0xc9
    github.com/valyala/fasthttp.tlsClientHandshake.func1(0xc0a80d1200, 0xc0e24d3880)
            /home/runner/go/pkg/mod/github.com/valyala/[email protected]/client.go:1896 +0x2b
    created by github.com/valyala/fasthttp.tlsClientHandshake
            /home/runner/go/pkg/mod/github.com/valyala/[email protected]/client.go:1895 +0x15b
    
    goroutine 18291328 [select]:
    net.(*netFD).connect.func2(0xdf3960, 0xc0e2bd8c00, 0xc0e25cea00, 0xc0e2b9e660, 0xc0e2b9e600)
            /opt/hostedtoolcache/go/1.15.11/x64/src/net/fd_unix.go:118 +0xc5
    created by net.(*netFD).connect
            /opt/hostedtoolcache/go/1.15.11/x64/src/net/fd_unix.go:117 +0x234
    
    goroutine 18291279 [select]:
    net.(*netFD).connect.func2(0xdf3960, 0xc0e285ea80, 0xc0e18a1f80, 0xc0e2848660, 0xc0e2848600)
            /opt/hostedtoolcache/go/1.15.11/x64/src/net/fd_unix.go:118 +0xc5
    created by net.(*netFD).connect
            /opt/hostedtoolcache/go/1.15.11/x64/src/net/fd_unix.go:117 +0x234
    
    goroutine 3144 [sleep]:
    time.Sleep(0x2540be400)
            /opt/hostedtoolcache/go/1.15.11/x64/src/runtime/time.go:188 +0xbf
    github.com/valyala/fasthttp.(*HostClient).connsCleaner(0xc00f4e8900)
            /home/runner/go/pkg/mod/github.com/valyala/[email protected]/client.go:1659 +0x2ff
    created by github.com/valyala/fasthttp.(*HostClient).acquireConn
            /home/runner/go/pkg/mod/github.com/valyala/[email protected]/client.go:1549 +0x1da
    
    goroutine 3227 [chan send]:
    github.com/assetnote/kiterunner/pkg/kiterunner.handleTarget.func3(0xc00a51ead0, 0xb, 0xc0002b2300, 0xc00017e680, 0xc000320c00, 0xc00a552a80, 0xc0002f6090)
            /home/runner/work/kiterunner/kiterunner/pkg/kiterunner/kiterunner.go:143 +0x4d4
    created by github.com/assetnote/kiterunner/pkg/kiterunner.handleTarget
            /home/runner/work/kiterunner/kiterunner/pkg/kiterunner/kiterunner.go:100 +0x285
    
    goroutine 2079 [chan send]:
    github.com/assetnote/kiterunner/pkg/kiterunner.handleTarget.func3(0xc007cd65d0, 0xb, 0xc0002b2300, 0xc000079c70, 0xc000320720, 0xc00e598000, 0xc0002f6090)
            /home/runner/work/kiterunner/kiterunner/pkg/kiterunner/kiterunner.go:143 +0x4d4
    created by github.com/assetnote/kiterunner/pkg/kiterunner.handleTarget
            /home/runner/work/kiterunner/kiterunner/pkg/kiterunner/kiterunner.go:100 +0x285
    
    goroutine 18291283 [runnable]:
    internal/poll.runtime_pollWait(0x7f2726f31448, 0x72, 0xde4420)
            /opt/hostedtoolcache/go/1.15.11/x64/src/runtime/netpoll.go:222 +0x55
    internal/poll.(*pollDesc).wait(0xc0e1c86e18, 0x72, 0xde4400, 0x11ec798, 0x0)
            /opt/hostedtoolcache/go/1.15.11/x64/src/internal/poll/fd_poll_runtime.go:87 +0x45
    internal/poll.(*pollDesc).waitRead(...)
            /opt/hostedtoolcache/go/1.15.11/x64/src/internal/poll/fd_poll_runtime.go:92
    internal/poll.(*FD).Read(0xc0e1c86e00, 0xc0e2927500, 0x1395, 0x1395, 0x0, 0x0, 0x0)
            /opt/hostedtoolcache/go/1.15.11/x64/src/internal/poll/fd_unix.go:159 +0x1a5
    net.(*netFD).Read(0xc0e1c86e00, 0xc0e2927500, 0x1395, 0x1395, 0x203038, 0x1824cea5cb6c7fde, 0xeda59954d59de281)
            /opt/hostedtoolcache/go/1.15.11/x64/src/net/fd_posix.go:55 +0x4f
    net.(*conn).Read(0xc007178d60, 0xc0e2927500, 0x1395, 0x1395, 0x0, 0x0, 0x0)
            /opt/hostedtoolcache/go/1.15.11/x64/src/net/net.go:182 +0x8e
    crypto/tls.(*atLeastReader).Read(0xc0e294e8a0, 0xc0e2927500, 0x1395, 0x1395, 0xe84014a3facd765b, 0xc0d6e1b708, 0xc0d6e1b440)
            /opt/hostedtoolcache/go/1.15.11/x64/src/crypto/tls/conn.go:779 +0x62
    bytes.(*Buffer).ReadFrom(0xc0e26a4600, 0xde2360, 0xc0e294e8a0, 0x40b725, 0xc3ab20, 0xcc3ee0)
            /opt/hostedtoolcache/go/1.15.11/x64/src/bytes/buffer.go:204 +0xb1
    crypto/tls.(*Conn).readFromUntil(0xc0e26a4380, 0xde3060, 0xc007178d60, 0x5, 0xc007178d60, 0x0)
            /opt/hostedtoolcache/go/1.15.11/x64/src/crypto/tls/conn.go:801 +0xf3
    crypto/tls.(*Conn).readRecordOrCCS(0xc0e26a4380, 0xc0e1c86e01, 0xc0e4130000, 0x7e)
            /opt/hostedtoolcache/go/1.15.11/x64/src/crypto/tls/conn.go:608 +0x115
    crypto/tls.(*Conn).readChangeCipherSpec(...)
            /opt/hostedtoolcache/go/1.15.11/x64/src/crypto/tls/conn.go:580
    crypto/tls.(*clientHandshakeState).readFinished(0xc0d6e1bd68, 0xc0e26a44b5, 0xc, 0xc, 0x0, 0x0)
            /opt/hostedtoolcache/go/1.15.11/x64/src/crypto/tls/handshake_client.go:748 +0x53
    crypto/tls.(*clientHandshakeState).handshake(0xc0d6e1bd68, 0xc0e290fcd0, 0x4)
            /opt/hostedtoolcache/go/1.15.11/x64/src/crypto/tls/handshake_client.go:436 +0x673
    crypto/tls.(*Conn).clientHandshake(0xc0e26a4380, 0x0, 0x0)
            /opt/hostedtoolcache/go/1.15.11/x64/src/crypto/tls/handshake_client.go:219 +0x754
    crypto/tls.(*Conn).Handshake(0xc0e26a4380, 0x0, 0x0)
            /opt/hostedtoolcache/go/1.15.11/x64/src/crypto/tls/conn.go:1362 +0xc9
    github.com/valyala/fasthttp.tlsClientHandshake.func1(0xc0312625a0, 0xc0e26a4380)
            /home/runner/go/pkg/mod/github.com/valyala/[email protected]/client.go:1896 +0x2b
    created by github.com/valyala/fasthttp.tlsClientHandshake
            /home/runner/go/pkg/mod/github.com/valyala/[email protected]/client.go:1895 +0x15b
    
    goroutine 18291409 [runnable]:
    internal/poll.runtime_pollWait(0x7f27274fb2f0, 0x72, 0xde4420)
            /opt/hostedtoolcache/go/1.15.11/x64/src/runtime/netpoll.go:222 +0x55
    internal/poll.(*pollDesc).wait(0xc0e18a1a98, 0x72, 0xde4400, 0x11ec798, 0x0)
            /opt/hostedtoolcache/go/1.15.11/x64/src/internal/poll/fd_poll_runtime.go:87 +0x45
    internal/poll.(*pollDesc).waitRead(...)
            /opt/hostedtoolcache/go/1.15.11/x64/src/internal/poll/fd_poll_runtime.go:92
    internal/poll.(*FD).Read(0xc0e18a1a80, 0xc0e2865b00, 0x205, 0x205, 0x0, 0x0, 0x0)
            /opt/hostedtoolcache/go/1.15.11/x64/src/internal/poll/fd_unix.go:159 +0x1a5
    net.(*netFD).Read(0xc0e18a1a80, 0xc0e2865b00, 0x205, 0x205, 0x203038, 0x58, 0xc000600000)
            /opt/hostedtoolcache/go/1.15.11/x64/src/net/fd_posix.go:55 +0x4f
    net.(*conn).Read(0xc00128af28, 0xc0e2865b00, 0x205, 0x205, 0x0, 0x0, 0x0)
            /opt/hostedtoolcache/go/1.15.11/x64/src/net/net.go:182 +0x8e
    crypto/tls.(*atLeastReader).Read(0xc0e28626a0, 0xc0e2865b00, 0x205, 0x205, 0xc0e2865b00, 0x0, 0xc00e9676a8)
            /opt/hostedtoolcache/go/1.15.11/x64/src/crypto/tls/conn.go:779 +0x62
    bytes.(*Buffer).ReadFrom(0xc0e24d3e80, 0xde2360, 0xc0e28626a0, 0x40b725, 0xc3ab20, 0xcc3ee0)
            /opt/hostedtoolcache/go/1.15.11/x64/src/bytes/buffer.go:204 +0xb1
    crypto/tls.(*Conn).readFromUntil(0xc0e24d3c00, 0xde3060, 0xc00128af28, 0x5, 0xc00128af28, 0x1000000caa9a0)
            /opt/hostedtoolcache/go/1.15.11/x64/src/crypto/tls/conn.go:801 +0xf3
    crypto/tls.(*Conn).readRecordOrCCS(0xc0e24d3c00, 0xc0e2800400, 0x11d, 0x120)
            /opt/hostedtoolcache/go/1.15.11/x64/src/crypto/tls/conn.go:608 +0x115
    crypto/tls.(*Conn).readRecord(...)
            /opt/hostedtoolcache/go/1.15.11/x64/src/crypto/tls/conn.go:576
    crypto/tls.(*Conn).readHandshake(0xc0e24d3c00, 0xc0e20c7916, 0xc0e20c7980, 0x118, 0x180)
            /opt/hostedtoolcache/go/1.15.11/x64/src/crypto/tls/conn.go:992 +0x6d
    crypto/tls.(*Conn).clientHandshake(0xc0e24d3c00, 0x0, 0x0)
            /opt/hostedtoolcache/go/1.15.11/x64/src/crypto/tls/handshake_client.go:170 +0x2a7
    crypto/tls.(*Conn).Handshake(0xc0e24d3c00, 0x0, 0x0)
            /opt/hostedtoolcache/go/1.15.11/x64/src/crypto/tls/conn.go:1362 +0xc9
    github.com/valyala/fasthttp.tlsClientHandshake.func1(0xc030661500, 0xc0e24d3c00)
            /home/runner/go/pkg/mod/github.com/valyala/[email protected]/client.go:1896 +0x2b
    created by github.com/valyala/fasthttp.tlsClientHandshake
            /home/runner/go/pkg/mod/github.com/valyala/[email protected]/client.go:1895 +0x15b
    
    goroutine 18291391 [select]:
    net.(*netFD).connect.func2(0xdf3960, 0xc0e2c26ae0, 0xc0e26fc600, 0xc0e26d7320, 0xc0e26d72c0)
            /opt/hostedtoolcache/go/1.15.11/x64/src/net/fd_unix.go:118 +0xc5
    created by net.(*netFD).connect
            /opt/hostedtoolcache/go/1.15.11/x64/src/net/fd_unix.go:117 +0x234
    
    goroutine 2080 [chan send]:
    github.com/assetnote/kiterunner/pkg/kiterunner.handleTarget.func3(0xc000594010, 0xb, 0xc0002b2300, 0xc000079a00, 0xc000320600, 0xc00e598360, 0xc0002f6090)
            /home/runner/work/kiterunner/kiterunner/pkg/kiterunner/kiterunner.go:143 +0x4d4
    created by github.com/assetnote/kiterunner/pkg/kiterunner.handleTarget
            /home/runner/work/kiterunner/kiterunner/pkg/kiterunner/kiterunner.go:100 +0x285
    
    goroutine 18291417 [runnable]:
    internal/poll.runtime_pollWait(0x7f2726f305c8, 0x72, 0xde4420)
            /opt/hostedtoolcache/go/1.15.11/x64/src/runtime/netpoll.go:222 +0x55
    internal/poll.(*pollDesc).wait(0xc0e2464e18, 0x72, 0xde4400, 0x11ec798, 0x0)
            /opt/hostedtoolcache/go/1.15.11/x64/src/internal/poll/fd_poll_runtime.go:87 +0x45
    internal/poll.(*pollDesc).waitRead(...)
            /opt/hostedtoolcache/go/1.15.11/x64/src/internal/poll/fd_poll_runtime.go:92
    internal/poll.(*FD).Read(0xc0e2464e00, 0xc0e2c94900, 0x205, 0x205, 0x0, 0x0, 0x0)
            /opt/hostedtoolcache/go/1.15.11/x64/src/internal/poll/fd_unix.go:159 +0x1a5
    net.(*netFD).Read(0xc0e2464e00, 0xc0e2c94900, 0x205, 0x205, 0x203038, 0x58, 0xc042243c00)
            /opt/hostedtoolcache/go/1.15.11/x64/src/net/fd_posix.go:55 +0x4f
    net.(*conn).Read(0xc00128af48, 0xc0e2c94900, 0x205, 0x205, 0x0, 0x0, 0x0)
            /opt/hostedtoolcache/go/1.15.11/x64/src/net/net.go:182 +0x8e
    crypto/tls.(*atLeastReader).Read(0xc0e28630e0, 0xc0e2c94900, 0x205, 0x205, 0xc0e2c94900, 0x0, 0xc00e9696a8)
            /opt/hostedtoolcache/go/1.15.11/x64/src/crypto/tls/conn.go:779 +0x62
    bytes.(*Buffer).ReadFrom(0xc0e2870d00, 0xde2360, 0xc0e28630e0, 0x40b725, 0xc3ab20, 0xcc3ee0)
            /opt/hostedtoolcache/go/1.15.11/x64/src/bytes/buffer.go:204 +0xb1
    crypto/tls.(*Conn).readFromUntil(0xc0e2870a80, 0xde3060, 0xc00128af48, 0x5, 0xc00128af48, 0x1000000caa9a0)
            /opt/hostedtoolcache/go/1.15.11/x64/src/crypto/tls/conn.go:801 +0xf3
    crypto/tls.(*Conn).readRecordOrCCS(0xc0e2870a80, 0xc0e24d8b00, 0x1d9, 0x1e0)
            /opt/hostedtoolcache/go/1.15.11/x64/src/crypto/tls/conn.go:608 +0x115
    crypto/tls.(*Conn).readRecord(...)
            /opt/hostedtoolcache/go/1.15.11/x64/src/crypto/tls/conn.go:576
    crypto/tls.(*Conn).readHandshake(0xc0e2870a80, 0xc0e24d7b16, 0xc0e24d7b00, 0x1d4, 0x300)
            /opt/hostedtoolcache/go/1.15.11/x64/src/crypto/tls/conn.go:992 +0x6d
    crypto/tls.(*Conn).clientHandshake(0xc0e2870a80, 0x0, 0x0)
            /opt/hostedtoolcache/go/1.15.11/x64/src/crypto/tls/handshake_client.go:170 +0x2a7
    crypto/tls.(*Conn).Handshake(0xc0e2870a80, 0x0, 0x0)
            /opt/hostedtoolcache/go/1.15.11/x64/src/crypto/tls/conn.go:1362 +0xc9
    github.com/valyala/fasthttp.tlsClientHandshake.func1(0xc004e451a0, 0xc0e2870a80)
            /home/runner/go/pkg/mod/github.com/valyala/[email protected]/client.go:1896 +0x2b
    created by github.com/valyala/fasthttp.tlsClientHandshake
            /home/runner/go/pkg/mod/github.com/valyala/[email protected]/client.go:1895 +0x15b
    
    goroutine 1659366 [chan send]:
    github.com/assetnote/kiterunner/pkg/kiterunner.handleTarget.func3(0xc004e43234, 0xb, 0xc0002b2300, 0xc00017fd40, 0xc000320300, 0xc00dbac420, 0xc0002f6090)
            /home/runner/work/kiterunner/kiterunner/pkg/kiterunner/kiterunner.go:143 +0x4d4
    created by github.com/assetnote/kiterunner/pkg/kiterunner.handleTarget
            /home/runner/work/kiterunner/kiterunner/pkg/kiterunner/kiterunner.go:100 +0x285
    
    goroutine 18291386 [select]:
    net.(*netFD).connect.func2(0xdf3960, 0xc0e2c11740, 0xc0e26fc200, 0xc0e26d6c60, 0xc0e26d6c00)
            /opt/hostedtoolcache/go/1.15.11/x64/src/net/fd_unix.go:118 +0xc5
    created by net.(*netFD).connect
            /opt/hostedtoolcache/go/1.15.11/x64/src/net/fd_unix.go:117 +0x234
    
    goroutine 18291395 [select]:
    net.(*netFD).connect.func2(0xdf3960, 0xc0e297de00, 0xc0e1e9f900, 0xc0e2733a40, 0xc0e27339e0)
            /opt/hostedtoolcache/go/1.15.11/x64/src/net/fd_unix.go:118 +0xc5
    created by net.(*netFD).connect
            /opt/hostedtoolcache/go/1.15.11/x64/src/net/fd_unix.go:117 +0x234
    
    goroutine 18291441 [select]:
    net.(*netFD).connect.func2(0xdf3960, 0xc0e2ac0b40, 0xc0e2465100, 0xc0e2aa0720, 0xc0e2aa06c0)
            /opt/hostedtoolcache/go/1.15.11/x64/src/net/fd_unix.go:118 +0xc5
    created by net.(*netFD).connect
            /opt/hostedtoolcache/go/1.15.11/x64/src/net/fd_unix.go:117 +0x234
    
    goroutine 18291411 [select]:
    net.(*netFD).connect.func2(0xdf3960, 0xc0e2872900, 0xc0e2876080, 0xc0e2848a20, 0xc0e28489c0)
            /opt/hostedtoolcache/go/1.15.11/x64/src/net/fd_unix.go:118 +0xc5
    created by net.(*netFD).connect
            /opt/hostedtoolcache/go/1.15.11/x64/src/net/fd_unix.go:117 +0x234
    
    goroutine 18291344 [runnable]:
    internal/poll.runtime_pollWait(0x7f27279b3298, 0x72, 0xde4420)
            /opt/hostedtoolcache/go/1.15.11/x64/src/runtime/netpoll.go:222 +0x55
    internal/poll.(*pollDesc).wait(0xc0e18a1b98, 0x72, 0xde4400, 0x11ec798, 0x0)
            /opt/hostedtoolcache/go/1.15.11/x64/src/internal/poll/fd_poll_runtime.go:87 +0x45
    internal/poll.(*pollDesc).waitRead(...)
            /opt/hostedtoolcache/go/1.15.11/x64/src/internal/poll/fd_poll_runtime.go:92
    internal/poll.(*FD).Read(0xc0e18a1b80, 0xc0e2ab0900, 0x205, 0x205, 0x0, 0x0, 0x0)
            /opt/hostedtoolcache/go/1.15.11/x64/src/internal/poll/fd_unix.go:159 +0x1a5
    net.(*netFD).Read(0xc0e18a1b80, 0xc0e2ab0900, 0x205, 0x205, 0x203038, 0x58, 0xc015207c00)
            /opt/hostedtoolcache/go/1.15.11/x64/src/net/fd_posix.go:55 +0x4f
    net.(*conn).Read(0xc006fcbd58, 0xc0e2ab0900, 0x205, 0x205, 0x0, 0x0, 0x0)
            /opt/hostedtoolcache/go/1.15.11/x64/src/net/net.go:182 +0x8e
    crypto/tls.(*atLeastReader).Read(0xc0e2aaa400, 0xc0e2ab0900, 0x205, 0x205, 0xc0e2ab0900, 0x0, 0xc00e2006a8)
            /opt/hostedtoolcache/go/1.15.11/x64/src/crypto/tls/conn.go:779 +0x62
    bytes.(*Buffer).ReadFrom(0xc0e2987400, 0xde2360, 0xc0e2aaa400, 0x40b725, 0xc3ab20, 0xcc3ee0)
            /opt/hostedtoolcache/go/1.15.11/x64/src/bytes/buffer.go:204 +0xb1
    crypto/tls.(*Conn).readFromUntil(0xc0e2987180, 0xde3060, 0xc006fcbd58, 0x5, 0xc006fcbd58, 0x1000000caa9a0)
            /opt/hostedtoolcache/go/1.15.11/x64/src/crypto/tls/conn.go:801 +0xf3
    crypto/tls.(*Conn).readRecordOrCCS(0xc0e2987180, 0xc0e1e60f00, 0x1d9, 0x1e0)
            /opt/hostedtoolcache/go/1.15.11/x64/src/crypto/tls/conn.go:608 +0x115
    crypto/tls.(*Conn).readRecord(...)
            /opt/hostedtoolcache/go/1.15.11/x64/src/crypto/tls/conn.go:576
    crypto/tls.(*Conn).readHandshake(0xc0e2987180, 0xc0e27bb516, 0xc0e27bb500, 0x1d4, 0x300)
            /opt/hostedtoolcache/go/1.15.11/x64/src/crypto/tls/conn.go:992 +0x6d
    crypto/tls.(*Conn).clientHandshake(0xc0e2987180, 0x0, 0x0)
            /opt/hostedtoolcache/go/1.15.11/x64/src/crypto/tls/handshake_client.go:170 +0x2a7
    crypto/tls.(*Conn).Handshake(0xc0e2987180, 0x0, 0x0)
            /opt/hostedtoolcache/go/1.15.11/x64/src/crypto/tls/conn.go:1362 +0xc9
    github.com/valyala/fasthttp.tlsClientHandshake.func1(0xc0e8c13500, 0xc0e2987180)
            /home/runner/go/pkg/mod/github.com/valyala/[email protected]/client.go:1896 +0x2b
    created by github.com/valyala/fasthttp.tlsClientHandshake
            /home/runner/go/pkg/mod/github.com/valyala/[email protected]/client.go:1895 +0x15b
    
    goroutine 18291428 [select]:
    net.(*netFD).connect.func2(0xdf3960, 0xc0e2dca360, 0xc0e2a62180, 0xc0e2a5a840, 0xc0e2a5a7e0)
            /opt/hostedtoolcache/go/1.15.11/x64/src/net/fd_unix.go:118 +0xc5
    created by net.(*netFD).connect
            /opt/hostedtoolcache/go/1.15.11/x64/src/net/fd_unix.go:117 +0x234
    
    goroutine 18291325 [runnable]:
    internal/poll.runtime_pollWait(0x7f2726fb6eb0, 0x72, 0xde4420)
            /opt/hostedtoolcache/go/1.15.11/x64/src/runtime/netpoll.go:222 +0x55
    internal/poll.(*pollDesc).wait(0xc0e1c6bb98, 0x72, 0xde4400, 0x11ec798, 0x0)
            /opt/hostedtoolcache/go/1.15.11/x64/src/internal/poll/fd_poll_runtime.go:87 +0x45
    internal/poll.(*pollDesc).waitRead(...)
            /opt/hostedtoolcache/go/1.15.11/x64/src/internal/poll/fd_poll_runtime.go:92
    internal/poll.(*FD).Read(0xc0e1c6bb80, 0xc0e2bab200, 0x205, 0x205, 0x0, 0x0, 0x0)
            /opt/hostedtoolcache/go/1.15.11/x64/src/internal/poll/fd_unix.go:159 +0x1a5
    net.(*netFD).Read(0xc0e1c6bb80, 0xc0e2bab200, 0x205, 0x205, 0x203038, 0x58, 0xc000192000)
            /opt/hostedtoolcache/go/1.15.11/x64/src/net/fd_posix.go:55 +0x4f
    net.(*conn).Read(0xc10b7d28a0, 0xc0e2bab200, 0x205, 0x205, 0x0, 0x0, 0x0)
            /opt/hostedtoolcache/go/1.15.11/x64/src/net/net.go:182 +0x8e
    crypto/tls.(*atLeastReader).Read(0xc0e2ba0780, 0xc0e2bab200, 0x205, 0x205, 0xc0e2bab200, 0x0, 0xc00dc096a8)
            /opt/hostedtoolcache/go/1.15.11/x64/src/crypto/tls/conn.go:779 +0x62
    bytes.(*Buffer).ReadFrom(0xc0e25d1400, 0xde2360, 0xc0e2ba0780, 0x40b725, 0xc3ab20, 0xcc3ee0)
            /opt/hostedtoolcache/go/1.15.11/x64/src/bytes/buffer.go:204 +0xb1
    crypto/tls.(*Conn).readFromUntil(0xc0e25d1180, 0xde3060, 0xc10b7d28a0, 0x5, 0xc10b7d28a0, 0x1000000caa9a0)
            /opt/hostedtoolcache/go/1.15.11/x64/src/crypto/tls/conn.go:801 +0xf3
    crypto/tls.(*Conn).readRecordOrCCS(0xc0e25d1180, 0xc0e1b6b600, 0x1d7, 0x1e0)
            /opt/hostedtoolcache/go/1.15.11/x64/src/crypto/tls/conn.go:608 +0x115
    crypto/tls.(*Conn).readRecord(...)
            /opt/hostedtoolcache/go/1.15.11/x64/src/crypto/tls/conn.go:576
    crypto/tls.(*Conn).readHandshake(0xc0e25d1180, 0xc0e2bb6016, 0xc0e2bb6000, 0x1d2, 0x300)
            /opt/hostedtoolcache/go/1.15.11/x64/src/crypto/tls/conn.go:992 +0x6d
    crypto/tls.(*Conn).clientHandshake(0xc0e25d1180, 0x0, 0x0)
            /opt/hostedtoolcache/go/1.15.11/x64/src/crypto/tls/handshake_client.go:170 +0x2a7
    crypto/tls.(*Conn).Handshake(0xc0e25d1180, 0x0, 0x0)
            /opt/hostedtoolcache/go/1.15.11/x64/src/crypto/tls/conn.go:1362 +0xc9
    github.com/valyala/fasthttp.tlsClientHandshake.func1(0xc106f8ff80, 0xc0e25d1180)
            /home/runner/go/pkg/mod/github.com/valyala/[email protected]/client.go:1896 +0x2b
    created by github.com/valyala/fasthttp.tlsClientHandshake
            /home/runner/go/pkg/mod/github.com/valyala/[email protected]/client.go:1895 +0x15b
    
  • How to save results and what does a profile do?

    How to save results and what does a profile do?

    Attempting to distribute kiterunner with axiom https://github.com/pry0cc/axiom. How can we specify a text output file? Should we just pipe to tee?

    and does a profile do?

    Thank you!

  • kr kb replay error: FTL failed to replay request error=

    kr kb replay error: FTL failed to replay request error="unable to find ksuid"

    After completing a scan, and attempting to replay one of the requests, I get the following error:

    FTL failed to replay request error="unable to find ksuid"

    Screenshot 2022-07-23 at 9 55 03 AM

  • fix(cli-scan): avoid double appending / in the basepath and route path in output

    fix(cli-scan): avoid double appending / in the basepath and route path in output

    Fixes #13 .

    This changes the PrintOutput function for displaying results in pretty and text mode.

    this will inspect the output bytes for the target to avoid printing both a trailing / on the basepath and a prefix / for the route path. This is purely a cosmetic change, as our underlying request engine already collapses duplicate paths

    so now the behaviour will occurs as follows:

    http://foo.com/foo + /bar.txt => http://foo.com/foo/bar.txt (as normal)
    http://foo.com/foo + bar.txt => http://foo.com/foo/bar.txt (our wordlist loading prefixes / for you)
    http://foo.com/foo + /bar.txt => http://foo.com/foo/bar.txt
    http://foo.com/foo/ + /bar.txt => http://foo.com/foo/bar.txt (the bar.txt slash is dropped)
    http://foo.com/foo// + /bar.txt => http://foo.com/foo//bar.txt (the bar.txt slash is dropped, but you added two, so thats your fault)
    

    We also add some tests to validate that the parsing of the basepath is as we expect with trailing slashes.

    In the future, we may want to modify the behaviour of the routes loading to not prepend the '/' so if you specify http://foo.com/bar and file.txt you'll get http://foo.com/barfile.txt without a joining slash.

  • docs(kiterunner.yaml): added example kiterunner.yaml

    docs(kiterunner.yaml): added example kiterunner.yaml

    fixes https://github.com/assetnote/kiterunner/issues/3

    on a related note, we should extend the number of flags supported by the viper yaml config tracked in issue https://github.com/assetnote/kiterunner/issues/19

  • Handle visual bug with multiple `/` in the base path and the request

    Handle visual bug with multiple `/` in the base path and the request

    When a target is supplied with a basepath of /, e.g. http://example.com/, we display a request being sent to http://example.com//foo.txt.

    however, this appears to be a visual bug, as our http library will collapse consecutive //.

    image

    The duplication likely occurs when when we concat the basepath / with the / prefixed path, http://example.com/ + /foo.txt when printing the result.

    it may be worthwhile either:

    • ensuring the basepath does not end with a /.
    • Using a http library that does not collapse consecutive //

    Issue reported by @NayrGames on twitter.

  • GH-8 Wordlist panic fix

    GH-8 Wordlist panic fix

    Fixes https://github.com/assetnote/kiterunner/issues/8

    • handles empty lines in wordlist
    • handles .kite and .json filetypes in normal wordlist loading.
  • panic: runtime error: index out of range [0] with length 0

    panic: runtime error: index out of range [0] with length 0

    command: kr brute https://www.site.com -w /opt/assetnote/swagger-wordlist.txt

    result: panic: runtime error: index out of range [0] with length 0

    goroutine 1 [running]: github.com/assetnote/kiterunner/internal/scan.LoadTextWordlist.func1(0xc0001a6000, 0x0, 0x0) /home/runner/work/kiterunner/kiterunner/internal/scan/options.go:290 +0xa94 github.com/assetnote/kiterunner/internal/scan.ScanDomainOrFile(0xdf37e0, 0xc00027c380, 0x7fffec2dc43e, 0x19, 0xc00026dce0, 0x14, 0x14, 0xc00027c340, 0xc00026dcb8) /home/runner/work/kiterunner/kiterunner/internal/scan/scan.go:61 +0x2a6 github.com/assetnote/kiterunner/cmd/kiterunner/cmd.glob..func1(0x12a9d80, 0xc0000a5180, 0x1, 0x8) /home/runner/work/kiterunner/kiterunner/cmd/kiterunner/cmd/brute.go:93 +0x5f7 github.com/spf13/cobra.(*Command).execute(0x12a9d80, 0xc0000a5100, 0x8, 0x8, 0x12a9d80, 0xc0000a5100) /home/runner/go/pkg/mod/github.com/spf13/[email protected]/command.go:856 +0x2c2 github.com/spf13/cobra.(*Command).ExecuteC(0x12ab900, 0x0, 0x0, 0x0) /home/runner/go/pkg/mod/github.com/spf13/[email protected]/command.go:960 +0x375 github.com/spf13/cobra.(*Command).Execute(...) /home/runner/go/pkg/mod/github.com/spf13/[email protected]/command.go:897 github.com/assetnote/kiterunner/cmd/kiterunner/cmd.Execute() /home/runner/work/kiterunner/kiterunner/cmd/kiterunner/cmd/root.go:37 +0x2d main.main() /home/runner/work/kiterunner/kiterunner/cmd/kiterunner/main.go:5 +0x25

  • kiterunner kb fails: error=

    kiterunner kb fails: error="failed to unmarshal param: json: ...

    Any idea what is causing this bug and how to fix it?

    % ./kr version -q
    1.0.2 - e7a7fa6
    Built on 2021-04-11T09:51:54Z
    
    % ./kr kb -v debug -q compile routes-small.json testd.kite
    6:01AM DBG custom log settings format=pretty
    6:01AM DBG beginning slow load of json bytes
    6:02AM DBG  Context=root.[].v ID=root Method= Route=
    6:02AM DBG      Context=api.paths.operations.parameters ID=0cc39f6e72c06b91fbe278994d5ec9f40c67eece Method=post Route=/onos/vtn/subnets
    6:02AM DBG          error="failed to unmarshal param: json: cannot unmarshal array into Go struct field Parameter.schema of type kitebuilder.Schema" Context=param.[].v ID= JSON={"in":"body","name":"input","required":true,"schema":[]} Method= Route=
    6:02AM DBG      Context=api.paths.operations.parameters ID=0cc39f6e72c06b91fbe278994d5ec9f40c67eece Method=post Route=/onos/vtn/routers
    6:02AM DBG          error="failed to unmarshal param: json: cannot unmarshal array into Go struct field Parameter.schema of
    p type kitebuilder.Schema" Context=param.[].v ID= JSON={"in":"body","name":"input","required":true,"schema":[]} Method= Route=
    [...]
    
  • Confusing description of scan VS brute modes

    Confusing description of scan VS brute modes

    Can you extend the documentation diging more in the difference between scan and brute modes, its not clear, maybe some examples would be useful explaining the requests that would send kiterunner.

  • Parse errors on perl-ish negative lookahead regex syntax in routes-small.json, routes-large.json

    Parse errors on perl-ish negative lookahead regex syntax in routes-small.json, routes-large.json

    The routes-small.json and routes-large.json files at https://wordlists-cdn.assetnote.io/rawdata/kiterunner/ trigger parse errors visible when running kr scan ... -v debug such as:

    7:05PM DBG failed to generate regex string crumb value error="error parsing regexp: invalid or unsupported Perl syntax: `(?!`" name=owner regex=[a-z0-9](?:-(?!-)|[a-z0-9])+[a-z0-9]
    7:05PM DBG failed to generate regex string crumb value error="error parsing regexp: invalid or unsupported Perl syntax: `(?!`" name=id regex=[a-z0-9](?:-(?!-)|[a-z0-9])+[a-z0-9]
    7:05PM DBG failed to generate regex string crumb value error="error parsing regexp: invalid or unsupported Perl syntax: `(?!`" name=streamId regex=[a-z0-9](?:-(?!-)|[a-z0-9]){1,93}[a-z0-9]
    7:05PM DBG failed to generate regex string crumb value error="error parsing regexp: invalid or unsupported Perl syntax: `(?!`" name=owner regex=[a-z0-9](?:-(?!-)|[a-z0-9])+[a-z0-9]
    ...
    

    Those regexes seem perfectly fine; these simple tests do what I think they should:

    $ for A in foo f-oo f--oo ; do echo "## $A" ; echo $A | grep -P '[a-z0-9](?:-(?!-)|[a-z0-9])+[a-z0-9]' ; echo $A | perl -ne 'print if /[a-z0-9](?:-(?!-)|[a-z0-9])+[a-z0-9]/' ; done
    ## foo
    foo
    foo
    ## f-oo
    f-oo
    f-oo
    ## f--oo
    $
    

    ...But, I think those errors are being emitted by binaryregexp, which although it has Perl / PerlX flags to turn on various perl-regex-like features, apparently does not support negative lookahead (?!.

    It's not clear to me if this bug belongs here or in https://github.com/assetnote/wordlists; given that those routes files exist solely for kiterunner, they ought to stick to syntax that kiterunner supports, or, kiterunner ought to switch to a smarter regex library that supports negative lookahead like maybe go-pcre.

  • Kiterunner not Using PROXY connection

    Kiterunner not Using PROXY connection

    Recently Kiterunner Stopped working/Using with PROXY connection and Also --proxy flags are not working, i'm not sure wheather the --proxy flag is used for proxy connection.

Parametrized JSON logging library in Golang which lets you obfuscate sensitive data and marshal any kind of content.
Parametrized JSON logging library in Golang which lets you obfuscate sensitive data and marshal any kind of content.

Noodlog Summary Noodlog is a Golang JSON parametrized and highly configurable logging library. It allows you to: print go structs as JSON messages; pr

Oct 27, 2022
Request-logging-tool - A tool logs the md5 codes of the responses of the given domains in parameter

request-logging-tool Application to send http requests and log the md5 responses

Jan 7, 2022
A GNU/Linux monitoring and profiling tool focused on single processes.
A GNU/Linux monitoring and profiling tool focused on single processes.

Uroboros is a GNU/Linux monitoring tool focused on single processes. While utilities like top, ps and htop provide great overall details, they often l

Dec 26, 2022
rtop is an interactive, remote system monitoring tool based on SSH

rtop rtop is a remote system monitor. It connects over SSH to a remote system and displays vital system metrics (CPU, disk, memory, network). No speci

Dec 30, 2022
Cloudinsight Agent is a system tool that monitors system processes and services, and sends information back to your Cloudinsight account.

Cloudinsight Agent 中文版 README Cloudinsight Agent is written in Go for collecting metrics from the system it's running on, or from other services, and

Nov 3, 2022
A system and resource monitoring tool written in Golang!
A system and resource monitoring tool written in Golang!

Grofer A clean and modern system and resource monitor written purely in golang using termui and gopsutil! Currently compatible with Linux only. Curren

Jan 8, 2023
A tool to list and diagnose Go processes currently running on your system

gops gops is a command to list and diagnose Go processes currently running on your system. $ gops 983 980 uplink-soecks go1.9 /usr/local/bin/u

Dec 27, 2022
pprof is a tool for visualization and analysis of profiling data

Introduction pprof is a tool for visualization and analysis of profiling data. pprof reads a collection of profiling samples in profile.proto format a

Jan 8, 2023
Changelog management tool, avoid merge conflicts and generate markdown changelogs.

chalog This is chalog, a changelog management tool. With chalog you can manage your project's changelog in a simple markdown format, split across mult

Jul 7, 2022
Gowl is a process management and process monitoring tool at once. An infinite worker pool gives you the ability to control the pool and processes and monitor their status.
Gowl is a process management and process monitoring tool at once. An infinite worker pool gives you the ability to control the pool and processes and monitor their status.

Gowl is a process management and process monitoring tool at once. An infinite worker pool gives you the ability to control the pool and processes and monitor their status.

Nov 10, 2022
gosivy - Real-time visualization tool for Go process metrics
 gosivy - Real-time visualization tool for Go process metrics

Gosivy tracks Go process's metrics and plot their evolution over time right into your terminal, no matter where it's running on. It helps you understand how your application consumes the resources.

Nov 27, 2022
Hidra is a tool to monitor all of your services without making a mess.

hidra Don't lose your mind monitoring your services. Hidra lends you its head. ICMP If you want to use ICMP scenario, you should activate on your syst

Nov 8, 2022
checkah is an agentless SSH system monitoring and alerting tool.

CHECKAH checkah is an agentless SSH system monitoring and alerting tool. Features: agentless check over SSH (password, keyfile, agent) config file bas

Oct 14, 2022
System resource usage profiler tool which regularly takes snapshots of the memory and CPU load of one or more running processes so as to dynamically build up a profile of their usage of system resources.
System resource usage profiler tool which regularly takes snapshots of the memory and CPU load of one or more running processes so as to dynamically build up a profile of their usage of system resources.

Vegeta is a system resource usage tracking tool built to regularly take snapshots of the memory and CPU load of one or more running processes, so as to dynamically build up a profile of their usage of system resources.

Jan 16, 2022
SigNoz helps developers monitor their applications & troubleshoot problems, an open-source alternative to DataDog, NewRelic, etc. 🔥 🖥. 👉 Open source Application Performance Monitoring (APM) & Observability tool
SigNoz helps developers monitor their applications & troubleshoot problems, an open-source alternative to DataDog, NewRelic, etc. 🔥 🖥.   👉  Open source Application Performance Monitoring (APM) & Observability tool

Monitor your applications and troubleshoot problems in your deployed applications, an open-source alternative to DataDog, New Relic, etc. Documentatio

Sep 24, 2021
Tool for generating OpenTelemetry tracing decorators.

tracegen Tool for generating OpenTelemetry tracing decorators. Installation go get -u github.com/KazanExpress/tracegen/cmd/... Usage tracegen generate

Apr 7, 2022
Beta tool to normalize Orbit member data

Orbit Normalize Member Data Thanks for checking out my handy tool to work with Orbit's api. Everything is written in go and will continue to be update

Sep 16, 2021
A Log merging tool for linux.

logmerge A Log merging tool for linux. How to build make build How to run --files or -f will allow you to specify multiple log files (comma-seperated)

Nov 4, 2021
Drop-in replacement for Go's stringer tool with support for bitflag sets.

stringer This program is a drop-in replacement for Go's commonly used stringer tool. In addition to generating String() string implementations for ind

Nov 26, 2021