mirror of
https://github.com/cheat/cheat.git
synced 2026-03-07 19:23:34 +01:00
chore: modernize CI and update Go toolchain
- Bump Go from 1.19 to 1.26 and update all dependencies - Rewrite CI workflow with matrix strategy (Linux, macOS, Windows) - Update GitHub Actions to current versions (checkout@v4, setup-go@v5) - Update CodeQL actions from v1 to v3 - Fix cross-platform bug in mock/path.go (path.Join -> filepath.Join) - Clean up dependabot config (weekly schedule, remove stale ignore) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
1
vendor/github.com/kevinburke/ssh_config/.gitattributes
generated
vendored
1
vendor/github.com/kevinburke/ssh_config/.gitattributes
generated
vendored
@@ -1 +0,0 @@
|
||||
testdata/dos-lines eol=crlf
|
||||
1
vendor/github.com/kevinburke/ssh_config/.gitignore
generated
vendored
1
vendor/github.com/kevinburke/ssh_config/.gitignore
generated
vendored
@@ -0,0 +1 @@
|
||||
/coverage.out
|
||||
|
||||
2
vendor/github.com/kevinburke/ssh_config/AUTHORS.txt
generated
vendored
2
vendor/github.com/kevinburke/ssh_config/AUTHORS.txt
generated
vendored
@@ -5,5 +5,7 @@ Kevin Burke <kevin@burke.dev>
|
||||
Mark Nevill <nev@improbable.io>
|
||||
Scott Lessans <slessans@gmail.com>
|
||||
Sergey Lukjanov <me@slukjanov.name>
|
||||
Simon Josefsson <simon@josefsson.org>
|
||||
sio2boss <sio2boss@users.noreply.github.com>
|
||||
Wayne Ashley Berry <wayneashleyberry@gmail.com>
|
||||
santosh653 <70637961+santosh653@users.noreply.github.com>
|
||||
|
||||
31
vendor/github.com/kevinburke/ssh_config/CHANGELOG.md
generated
vendored
31
vendor/github.com/kevinburke/ssh_config/CHANGELOG.md
generated
vendored
@@ -1,7 +1,34 @@
|
||||
# Changes
|
||||
|
||||
## Version 1.2
|
||||
## Unreleased
|
||||
|
||||
- Implement Match support. Most of the Match spec is implemented, including
|
||||
`Match host`, `Match originalhost`, `Match user`, `Match localuser`, and `Match
|
||||
all`. `Match exec` is not yet implemented.
|
||||
|
||||
- Add SECURITY.md
|
||||
|
||||
- Add Dependabot configuration
|
||||
|
||||
## Version 1.4 (released August 19, 2025)
|
||||
|
||||
- Remove .gitattributes file (which was used to test different line endings, and
|
||||
caused issues in some build environments). Store tests/dos-lines as CRLF in git
|
||||
directly instead.
|
||||
|
||||
## Version 1.3 (released February 20, 2025)
|
||||
|
||||
- Add go.mod file (although this project has no dependencies).
|
||||
|
||||
- config: add UserSettings.ConfigFinder
|
||||
|
||||
- Various updates to CI and build environment
|
||||
|
||||
## Version 1.2 (released March 31, 2022)
|
||||
|
||||
- config: add DecodeBytes to directly read a byte array.
|
||||
|
||||
- Strip trailing whitespace from Host declarations and key/value pairs.
|
||||
Previously, if a Host declaration or a value had trailing whitespace, that
|
||||
whitespace would have been included as part of the value. This led to unexpected
|
||||
consequences. For example:
|
||||
@@ -17,3 +44,5 @@ unintuitive.
|
||||
|
||||
Instead, we strip the trailing whitespace in the configuration, which leads to
|
||||
more intuitive behavior.
|
||||
|
||||
- Add fuzz tests.
|
||||
|
||||
16
vendor/github.com/kevinburke/ssh_config/Makefile
generated
vendored
16
vendor/github.com/kevinburke/ssh_config/Makefile
generated
vendored
@@ -1,21 +1,21 @@
|
||||
BUMP_VERSION := $(GOPATH)/bin/bump_version
|
||||
STATICCHECK := $(GOPATH)/bin/staticcheck
|
||||
WRITE_MAILMAP := $(GOPATH)/bin/write_mailmap
|
||||
|
||||
$(STATICCHECK):
|
||||
go get honnef.co/go/tools/cmd/staticcheck
|
||||
|
||||
lint: $(STATICCHECK)
|
||||
lint:
|
||||
go vet ./...
|
||||
$(STATICCHECK)
|
||||
go run honnef.co/go/tools/cmd/staticcheck@latest ./...
|
||||
|
||||
test: lint
|
||||
test:
|
||||
@# the timeout helps guard against infinite recursion
|
||||
go test -timeout=250ms ./...
|
||||
|
||||
race-test: lint
|
||||
race-test:
|
||||
go test -timeout=500ms -race ./...
|
||||
|
||||
coverage:
|
||||
go test -trimpath -timeout=250ms -coverprofile=coverage.out -covermode=atomic ./...
|
||||
go tool cover -func=coverage.out
|
||||
|
||||
$(BUMP_VERSION):
|
||||
go get -u github.com/kevinburke/bump_version
|
||||
|
||||
|
||||
10
vendor/github.com/kevinburke/ssh_config/README.md
generated
vendored
10
vendor/github.com/kevinburke/ssh_config/README.md
generated
vendored
@@ -82,11 +82,11 @@ file format.
|
||||
[blog]: https://kev.inburke.com/kevin/more-comment-preserving-configuration-parsers/
|
||||
[hostsfile]: https://github.com/kevinburke/hostsfile
|
||||
|
||||
## Donating
|
||||
## Sponsorships
|
||||
|
||||
I don't get paid to maintain this project. Donations free up time to make
|
||||
improvements to the library, and respond to bug reports. You can send donations
|
||||
via Paypal's "Send Money" feature to kev@inburke.com. Donations are not tax
|
||||
deductible in the USA.
|
||||
Thank you very much to Tailscale and Indeed for sponsoring development of this
|
||||
library. [Sponsors][sponsors] will get their names featured in the README.
|
||||
|
||||
You can also reach out about a consulting engagement: https://burke.services
|
||||
|
||||
[sponsors]: https://github.com/sponsors/kevinburke
|
||||
|
||||
63
vendor/github.com/kevinburke/ssh_config/SECURITY.md
generated
vendored
Normal file
63
vendor/github.com/kevinburke/ssh_config/SECURITY.md
generated
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
# ssh_config security policy
|
||||
|
||||
## Supported Versions
|
||||
|
||||
As of September 2025, we're not aware of any security problems with ssh_config,
|
||||
past or present. That said, we recommend always using the latest version of
|
||||
ssh_config, and of the Go programming language, to ensure you have the most
|
||||
recent security fixes.
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
We take security vulnerabilities seriously. If you discover a security vulnerability in ssh_config, please report it responsibly by following these steps:
|
||||
|
||||
### How to Report
|
||||
|
||||
Please follow the instructions outlined here to report a vulnerability
|
||||
privately: https://docs.github.com/en/code-security/security-advisories/guidance-on-reporting-and-writing-information-about-vulnerabilities/privately-reporting-a-security-vulnerability
|
||||
|
||||
If these are insufficient - it is not hard to find Kevin's contact information
|
||||
on the Internet.
|
||||
|
||||
### What to Include
|
||||
|
||||
When reporting a vulnerability, please include a clear description of the vulnerability, steps to reproduce the issue, the potential impact, as well as any fixes you might have.
|
||||
|
||||
### Response Timeline
|
||||
|
||||
I'll try to acknowledge and patch the issue as quickly as possible.
|
||||
|
||||
Security advisories for this project will be published through:
|
||||
- GitHub Security Advisories on this repository
|
||||
- an Issue on this repository
|
||||
- The project's release notes
|
||||
- Go vulnerability databases
|
||||
|
||||
If you are using `ssh_config` and would like to be on a "pre-release"
|
||||
distribution list for coordinating releases, please contact Kevin directly.
|
||||
|
||||
### Security Considerations
|
||||
|
||||
When using ssh_config, please be aware of these security considerations.
|
||||
|
||||
#### File System Access
|
||||
|
||||
This library reads SSH configuration files from the file system. Try to ensure
|
||||
proper file permissions on SSH config files (typically 600 or 644), and be
|
||||
cautious when parsing config files from untrusted sources.
|
||||
|
||||
#### Input Validation
|
||||
|
||||
The parser handles user-provided SSH configuration data. While we try our best
|
||||
to parse the data appropriately, malformed configuration files could potentially
|
||||
cause issues. Please try to validate and sanitize any configuration data from
|
||||
external sources.
|
||||
|
||||
#### Dependencies
|
||||
|
||||
This project does not have any third party dependencies. Please try to keep your
|
||||
Go version up to date.
|
||||
|
||||
## Acknowledgments
|
||||
|
||||
We appreciate security researchers and users who responsibly disclose vulnerabilities. Contributors who report valid security issues will be acknowledged in our security advisories (unless they prefer to remain anonymous).
|
||||
101
vendor/github.com/kevinburke/ssh_config/config.go
generated
vendored
101
vendor/github.com/kevinburke/ssh_config/config.go
generated
vendored
@@ -8,7 +8,7 @@
|
||||
// the host name to match on ("example.com"), and the second argument is the key
|
||||
// you want to retrieve ("Port"). The keywords are case insensitive.
|
||||
//
|
||||
// port := ssh_config.Get("myhost", "Port")
|
||||
// port := ssh_config.Get("myhost", "Port")
|
||||
//
|
||||
// You can also manipulate an SSH config file and then print it or write it back
|
||||
// to disk.
|
||||
@@ -24,9 +24,6 @@
|
||||
//
|
||||
// // Write the cfg back to disk:
|
||||
// fmt.Println(cfg.String())
|
||||
//
|
||||
// BUG: the Match directive is currently unsupported; parsing a config with
|
||||
// a Match directive will trigger an error.
|
||||
package ssh_config
|
||||
|
||||
import (
|
||||
@@ -43,7 +40,7 @@ import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
const version = "1.2"
|
||||
const version = "1.5.0"
|
||||
|
||||
var _ = version
|
||||
|
||||
@@ -53,6 +50,8 @@ type configFinder func() string
|
||||
// files are parsed and cached the first time Get() or GetStrict() is called.
|
||||
type UserSettings struct {
|
||||
IgnoreErrors bool
|
||||
customConfig *Config
|
||||
customConfigFinder configFinder
|
||||
systemConfig *Config
|
||||
systemConfigFinder configFinder
|
||||
userConfig *Config
|
||||
@@ -203,6 +202,13 @@ func (u *UserSettings) GetStrict(alias, key string) (string, error) {
|
||||
if u.onceErr != nil && u.IgnoreErrors == false {
|
||||
return "", u.onceErr
|
||||
}
|
||||
// TODO this is getting repetitive
|
||||
if u.customConfig != nil {
|
||||
val, err := findVal(u.customConfig, alias, key)
|
||||
if err != nil || val != "" {
|
||||
return val, err
|
||||
}
|
||||
}
|
||||
val, err := findVal(u.userConfig, alias, key)
|
||||
if err != nil || val != "" {
|
||||
return val, err
|
||||
@@ -228,6 +234,12 @@ func (u *UserSettings) GetAllStrict(alias, key string) ([]string, error) {
|
||||
if u.onceErr != nil && u.IgnoreErrors == false {
|
||||
return nil, u.onceErr
|
||||
}
|
||||
if u.customConfig != nil {
|
||||
val, err := findAll(u.customConfig, alias, key)
|
||||
if err != nil || val != nil {
|
||||
return val, err
|
||||
}
|
||||
}
|
||||
val, err := findAll(u.userConfig, alias, key)
|
||||
if err != nil || val != nil {
|
||||
return val, err
|
||||
@@ -243,16 +255,38 @@ func (u *UserSettings) GetAllStrict(alias, key string) ([]string, error) {
|
||||
return []string{}, nil
|
||||
}
|
||||
|
||||
// ConfigFinder will invoke f to try to find a ssh config file in a custom
|
||||
// location on disk, instead of in /etc/ssh or $HOME/.ssh. f should return the
|
||||
// name of a file containing SSH configuration.
|
||||
//
|
||||
// ConfigFinder must be invoked before any calls to Get or GetStrict and panics
|
||||
// if f is nil. Most users should not need to use this function.
|
||||
func (u *UserSettings) ConfigFinder(f func() string) {
|
||||
if f == nil {
|
||||
panic("cannot call ConfigFinder with nil function")
|
||||
}
|
||||
u.customConfigFinder = f
|
||||
}
|
||||
|
||||
func (u *UserSettings) doLoadConfigs() {
|
||||
u.loadConfigs.Do(func() {
|
||||
// can't parse user file, that's ok.
|
||||
var filename string
|
||||
var err error
|
||||
if u.customConfigFinder != nil {
|
||||
filename = u.customConfigFinder()
|
||||
u.customConfig, err = parseFile(filename)
|
||||
// IsNotExist should be returned because a user specified this
|
||||
// function - not existing likely means they made an error
|
||||
if err != nil {
|
||||
u.onceErr = err
|
||||
}
|
||||
return
|
||||
}
|
||||
if u.userConfigFinder == nil {
|
||||
filename = userConfigFinder()
|
||||
} else {
|
||||
filename = u.userConfigFinder()
|
||||
}
|
||||
var err error
|
||||
u.userConfig, err = parseFile(filename)
|
||||
//lint:ignore S1002 I prefer it this way
|
||||
if err != nil && os.IsNotExist(err) == false {
|
||||
@@ -351,9 +385,6 @@ func (c *Config) Get(alias, key string) (string, error) {
|
||||
case *KV:
|
||||
// "keys are case insensitive" per the spec
|
||||
lkey := strings.ToLower(t.Key)
|
||||
if lkey == "match" {
|
||||
panic("can't handle Match directives")
|
||||
}
|
||||
if lkey == lowerKey {
|
||||
return t.Value, nil
|
||||
}
|
||||
@@ -386,9 +417,6 @@ func (c *Config) GetAll(alias, key string) ([]string, error) {
|
||||
case *KV:
|
||||
// "keys are case insensitive" per the spec
|
||||
lkey := strings.ToLower(t.Key)
|
||||
if lkey == "match" {
|
||||
panic("can't handle Match directives")
|
||||
}
|
||||
if lkey == lowerKey {
|
||||
all = append(all, t.Value)
|
||||
}
|
||||
@@ -433,6 +461,9 @@ type Pattern struct {
|
||||
|
||||
// String prints the string representation of the pattern.
|
||||
func (p Pattern) String() string {
|
||||
if p.not {
|
||||
return "!" + p.str
|
||||
}
|
||||
return p.str
|
||||
}
|
||||
|
||||
@@ -491,7 +522,7 @@ func NewPattern(s string) (*Pattern, error) {
|
||||
return &Pattern{str: s, regex: r, not: negated}, nil
|
||||
}
|
||||
|
||||
// Host describes a Host directive and the keywords that follow it.
|
||||
// Host describes a Host or Match directive and the keywords that follow it.
|
||||
type Host struct {
|
||||
// A list of host patterns that should match this host.
|
||||
Patterns []*Pattern
|
||||
@@ -506,6 +537,11 @@ type Host struct {
|
||||
leadingSpace int // TODO: handle spaces vs tabs here.
|
||||
// The file starts with an implicit "Host *" declaration.
|
||||
implicit bool
|
||||
// isMatch is true if this block was created by a Match directive.
|
||||
isMatch bool
|
||||
// matchKeyword stores the original text after "Match" (e.g. "Host" or
|
||||
// "all") so we can round-trip correctly.
|
||||
matchKeyword string
|
||||
}
|
||||
|
||||
// Matches returns true if the Host matches for the given alias. For
|
||||
@@ -537,17 +573,36 @@ func (h *Host) String() string {
|
||||
//lint:ignore S1002 I prefer to write it this way
|
||||
if h.implicit == false {
|
||||
buf.WriteString(strings.Repeat(" ", int(h.leadingSpace)))
|
||||
buf.WriteString("Host")
|
||||
if h.hasEquals {
|
||||
buf.WriteString(" = ")
|
||||
} else {
|
||||
buf.WriteString(" ")
|
||||
}
|
||||
for i, pat := range h.Patterns {
|
||||
buf.WriteString(pat.String())
|
||||
if i < len(h.Patterns)-1 {
|
||||
if h.isMatch {
|
||||
buf.WriteString("Match")
|
||||
if h.hasEquals {
|
||||
buf.WriteString(" = ")
|
||||
} else {
|
||||
buf.WriteString(" ")
|
||||
}
|
||||
buf.WriteString(h.matchKeyword)
|
||||
if !strings.EqualFold(h.matchKeyword, "all") {
|
||||
buf.WriteString(" ")
|
||||
for i, pat := range h.Patterns {
|
||||
buf.WriteString(pat.String())
|
||||
if i < len(h.Patterns)-1 {
|
||||
buf.WriteString(" ")
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
buf.WriteString("Host")
|
||||
if h.hasEquals {
|
||||
buf.WriteString(" = ")
|
||||
} else {
|
||||
buf.WriteString(" ")
|
||||
}
|
||||
for i, pat := range h.Patterns {
|
||||
buf.WriteString(pat.String())
|
||||
if i < len(h.Patterns)-1 {
|
||||
buf.WriteString(" ")
|
||||
}
|
||||
}
|
||||
}
|
||||
buf.WriteString(h.spaceBeforeComment)
|
||||
if h.EOLComment != "" {
|
||||
|
||||
79
vendor/github.com/kevinburke/ssh_config/parser.go
generated
vendored
79
vendor/github.com/kevinburke/ssh_config/parser.go
generated
vendored
@@ -21,9 +21,9 @@ type sshParser struct {
|
||||
type sshParserStateFn func() sshParserStateFn
|
||||
|
||||
// Formats and panics an error message based on a token
|
||||
func (p *sshParser) raiseErrorf(tok *token, msg string, args ...interface{}) {
|
||||
func (p *sshParser) raiseErrorf(tok *token, msg string) {
|
||||
// TODO this format is ugly
|
||||
panic(tok.Position.String() + ": " + fmt.Sprintf(msg, args...))
|
||||
panic(tok.Position.String() + ": " + msg)
|
||||
}
|
||||
|
||||
func (p *sshParser) raiseError(tok *token, err error) {
|
||||
@@ -105,9 +105,7 @@ func (p *sshParser) parseKV() sshParserStateFn {
|
||||
comment = tok.val
|
||||
}
|
||||
if strings.ToLower(key.val) == "match" {
|
||||
// https://github.com/kevinburke/ssh_config/issues/6
|
||||
p.raiseErrorf(val, "ssh_config: Match directive parsing is unsupported")
|
||||
return nil
|
||||
return p.parseMatch(val, hasEquals, comment)
|
||||
}
|
||||
if strings.ToLower(key.val) == "host" {
|
||||
strPatterns := strings.Split(val.val, " ")
|
||||
@@ -118,7 +116,7 @@ func (p *sshParser) parseKV() sshParserStateFn {
|
||||
}
|
||||
pat, err := NewPattern(strPatterns[i])
|
||||
if err != nil {
|
||||
p.raiseErrorf(val, "Invalid host pattern: %v", err)
|
||||
p.raiseErrorf(val, fmt.Sprintf("Invalid host pattern: %v", err))
|
||||
return nil
|
||||
}
|
||||
patterns = append(patterns, pat)
|
||||
@@ -144,7 +142,7 @@ func (p *sshParser) parseKV() sshParserStateFn {
|
||||
return nil
|
||||
}
|
||||
if err != nil {
|
||||
p.raiseErrorf(val, "Error parsing Include directive: %v", err)
|
||||
p.raiseErrorf(val, fmt.Sprintf("Error parsing Include directive: %v", err))
|
||||
return nil
|
||||
}
|
||||
lastHost.Nodes = append(lastHost.Nodes, inc)
|
||||
@@ -165,6 +163,73 @@ func (p *sshParser) parseKV() sshParserStateFn {
|
||||
return p.parseStart
|
||||
}
|
||||
|
||||
func (p *sshParser) parseMatch(val *token, hasEquals bool, comment string) sshParserStateFn {
|
||||
// val.val contains everything after "Match ", e.g. "Host *.example.com"
|
||||
// or "all".
|
||||
trimmed := strings.TrimRightFunc(val.val, unicode.IsSpace)
|
||||
spaceBeforeComment := val.val[len(trimmed):]
|
||||
fields := strings.Fields(trimmed)
|
||||
if len(fields) == 0 {
|
||||
p.raiseErrorf(val, "ssh_config: Match directive requires at least one criterion")
|
||||
return nil
|
||||
}
|
||||
criterion := strings.ToLower(fields[0])
|
||||
|
||||
switch criterion {
|
||||
case "all":
|
||||
// "Match all" is equivalent to "Host *" — matches everything.
|
||||
p.config.Hosts = append(p.config.Hosts, &Host{
|
||||
Patterns: []*Pattern{matchAll},
|
||||
Nodes: make([]Node, 0),
|
||||
EOLComment: comment,
|
||||
spaceBeforeComment: spaceBeforeComment,
|
||||
hasEquals: hasEquals,
|
||||
isMatch: true,
|
||||
matchKeyword: fields[0], // preserve original case
|
||||
})
|
||||
return p.parseStart
|
||||
|
||||
case "host":
|
||||
patterns := make([]*Pattern, 0)
|
||||
for _, s := range fields[1:] {
|
||||
if s == "" {
|
||||
continue
|
||||
}
|
||||
pat, err := NewPattern(s)
|
||||
if err != nil {
|
||||
p.raiseErrorf(val, fmt.Sprintf("Invalid host pattern: %v", err))
|
||||
return nil
|
||||
}
|
||||
patterns = append(patterns, pat)
|
||||
}
|
||||
if len(patterns) == 0 {
|
||||
p.raiseErrorf(val, "ssh_config: Match Host requires at least one pattern")
|
||||
return nil
|
||||
}
|
||||
p.config.Hosts = append(p.config.Hosts, &Host{
|
||||
Patterns: patterns,
|
||||
Nodes: make([]Node, 0),
|
||||
EOLComment: comment,
|
||||
spaceBeforeComment: spaceBeforeComment,
|
||||
hasEquals: hasEquals,
|
||||
isMatch: true,
|
||||
matchKeyword: fields[0], // preserve original case
|
||||
})
|
||||
return p.parseStart
|
||||
|
||||
case "exec":
|
||||
// Match Exec runs arbitrary commands. Supporting it would allow
|
||||
// untrusted SSH config files to execute code on the parsing
|
||||
// machine. Reject it explicitly.
|
||||
p.raiseErrorf(val, "ssh_config: Match Exec is not supported")
|
||||
return nil
|
||||
|
||||
default:
|
||||
p.raiseErrorf(val, fmt.Sprintf("ssh_config: unsupported Match criterion %q", criterion))
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (p *sshParser) parseComment() sshParserStateFn {
|
||||
comment := p.getToken()
|
||||
lastHost := p.config.Hosts[len(p.config.Hosts)-1]
|
||||
|
||||
Reference in New Issue
Block a user