@searls/turbocommit 0.11.0 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/redact.js +156 -0
- package/lib/run.js +6 -2
- package/package.json +1 -1
package/lib/redact.js
ADDED
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
const SAFE_NAMES = new Set([
|
|
2
|
+
// Shell / OS
|
|
3
|
+
'HOME', 'USER', 'SHELL', 'PATH', 'PWD', 'OLDPWD', 'LANG', 'TERM',
|
|
4
|
+
'EDITOR', 'VISUAL', 'PAGER', 'HOSTNAME', 'LOGNAME', 'DISPLAY', 'TZ',
|
|
5
|
+
'TMPDIR', 'SHLVL', '_', 'BROWSER', 'COMMAND_MODE', 'COLUMNS', 'LINES',
|
|
6
|
+
'MANPATH', 'INFOPATH',
|
|
7
|
+
|
|
8
|
+
// Terminal
|
|
9
|
+
'COLORTERM', 'TERM_PROGRAM', 'TERM_PROGRAM_VERSION', 'TERM_SESSION_ID',
|
|
10
|
+
'ITERM_SESSION_ID', 'ITERM_PROFILE', 'APPLE_TERMINAL_ID',
|
|
11
|
+
|
|
12
|
+
// Locale
|
|
13
|
+
'LC_ALL', 'LC_COLLATE', 'LC_CTYPE', 'LC_MESSAGES', 'LC_MONETARY',
|
|
14
|
+
'LC_NUMERIC', 'LC_TIME',
|
|
15
|
+
|
|
16
|
+
// XDG
|
|
17
|
+
'XDG_DATA_HOME', 'XDG_CONFIG_HOME', 'XDG_STATE_HOME', 'XDG_CACHE_HOME',
|
|
18
|
+
'XDG_RUNTIME_DIR', 'XDG_DATA_DIRS', 'XDG_CONFIG_DIRS', 'XDG_SESSION_TYPE',
|
|
19
|
+
'XDG_CURRENT_DESKTOP', 'XDG_SESSION_CLASS', 'XDG_SESSION_ID', 'XDG_SEAT',
|
|
20
|
+
'XDG_VTNR', 'XDG_MENU_PREFIX',
|
|
21
|
+
|
|
22
|
+
// Dev environment
|
|
23
|
+
'NODE_ENV', 'RAILS_ENV', 'RACK_ENV', 'GO_ENV', 'MIX_ENV', 'FLASK_ENV',
|
|
24
|
+
'DEBUG', 'VERBOSE', 'LOG_LEVEL', 'PORT', 'HOST', 'CI',
|
|
25
|
+
'NVM_DIR', 'NVM_BIN', 'NVM_INC', 'NVM_CD_FLAGS',
|
|
26
|
+
'VOLTA_HOME', 'HOMEBREW_PREFIX', 'HOMEBREW_CELLAR', 'HOMEBREW_REPOSITORY',
|
|
27
|
+
'HOMEBREW_SHELLENV_PREFIX',
|
|
28
|
+
|
|
29
|
+
// SSH / GPG (socket paths, not keys)
|
|
30
|
+
'SSH_AUTH_SOCK', 'SSH_AGENT_PID', 'GPG_AGENT_INFO', 'GPG_TTY',
|
|
31
|
+
|
|
32
|
+
// Git
|
|
33
|
+
'GIT_EDITOR', 'GIT_PAGER', 'GIT_TERMINAL_PROMPT'
|
|
34
|
+
])
|
|
35
|
+
|
|
36
|
+
// Values that are common English words, config toggles, or well-known
|
|
37
|
+
// non-secret defaults. Checked case-insensitively.
|
|
38
|
+
const SAFE_VALUES = new Set([
|
|
39
|
+
// Boolean-like
|
|
40
|
+
'true', 'false', 'yes', 'no', 'on', 'off',
|
|
41
|
+
|
|
42
|
+
// Environment modes
|
|
43
|
+
'development', 'production', 'staging', 'test', 'testing',
|
|
44
|
+
'dev', 'prod', 'local', 'ci', 'qa', 'sandbox', 'preview',
|
|
45
|
+
'canary', 'demo', 'benchmark', 'profile', 'uat', 'integration',
|
|
46
|
+
'preprod', 'pre-production', 'stage', 'deployment',
|
|
47
|
+
|
|
48
|
+
// Log levels
|
|
49
|
+
'trace', 'debug', 'info', 'warn', 'warning', 'error', 'fatal',
|
|
50
|
+
'critical', 'notice', 'verbose', 'silent', 'quiet', 'off',
|
|
51
|
+
|
|
52
|
+
// Common toggles/modes
|
|
53
|
+
'enabled', 'disabled', 'always', 'never', 'auto', 'default',
|
|
54
|
+
'manual', 'none', 'null', 'undefined', 'inherit', 'unset',
|
|
55
|
+
'strict', 'lax', 'permissive', 'enforcing', 'noninteractive',
|
|
56
|
+
|
|
57
|
+
// Editors, pagers, browsers (bare names)
|
|
58
|
+
'vim', 'vi', 'nano', 'emacs', 'nvim', 'code', 'subl', 'mate',
|
|
59
|
+
'micro', 'ed', 'pico', 'gedit', 'kate', 'hx', 'kak', 'kakoune',
|
|
60
|
+
'joe', 'emacsclient', 'less', 'more', 'most', 'cat',
|
|
61
|
+
'open', 'firefox', 'chromium', 'links', 'lynx', 'w3m', 'safari', 'opera',
|
|
62
|
+
|
|
63
|
+
// Common English words that appear as env values
|
|
64
|
+
'allow', 'deny', 'block', 'drop', 'accept', 'reject',
|
|
65
|
+
'public', 'private', 'master', 'main', 'release',
|
|
66
|
+
'read', 'write', 'root', 'latest', 'stable', 'edge',
|
|
67
|
+
'screen', 'random', 'node', 'ruby', 'python', 'go', 'java',
|
|
68
|
+
'rust', 'php', 'slim', 'alpine',
|
|
69
|
+
'localhost',
|
|
70
|
+
|
|
71
|
+
// Platform/architecture identifiers
|
|
72
|
+
'linux', 'darwin', 'win32', 'windows', 'freebsd', 'openbsd',
|
|
73
|
+
'netbsd', 'sunos', 'aix', 'android', 'cygwin', 'msys',
|
|
74
|
+
'x86_64', 'amd64', 'x64', 'arm64', 'aarch64', 'i386', 'i686',
|
|
75
|
+
'ia32', 'armv7l', 'arm', 'ppc64le', 's390x', 'riscv64',
|
|
76
|
+
|
|
77
|
+
// TERM values
|
|
78
|
+
'xterm', 'xterm-256color', 'xterm-color', 'xterm-16color',
|
|
79
|
+
'screen', 'screen-256color', 'tmux', 'tmux-256color',
|
|
80
|
+
'linux', 'vt100', 'vt220', 'dumb', 'ansi', 'rxvt',
|
|
81
|
+
'rxvt-unicode', 'rxvt-unicode-256color', 'alacritty', 'kitty',
|
|
82
|
+
'wezterm', 'eterm-color', 'foot', 'foot-extra',
|
|
83
|
+
'gnome-256color', 'konsole-256color', 'st-256color',
|
|
84
|
+
'putty', 'putty-256color',
|
|
85
|
+
|
|
86
|
+
// COLORTERM
|
|
87
|
+
'truecolor', '24bit',
|
|
88
|
+
|
|
89
|
+
// TERM_PROGRAM
|
|
90
|
+
'apple_terminal', 'iterm.app', 'vscode', 'hyper',
|
|
91
|
+
|
|
92
|
+
// Docker/CI identifiers
|
|
93
|
+
'bullseye', 'bookworm', 'jammy', 'lts',
|
|
94
|
+
'travis-ci', 'circleci', 'codeship', 'github-actions',
|
|
95
|
+
'gitlab-ci', 'jenkins', 'buildkite',
|
|
96
|
+
|
|
97
|
+
// System users
|
|
98
|
+
'nobody', 'www-data', 'daemon', 'nonroot', 'appuser',
|
|
99
|
+
'nginx', 'postgres', 'mysql', 'redis',
|
|
100
|
+
|
|
101
|
+
// XDG session types
|
|
102
|
+
'x11', 'wayland', 'tty',
|
|
103
|
+
|
|
104
|
+
// Metasyntactic / genuinely-never-a-credential values
|
|
105
|
+
'todo', 'fixme', 'tbd', 'n/a',
|
|
106
|
+
'xxx', 'yyy', 'zzz', 'foo', 'bar', 'baz',
|
|
107
|
+
'lorem', 'temp', 'tmp', 'blah'
|
|
108
|
+
])
|
|
109
|
+
|
|
110
|
+
// Pattern-based rules for values that match known non-secret formats
|
|
111
|
+
const SAFE_VALUE_PATTERNS = [
|
|
112
|
+
/^\d+$/, // pure numeric
|
|
113
|
+
/^(.)\1+$/, // repeated single char (xxxx, ****, ....)
|
|
114
|
+
/^\d+\.\d+\.\d+(-[\w.]+)?$/, // semver (18.17.1, 1.0.0-beta.1)
|
|
115
|
+
/^[a-z]{2}_[A-Z]{2}([.\w-]*)?$/, // locale (en_US.UTF-8)
|
|
116
|
+
/^(C|POSIX)(\.UTF-8)?$/, // C/POSIX locale
|
|
117
|
+
/^[A-Z][a-z]+\/[A-Za-z_]+$/, // timezone (America/New_York)
|
|
118
|
+
/^(UTC|Etc\/UTC|US\/\w+)$/, // timezone shorthand
|
|
119
|
+
/^\/[a-z][\w/.-]*$/, // unix path (/usr/local/bin)
|
|
120
|
+
/^(https?|redis|mongodb|postgres(ql)?|mysql|amqp|smtp|memcached|elasticsearch):\/\/(localhost|127\.0\.0\.1|0\.0\.0\.0|::1)/, // localhost URLs
|
|
121
|
+
/^(xterm|screen|tmux|linux|vt\d+|dumb|ansi|rxvt|alacritty|kitty|wezterm|foot)(-[\w]+)*$/, // TERM identifiers
|
|
122
|
+
/^(localhost)?:\d+(\.\d+)?$/, // X11 DISPLAY (:0, :0.0)
|
|
123
|
+
/^wayland-\d+$/, // Wayland display
|
|
124
|
+
/^sqlite:(\/\/\/)?(:\w+:|[\w./]+)$/ // sqlite URLs
|
|
125
|
+
]
|
|
126
|
+
|
|
127
|
+
function isSafeValue (value) {
|
|
128
|
+
if (!value || value.length <= 3) return true
|
|
129
|
+
if (SAFE_VALUES.has(value.toLowerCase())) return true
|
|
130
|
+
for (const pattern of SAFE_VALUE_PATTERNS) {
|
|
131
|
+
if (pattern.test(value)) return true
|
|
132
|
+
}
|
|
133
|
+
return false
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function buildRedactions (env) {
|
|
137
|
+
env = env || process.env
|
|
138
|
+
const entries = []
|
|
139
|
+
for (const [name, value] of Object.entries(env)) {
|
|
140
|
+
if (SAFE_NAMES.has(name)) continue
|
|
141
|
+
if (isSafeValue(value)) continue
|
|
142
|
+
entries.push({ name, value })
|
|
143
|
+
}
|
|
144
|
+
entries.sort((a, b) => b.value.length - a.value.length)
|
|
145
|
+
return entries
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function redact (text, redactions) {
|
|
149
|
+
if (!text) return text
|
|
150
|
+
for (const { name, value } of redactions) {
|
|
151
|
+
text = text.replaceAll(value, '[REDACTED:' + name + ']')
|
|
152
|
+
}
|
|
153
|
+
return text
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
module.exports = { buildRedactions, redact }
|
package/lib/run.js
CHANGED
|
@@ -8,6 +8,7 @@ const { gitRoot, hasChanges, addAndCommit, hasCommits, currentBranch, pushClean
|
|
|
8
8
|
const { logEvent } = require('./log')
|
|
9
9
|
const { wrapText } = require('./wrap')
|
|
10
10
|
const { hasTrackedModifications, cleanupTracking } = require('./track')
|
|
11
|
+
const { redact, buildRedactions } = require('./redact')
|
|
11
12
|
const { getAncestors, savePending, collectPending, cleanupConsumed, cleanupStale, readWatermark, saveWatermark, resolveParentCommit } = require('./session')
|
|
12
13
|
|
|
13
14
|
/**
|
|
@@ -187,9 +188,12 @@ function run (input) {
|
|
|
187
188
|
const coauthor = resolveCoauthor(config, hookInput.transcript_path, root)
|
|
188
189
|
const tag = coauthor ? '\n\n' + coauthor : ''
|
|
189
190
|
|
|
190
|
-
const
|
|
191
|
+
const redactions = buildRedactions()
|
|
192
|
+
const safeHeadline = redact(headline, redactions)
|
|
193
|
+
const safeBody = redact(wrappedBody + tag, redactions)
|
|
194
|
+
const sha = addAndCommit(root, safeHeadline, safeBody)
|
|
191
195
|
|
|
192
|
-
logEvent('success', { project, branch, context, title:
|
|
196
|
+
logEvent('success', { project, branch, context, title: safeHeadline })
|
|
193
197
|
|
|
194
198
|
if (config.push === true) {
|
|
195
199
|
if (pushClean(root)) {
|