Read a lowercase name with digits as a name, not a secret (issue 1439)
mesh/repo-check head 7bf4a8053a49 merged into trunk 36d6f7745c8d — pass: its merge-check.sh passed, each part in its toolchain: merge-check.sh (typescript)…
mesh/merge-gate head 7bf4a8053a49 merged into trunk 36d6f7745c8d — pass: group feat/1439-name-runs composed: every machine composes with the change as it d…
mesh/delivery delivered
mesh/delivery-group group feat/1439-name-runs delivered: every member is delivered
mesh/repo-check head 7bf4a8053a49 merged into trunk 36d6f7745c8d — pass: its merge-check.sh passed, each part in its toolchain: merge-check.sh (typescript)…
mesh/merge-gate head 7bf4a8053a49 merged into trunk 36d6f7745c8d — pass: group feat/1439-name-runs composed: every machine composes with the change as it d…
mesh/delivery delivered
mesh/delivery-group group feat/1439-name-runs delivered: every member is delivered
mesh-config refused to propose mesh-issues' owners because CheckSecret took modules/asus-zephyrus-g14, i3status-rust and powerlevel10k for random strings: a run with a digit in it was judged whole. A run of lowercase letters and digits in short pieces between -, _ and / is now judged piece by piece; a capital letter or a piece of 20 or more is judged whole as before.
This commit is contained in:
+26
-2
@@ -48,6 +48,8 @@ var (
|
||||
reURLCredential = regexp.MustCompile(`(?i)\b[a-z][a-z0-9+.-]*://[^/\s:@]+:[^/\s@]+@`)
|
||||
// reSecretRun is a run CheckSecret judges: reRun with `-`, so a base64url value is judged whole.
|
||||
reSecretRun = regexp.MustCompile(`[A-Za-z0-9+/=_-]{20,}`)
|
||||
// reLowerName is a run written as a name is: lowercase letters, digits, and `-`, `_` or `/` between them.
|
||||
reLowerName = regexp.MustCompile(`^[a-z0-9]+([-_/][a-z0-9]+)*$`)
|
||||
reUUID = regexp.MustCompile(`^(?i)[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$`)
|
||||
reHex = regexp.MustCompile(`(?i)\b[0-9a-f]{32,}\b`)
|
||||
reRun = regexp.MustCompile(`[A-Za-z0-9+/=_]{20,}`)
|
||||
@@ -138,8 +140,10 @@ func randomRunOutsidePaths(text string) (Refusal, bool) {
|
||||
pieces = strings.Split(seg, "/")
|
||||
}
|
||||
for _, piece := range pieces {
|
||||
if len(piece) >= 20 && !reUUID.MatchString(piece) && looksRandomValue(piece) {
|
||||
return Refusal{"secret", "a long random-looking string"}, false
|
||||
for _, part := range nameParts(piece) {
|
||||
if len(part) >= 20 && !reUUID.MatchString(part) && looksRandomValue(part) {
|
||||
return Refusal{"secret", "a long random-looking string"}, false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -147,6 +151,26 @@ func randomRunOutsidePaths(text string) (Refusal, bool) {
|
||||
return Refusal{}, true
|
||||
}
|
||||
|
||||
// nameParts is a run read as a name when it is one: lowercase letters and digits only, in pieces between
|
||||
// `-`, `_` and `/` that are each under 20 long, as a module or repository is named (modules/asus-zephyrus-g14,
|
||||
// i3status-rust: novox/hq issue 1439). Such a run is judged piece by piece, and every piece, being short, is
|
||||
// a word. A run with a capital letter, or a piece of 20 or more, is judged whole, as a token's is.
|
||||
func nameParts(run string) []string {
|
||||
if !reLowerName.MatchString(run) {
|
||||
return []string{run}
|
||||
}
|
||||
parts := strings.FieldsFunc(run, func(r rune) bool { return r == '-' || r == '_' || r == '/' })
|
||||
if len(parts) < 2 {
|
||||
return []string{run}
|
||||
}
|
||||
for _, p := range parts {
|
||||
if len(p) >= 20 {
|
||||
return []string{run}
|
||||
}
|
||||
}
|
||||
return parts
|
||||
}
|
||||
|
||||
// secretShape is the secret shapes a pattern names.
|
||||
func secretShape(text string) (Refusal, bool) {
|
||||
switch {
|
||||
|
||||
@@ -4,8 +4,11 @@ package outward
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
)
|
||||
|
||||
@@ -162,3 +165,45 @@ func TestCheckSecretLetsACamelCaseNameThrough(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 1439/AC1: a name written in lowercase words and digits between `-`, `_` or `/`, every piece short, is a
|
||||
// name and not a secret: mesh-issues' owners list (the catalogue's 134 defaults plus okioki) was refused
|
||||
// whole as "a long random-looking string" for modules/asus-zephyrus-g14, i3status-rust and powerlevel10k.
|
||||
func TestCheckSecretLetsALowercaseNameWithDigitsThrough(t *testing.T) {
|
||||
for _, text := range []string{
|
||||
"mesh-catalog modules/asus-zephyrus-g14",
|
||||
"mesh-catalog modules/i3status-rust",
|
||||
"mesh-catalog modules/powerlevel10k",
|
||||
} {
|
||||
if r, ok := CheckSecret(text); !ok {
|
||||
t.Errorf("CheckSecret(%q) withheld it: %s", text, r)
|
||||
}
|
||||
}
|
||||
raw, err := os.ReadFile(filepath.Join("testdata", "owners-1439.json"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
var owners []string
|
||||
if err := json.Unmarshal(raw, &owners); err != nil || len(owners) != 135 {
|
||||
t.Fatalf("testdata holds %d owners (%v), want the 134 defaults plus okioki", len(owners), err)
|
||||
}
|
||||
compact, _ := json.Marshal(owners)
|
||||
if r, ok := CheckSecret("+ owners: " + string(compact)); !ok {
|
||||
t.Errorf("CheckSecret withheld the owners list: %s", r)
|
||||
}
|
||||
}
|
||||
|
||||
// 1439/AC2: what looks random is still refused: a mixed-case run, a base64url token with `-` and `_`, a
|
||||
// lowercase run of letters and digits with no separator, and a lowercase name with one long random piece.
|
||||
func TestCheckSecretStillRefusesRandomRunsBesideNames(t *testing.T) {
|
||||
for _, text := range []string{
|
||||
"key Zq8vR2mXk4Lp9sTw3nBy7cHd",
|
||||
"token dGhpc0lz-QVNlY3JldC1_Ub2tlbl9XaXRoLUh5cGhlbnM",
|
||||
"key k8s7x2m9q4w1e5r3t6y0u2p9",
|
||||
"modules/k8s7x2m9q4w1e5r3t6y0u2p9-tools",
|
||||
} {
|
||||
if r, ok := CheckSecret(text); ok || r.Class != "secret" {
|
||||
t.Errorf("CheckSecret(%q) let it through (%v)", text, r)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+137
@@ -0,0 +1,137 @@
|
||||
[
|
||||
"hq",
|
||||
"mesh-catalog",
|
||||
"mesh-catalog modules/adwaita",
|
||||
"mesh-catalog modules/artifact-store-tools",
|
||||
"mesh-catalog modules/asus-zephyrus-g14",
|
||||
"mesh-catalog modules/audit-logger",
|
||||
"mesh-catalog modules/avahi",
|
||||
"mesh-catalog modules/baserow",
|
||||
"mesh-catalog modules/betterbird",
|
||||
"mesh-catalog modules/blueman",
|
||||
"mesh-catalog modules/bluetooth",
|
||||
"mesh-catalog modules/ca-trust",
|
||||
"mesh-catalog modules/claude-code",
|
||||
"mesh-catalog modules/claude-licence-manager",
|
||||
"mesh-catalog modules/clipmenu",
|
||||
"mesh-catalog modules/confluence",
|
||||
"mesh-catalog modules/cups",
|
||||
"mesh-catalog modules/dbus",
|
||||
"mesh-catalog modules/desk-channel",
|
||||
"mesh-catalog modules/disk-load",
|
||||
"mesh-catalog modules/distribution",
|
||||
"mesh-catalog modules/dmenu",
|
||||
"mesh-catalog modules/dnsmasq",
|
||||
"mesh-catalog modules/docker",
|
||||
"mesh-catalog modules/docker-compose",
|
||||
"mesh-catalog modules/dunst",
|
||||
"mesh-catalog modules/fail2ban",
|
||||
"mesh-catalog modules/feh",
|
||||
"mesh-catalog modules/flatpak",
|
||||
"mesh-catalog modules/fonts",
|
||||
"mesh-catalog modules/forticlient",
|
||||
"mesh-catalog modules/gitea",
|
||||
"mesh-catalog modules/gitlab",
|
||||
"mesh-catalog modules/gnome-keyring",
|
||||
"mesh-catalog modules/grafana",
|
||||
"mesh-catalog modules/hello-web",
|
||||
"mesh-catalog modules/home-assistant",
|
||||
"mesh-catalog modules/hostname",
|
||||
"mesh-catalog modules/i3",
|
||||
"mesh-catalog modules/i3status-rust",
|
||||
"mesh-catalog modules/icecast",
|
||||
"mesh-catalog modules/influxdb",
|
||||
"mesh-catalog modules/invoicing",
|
||||
"mesh-catalog modules/jira",
|
||||
"mesh-catalog modules/keycloak",
|
||||
"mesh-catalog modules/lab",
|
||||
"mesh-catalog modules/lemurs",
|
||||
"mesh-catalog modules/letta",
|
||||
"mesh-catalog modules/local-model-consumer",
|
||||
"mesh-catalog modules/localization",
|
||||
"mesh-catalog modules/logrotate",
|
||||
"mesh-catalog modules/mailu",
|
||||
"mesh-catalog modules/marrytts",
|
||||
"mesh-catalog modules/matrix",
|
||||
"mesh-catalog modules/memory-pressure",
|
||||
"mesh-catalog modules/mesh-catalog",
|
||||
"mesh-catalog modules/mesh-cli",
|
||||
"mesh-catalog modules/mesh-delivery",
|
||||
"mesh-catalog modules/mesh-delivery-gate",
|
||||
"mesh-catalog modules/mesh-issues",
|
||||
"mesh-catalog modules/mesh-vault",
|
||||
"mesh-catalog modules/mesh-watcher",
|
||||
"mesh-catalog modules/messenger",
|
||||
"mesh-catalog modules/minio",
|
||||
"mesh-catalog modules/model-usage",
|
||||
"mesh-catalog modules/mongodb",
|
||||
"mesh-catalog modules/mosquitto",
|
||||
"mesh-catalog modules/mounts",
|
||||
"mesh-catalog modules/mssql",
|
||||
"mesh-catalog modules/n8n",
|
||||
"mesh-catalog modules/nats",
|
||||
"mesh-catalog modules/netcheck",
|
||||
"mesh-catalog modules/networkmanager",
|
||||
"mesh-catalog modules/nextcloud",
|
||||
"mesh-catalog modules/nextcloud-client",
|
||||
"mesh-catalog modules/nfs-server",
|
||||
"mesh-catalog modules/nftables",
|
||||
"mesh-catalog modules/nm-applet",
|
||||
"mesh-catalog modules/node-env",
|
||||
"mesh-catalog modules/nodered",
|
||||
"mesh-catalog modules/ollama",
|
||||
"mesh-catalog modules/only-office",
|
||||
"mesh-catalog modules/openai-consumer",
|
||||
"mesh-catalog modules/openrazer",
|
||||
"mesh-catalog modules/pacman",
|
||||
"mesh-catalog modules/photos-eef",
|
||||
"mesh-catalog modules/photos-filip",
|
||||
"mesh-catalog modules/picom",
|
||||
"mesh-catalog modules/polychromatic",
|
||||
"mesh-catalog modules/postgres",
|
||||
"mesh-catalog modules/power",
|
||||
"mesh-catalog modules/powerlevel10k",
|
||||
"mesh-catalog modules/records",
|
||||
"mesh-catalog modules/redis",
|
||||
"mesh-catalog modules/restic",
|
||||
"mesh-catalog modules/rofi",
|
||||
"mesh-catalog modules/route-adapter",
|
||||
"mesh-catalog modules/screen-lock",
|
||||
"mesh-catalog modules/searxng",
|
||||
"mesh-catalog modules/sensors",
|
||||
"mesh-catalog modules/showcase",
|
||||
"mesh-catalog modules/slack",
|
||||
"mesh-catalog modules/snapd",
|
||||
"mesh-catalog modules/ssh-client",
|
||||
"mesh-catalog modules/sshd",
|
||||
"mesh-catalog modules/step-ca",
|
||||
"mesh-catalog modules/sudo",
|
||||
"mesh-catalog modules/supabase",
|
||||
"mesh-catalog modules/systemd",
|
||||
"mesh-catalog modules/systemd-networkd",
|
||||
"mesh-catalog modules/systemd-resolved",
|
||||
"mesh-catalog modules/telegram",
|
||||
"mesh-catalog modules/time-sync",
|
||||
"mesh-catalog modules/triggerhappy",
|
||||
"mesh-catalog modules/umami",
|
||||
"mesh-catalog modules/unifi",
|
||||
"mesh-catalog modules/website",
|
||||
"mesh-catalog modules/xclip",
|
||||
"mesh-catalog modules/xdg",
|
||||
"mesh-catalog modules/xorg",
|
||||
"mesh-catalog modules/xterm",
|
||||
"mesh-catalog modules/zfs",
|
||||
"mesh-catalog modules/zsh",
|
||||
"mesh-catalog modules/zsh-autosuggestions",
|
||||
"mesh-catalog modules/zsh-syntax-highlighting",
|
||||
"mesh-controller",
|
||||
"mesh-controller modules/build-agent",
|
||||
"mesh-controller modules/route-proxy",
|
||||
"mesh-delivery",
|
||||
"mesh-host",
|
||||
"mesh-lab",
|
||||
"mesh-media-catalog",
|
||||
"mesh-sdk",
|
||||
"mesh-tools",
|
||||
"okioki"
|
||||
]
|
||||
Reference in New Issue
Block a user