security: scrub live credentials from tracked notes; point values at Vaultwarden
- replace real keys/passwords/tokens/connection strings with {{SECRET_*}}
placeholders across 24 files (review-named 12 + noise-audit finds:
WAQI/Dovecot/GPS/VPN subscriptions/Work runbooks/Plane API key)
- widen verifier: OPENSSH/RSA key headers, hyphenated sk-/prefixed sk-,
credential assignments & table cells, telegram bot tokens, conn strings
- placeholder/default-value/config-name exemptions to kill doc FPs
- skip .obsidian plugin code and frozen Inbox-Clippings from value scan
- GIT_WORKFLOW: no git add ., verifier before commit, force-push exception
- final regression: 0 flagged in tracked scope (was 43)
This commit is contained in:
+18
-10
@@ -5,7 +5,14 @@ import { readFileSync } from 'node:fs'
|
||||
|
||||
// 值形态的占位符 / 环境引用:不算泄漏
|
||||
const PLACEHOLDER =
|
||||
/(\{\{|<[^>]*>|\$\{|process\.env|\benv\[|your[-_]|example|sample|placeholder|changeme|redacted|\bxxx\b|\.\.\.|\[hidden\])/i
|
||||
/(\{\{|<[^>]*>|\$\{|process\.env|\benv\[|\byour|example|sample|placeholder|changeme|change_me|redacted|\bxxx\b|\.\.\.|\[hidden\]|super[_-]?secret|environ|\.\w)/i
|
||||
|
||||
// 公共默认口令:不算泄漏(本地开发默认值)
|
||||
const DEFAULT_VALUES =
|
||||
/^(postgres|hass|litellm|root|changeme|admin|123456)$/i
|
||||
const DEFAULT_SUFFIX = /(?:^|[_-])(?:password|passwd|secret|token|key|config)$/i
|
||||
// 全大写下划线 = 未填的配置名占位(如 MAILBOX_PASSWORD)
|
||||
const CONFIG_NAME = /^[A-Z0-9_-]{8,}$/
|
||||
|
||||
// 只报路径与行号,绝不打印匹配到的内容
|
||||
const KEY_PATTERNS = [
|
||||
@@ -22,7 +29,7 @@ const KEY_PATTERNS = [
|
||||
// 关键字赋值 / 表格单元格:PASSWORD=… / token: … / | API_KEY | …(值须 ≥16 位密钥形态字符)
|
||||
[
|
||||
'credential-assign',
|
||||
/[A-Za-z0-9_-]{0,32}(?:password|passwd|pwd|token|secret|api[_-]?key|apikey|access[_-]?key|secret[_-]?key|bot[_-]?token|private[_-]?key|credential)["']?\s*[:=|]\s*["']?([A-Za-z0-9_+/=~.!@#$%^&*?:-]{16,})/i,
|
||||
/[A-Za-z0-9_-]{0,32}(?:password|passwd|pwd|token|secret|api[_-]?key|apikey|access[_-]?key|secret[_-]?key|bot[_-]?token|private[_-]?key|credential)["']?\s*[:=|]\s*["']?(?![/~$])([A-Za-z0-9_+/=~.!@#$%^&*?:-]{16,})/i,
|
||||
true,
|
||||
],
|
||||
// Telegram bot token:<数字id>:AA<hash>
|
||||
@@ -30,8 +37,8 @@ const KEY_PATTERNS = [
|
||||
// 带内嵌口令的连接串 postgres://user:pass@host
|
||||
[
|
||||
'conn-string',
|
||||
/\b(?:postgres(?:ql)?|mysql|redis|mongodb(?:\+srv)?|amqp|smtp|mssql):\/\/[^\s'"@:/]+:[^\s'"@]{4,}@/,
|
||||
false,
|
||||
/\b(?:postgres(?:ql)?|mysql|redis|mongodb(?:\+srv)?|amqp|smtp|mssql):\/\/[^\s'"@:/]+:([A-Za-z0-9_+/=~.!@#$%^&*?:-]{4,})@/,
|
||||
true,
|
||||
],
|
||||
]
|
||||
|
||||
@@ -43,8 +50,12 @@ const trackedFiles = execSync('git ls-files', { encoding: 'utf8' })
|
||||
.split('\n')
|
||||
.filter(Boolean)
|
||||
|
||||
// 剪藏目录是第三方教程的冻结导入格式(阶段 3 边界),其中的示例凭据不是本库的
|
||||
const SKIP_PREFIXES = ['.obsidian/', '04_Archive/Inbox-Clippings/']
|
||||
|
||||
for (const file of trackedFiles) {
|
||||
if (file === '.scripts/verify-vault.mjs') continue
|
||||
if (SKIP_PREFIXES.some((p) => file.startsWith(p))) continue
|
||||
|
||||
if (file.endsWith('.png') || file.endsWith('.jpg') || file.endsWith('.jpeg') || file.endsWith('.gif') || file.endsWith('.webp') || file.endsWith('.svg') || file.endsWith('.ico') || file.endsWith('.woff') || file.endsWith('.woff2') || file.endsWith('.ttf') || file.endsWith('.eot') || file.endsWith('.pdf') || file.endsWith('.zip') || file.endsWith('.gz') || file.endsWith('.tar') || file.endsWith('.mp4') || file.endsWith('.mp3') || file.endsWith('.wav')) {
|
||||
continue
|
||||
@@ -58,20 +69,17 @@ for (const file of trackedFiles) {
|
||||
}
|
||||
|
||||
const lines = content.split('\n')
|
||||
// .obsidian/** 是第三方插件代码与状态,值形态规则误报极高(minified JS/CSS);
|
||||
// 密钥载体 data.json 已解除跟踪,这里只保留 64 位 hex 检查
|
||||
const isObsidian = file.startsWith('.obsidian/')
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
const line = lines[i]
|
||||
|
||||
if (!isObsidian) {
|
||||
if (!file.startsWith('.obsidian/')) {
|
||||
for (const [name, pattern, checkValue] of KEY_PATTERNS) {
|
||||
const m = pattern.exec(line)
|
||||
if (!m) continue
|
||||
// 赋值类:值是占位符 / 环境引用时放行
|
||||
// 赋值类:值是占位符 / 环境引用 / 默认口令时放行
|
||||
if (checkValue) {
|
||||
const value = m[1]
|
||||
if (!value || PLACEHOLDER.test(value)) continue
|
||||
if (!value || PLACEHOLDER.test(value) || DEFAULT_VALUES.test(value) || DEFAULT_SUFFIX.test(value) || CONFIG_NAME.test(value)) continue
|
||||
}
|
||||
console.error(`KEY LEAK (${name}): ${file}:${i + 1}`)
|
||||
found = true
|
||||
|
||||
Reference in New Issue
Block a user