proofscan 0.6.10 → 0.7.1
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/dist/commands/config.d.ts.map +1 -1
- package/dist/commands/config.js +74 -25
- package/dist/commands/config.js.map +1 -1
- package/dist/commands/connectors.d.ts.map +1 -1
- package/dist/commands/connectors.js +9 -4
- package/dist/commands/connectors.js.map +1 -1
- package/dist/config/add.d.ts +23 -2
- package/dist/config/add.d.ts.map +1 -1
- package/dist/config/add.js +26 -4
- package/dist/config/add.js.map +1 -1
- package/dist/secrets/detection.d.ts +71 -0
- package/dist/secrets/detection.d.ts.map +1 -0
- package/dist/secrets/detection.js +186 -0
- package/dist/secrets/detection.js.map +1 -0
- package/dist/secrets/index.d.ts +12 -0
- package/dist/secrets/index.d.ts.map +1 -0
- package/dist/secrets/index.js +18 -0
- package/dist/secrets/index.js.map +1 -0
- package/dist/secrets/providers/dpapi.d.ts +22 -0
- package/dist/secrets/providers/dpapi.d.ts.map +1 -0
- package/dist/secrets/providers/dpapi.js +95 -0
- package/dist/secrets/providers/dpapi.js.map +1 -0
- package/dist/secrets/providers/index.d.ts +20 -0
- package/dist/secrets/providers/index.d.ts.map +1 -0
- package/dist/secrets/providers/index.js +47 -0
- package/dist/secrets/providers/index.js.map +1 -0
- package/dist/secrets/providers/plain.d.ts +21 -0
- package/dist/secrets/providers/plain.d.ts.map +1 -0
- package/dist/secrets/providers/plain.js +29 -0
- package/dist/secrets/providers/plain.js.map +1 -0
- package/dist/secrets/redaction.d.ts +76 -0
- package/dist/secrets/redaction.d.ts.map +1 -0
- package/dist/secrets/redaction.js +136 -0
- package/dist/secrets/redaction.js.map +1 -0
- package/dist/secrets/secretize.d.ts +107 -0
- package/dist/secrets/secretize.d.ts.map +1 -0
- package/dist/secrets/secretize.js +148 -0
- package/dist/secrets/secretize.js.map +1 -0
- package/dist/secrets/store.d.ts +42 -0
- package/dist/secrets/store.d.ts.map +1 -0
- package/dist/secrets/store.js +174 -0
- package/dist/secrets/store.js.map +1 -0
- package/dist/secrets/types.d.ts +135 -0
- package/dist/secrets/types.d.ts.map +1 -0
- package/dist/secrets/types.js +39 -0
- package/dist/secrets/types.js.map +1 -0
- package/dist/utils/output.d.ts +14 -0
- package/dist/utils/output.d.ts.map +1 -1
- package/dist/utils/output.js +16 -0
- package/dist/utils/output.js.map +1 -1
- package/dist/utils/sanitize-secrets.d.ts.map +1 -1
- package/dist/utils/sanitize-secrets.js +20 -3
- package/dist/utils/sanitize-secrets.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Secret detection utilities (Phase 3.5)
|
|
3
|
+
*
|
|
4
|
+
* Detects sensitive keys and placeholder values in configuration.
|
|
5
|
+
* Used during config import/paste/set to auto-detect secrets.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Patterns that indicate a key is for sensitive data
|
|
9
|
+
* Case-insensitive matching
|
|
10
|
+
*/
|
|
11
|
+
const SECRET_KEY_PATTERNS = [
|
|
12
|
+
/api[-_]?key/i,
|
|
13
|
+
/apikey/i,
|
|
14
|
+
/api[-_]?token/i,
|
|
15
|
+
/access[-_]?key/i,
|
|
16
|
+
/access[-_]?token/i,
|
|
17
|
+
/secret[-_]?key/i,
|
|
18
|
+
/secret/i,
|
|
19
|
+
/password/i,
|
|
20
|
+
/passwd/i,
|
|
21
|
+
/bearer/i,
|
|
22
|
+
/authorization/i,
|
|
23
|
+
/auth[-_]?token/i,
|
|
24
|
+
/private[-_]?key/i,
|
|
25
|
+
/credentials?/i,
|
|
26
|
+
/client[-_]?secret/i,
|
|
27
|
+
];
|
|
28
|
+
/**
|
|
29
|
+
* Placeholder patterns that indicate a value should be replaced
|
|
30
|
+
* Case-insensitive matching
|
|
31
|
+
*/
|
|
32
|
+
const PLACEHOLDER_PATTERNS = [
|
|
33
|
+
/^your[-_\s]?api[-_\s]?key$/i,
|
|
34
|
+
/^your[-_\s]?token$/i,
|
|
35
|
+
/^your[-_\s]?secret$/i,
|
|
36
|
+
/^your[-_\s]?password$/i,
|
|
37
|
+
/^your[-_\s]?.*[-_\s]?here$/i,
|
|
38
|
+
/^<.*>$/, // <YOUR_API_KEY>
|
|
39
|
+
/^\[.*\]$/, // [YOUR_API_KEY]
|
|
40
|
+
/^{.*}$/, // {YOUR_API_KEY}
|
|
41
|
+
/^changeme$/i,
|
|
42
|
+
/^change[-_\s]?me$/i,
|
|
43
|
+
/^xxx+$/i,
|
|
44
|
+
/^placeholder$/i,
|
|
45
|
+
/^replace[-_\s]?me$/i,
|
|
46
|
+
/^todo$/i,
|
|
47
|
+
/^fixme$/i,
|
|
48
|
+
/^insert[-_\s]?here$/i,
|
|
49
|
+
/^sk[-_]xxx/i, // sk-xxxxxxxx
|
|
50
|
+
/^pk[-_]xxx/i, // pk-xxxxxxxx
|
|
51
|
+
];
|
|
52
|
+
/**
|
|
53
|
+
* Values that look like real secrets (for validation)
|
|
54
|
+
* These patterns help identify actual API keys vs. placeholders
|
|
55
|
+
*/
|
|
56
|
+
const REAL_SECRET_PATTERNS = [
|
|
57
|
+
/^sk-[a-zA-Z0-9]{20,}$/, // OpenAI API key
|
|
58
|
+
/^pk-[a-zA-Z0-9]{20,}$/, // Some provider public key
|
|
59
|
+
/^ghp_[a-zA-Z0-9]{36,}$/, // GitHub PAT
|
|
60
|
+
/^gho_[a-zA-Z0-9]{36,}$/, // GitHub OAuth token
|
|
61
|
+
/^github_pat_[a-zA-Z0-9_]{22,}$/, // GitHub fine-grained PAT
|
|
62
|
+
/^[A-Za-z0-9+/=]{20,}$/, // Generic base64-ish token
|
|
63
|
+
];
|
|
64
|
+
/**
|
|
65
|
+
* Check if a key name indicates a secret/sensitive value
|
|
66
|
+
*
|
|
67
|
+
* @param key - The key name to check (e.g., "OPENAI_API_KEY")
|
|
68
|
+
* @returns true if the key likely holds a secret
|
|
69
|
+
*/
|
|
70
|
+
export function isSecretKey(key) {
|
|
71
|
+
return SECRET_KEY_PATTERNS.some(pattern => pattern.test(key));
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Check if a value is a placeholder that needs to be replaced
|
|
75
|
+
*
|
|
76
|
+
* @param value - The value to check
|
|
77
|
+
* @returns true if the value is a placeholder
|
|
78
|
+
*/
|
|
79
|
+
export function isPlaceholder(value) {
|
|
80
|
+
if (!value || typeof value !== 'string') {
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
const trimmed = value.trim();
|
|
84
|
+
// Empty or very short values are not placeholders
|
|
85
|
+
if (trimmed.length < 3) {
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
return PLACEHOLDER_PATTERNS.some(pattern => pattern.test(trimmed));
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Check if a value looks like a real secret (not a placeholder)
|
|
92
|
+
*
|
|
93
|
+
* @param value - The value to check
|
|
94
|
+
* @returns true if the value appears to be a real secret
|
|
95
|
+
*/
|
|
96
|
+
export function looksLikeRealSecret(value) {
|
|
97
|
+
if (!value || typeof value !== 'string') {
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
const trimmed = value.trim();
|
|
101
|
+
// Check for known secret formats
|
|
102
|
+
if (REAL_SECRET_PATTERNS.some(pattern => pattern.test(trimmed))) {
|
|
103
|
+
return true;
|
|
104
|
+
}
|
|
105
|
+
// Heuristic: long alphanumeric strings are likely secrets
|
|
106
|
+
// Minimum 20 chars, mostly alphanumeric with some special chars
|
|
107
|
+
if (trimmed.length >= 20 && /^[a-zA-Z0-9_\-+=/.]{20,}$/.test(trimmed)) {
|
|
108
|
+
return true;
|
|
109
|
+
}
|
|
110
|
+
return false;
|
|
111
|
+
}
|
|
112
|
+
/** Minimum length for a value to be considered a storable secret */
|
|
113
|
+
const MIN_SECRET_LENGTH = 8;
|
|
114
|
+
/**
|
|
115
|
+
* Detect if a key-value pair is a secret and determine action
|
|
116
|
+
*
|
|
117
|
+
* @param key - The key name
|
|
118
|
+
* @param value - The value
|
|
119
|
+
* @returns Detection result with recommended action
|
|
120
|
+
*/
|
|
121
|
+
export function detectSecret(key, value) {
|
|
122
|
+
const secretKey = isSecretKey(key);
|
|
123
|
+
const placeholder = isPlaceholder(value);
|
|
124
|
+
const looksReal = looksLikeRealSecret(value);
|
|
125
|
+
const isTooShort = !value || value.length < MIN_SECRET_LENGTH;
|
|
126
|
+
let action;
|
|
127
|
+
if (!secretKey) {
|
|
128
|
+
// Not a secret key - skip
|
|
129
|
+
action = 'skip';
|
|
130
|
+
}
|
|
131
|
+
else if (placeholder) {
|
|
132
|
+
// Secret key with placeholder value - warn user
|
|
133
|
+
action = 'warn';
|
|
134
|
+
}
|
|
135
|
+
else if (isTooShort) {
|
|
136
|
+
// Secret key with very short/empty value - likely not a real secret, warn
|
|
137
|
+
action = 'warn';
|
|
138
|
+
}
|
|
139
|
+
else if (looksReal) {
|
|
140
|
+
// Secret key with real-looking value - store securely
|
|
141
|
+
action = 'store';
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
// Secret key with value that's long enough but doesn't match known patterns - store to be safe
|
|
145
|
+
action = 'store';
|
|
146
|
+
}
|
|
147
|
+
return {
|
|
148
|
+
key,
|
|
149
|
+
value,
|
|
150
|
+
isSecretKey: secretKey,
|
|
151
|
+
isPlaceholder: placeholder,
|
|
152
|
+
looksLikeSecret: looksReal,
|
|
153
|
+
action,
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Scan an env object for secrets
|
|
158
|
+
*
|
|
159
|
+
* @param env - Environment variables object
|
|
160
|
+
* @returns Array of detection results for secret keys
|
|
161
|
+
*/
|
|
162
|
+
export function scanEnvForSecrets(env) {
|
|
163
|
+
const results = [];
|
|
164
|
+
for (const [key, value] of Object.entries(env)) {
|
|
165
|
+
const result = detectSecret(key, value);
|
|
166
|
+
if (result.isSecretKey) {
|
|
167
|
+
results.push(result);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
return results;
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Count secrets in an env object
|
|
174
|
+
*
|
|
175
|
+
* @param env - Environment variables object
|
|
176
|
+
* @returns Object with counts by action type
|
|
177
|
+
*/
|
|
178
|
+
export function countSecrets(env) {
|
|
179
|
+
const results = scanEnvForSecrets(env);
|
|
180
|
+
return {
|
|
181
|
+
toStore: results.filter(r => r.action === 'store').length,
|
|
182
|
+
warnings: results.filter(r => r.action === 'warn').length,
|
|
183
|
+
total: results.length,
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
//# sourceMappingURL=detection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detection.js","sourceRoot":"","sources":["../../src/secrets/detection.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Secrets module (Phase 3.5)
|
|
3
|
+
*
|
|
4
|
+
* Provides secure storage and handling of API keys and sensitive configuration.
|
|
5
|
+
*/
|
|
6
|
+
export * from './types.js';
|
|
7
|
+
export { isSecretKey, isPlaceholder, looksLikeRealSecret, detectSecret, scanEnvForSecrets, countSecrets, type SecretDetectionResult, } from './detection.js';
|
|
8
|
+
export { redactDeep, redactValue, redactEnv, redactionSummary, isRedacted, REDACTED, REDACTED_REF, type RedactionResult, type RedactionOptions, } from './redaction.js';
|
|
9
|
+
export { SqliteSecretStore, getSecretStore, closeSecretStore, } from './store.js';
|
|
10
|
+
export { PlainProvider, DpapiProvider, getBestProvider, getProvider, } from './providers/index.js';
|
|
11
|
+
export { secretizeEnv, formatSecretizeOutput, isSecretizeAvailable, type SecretizeKeyResult, type SecretizeResult, type SecretizeOptions, type FormatSecretizeOptions, } from './secretize.js';
|
|
12
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/secrets/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,cAAc,YAAY,CAAC;AAG3B,OAAO,EACL,WAAW,EACX,aAAa,EACb,mBAAmB,EACnB,YAAY,EACZ,iBAAiB,EACjB,YAAY,EACZ,KAAK,qBAAqB,GAC3B,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EACL,UAAU,EACV,WAAW,EACX,SAAS,EACT,gBAAgB,EAChB,UAAU,EACV,QAAQ,EACR,YAAY,EACZ,KAAK,eAAe,EACpB,KAAK,gBAAgB,GACtB,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EACL,iBAAiB,EACjB,cAAc,EACd,gBAAgB,GACjB,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,aAAa,EACb,aAAa,EACb,eAAe,EACf,WAAW,GACZ,MAAM,sBAAsB,CAAC;AAG9B,OAAO,EACL,YAAY,EACZ,qBAAqB,EACrB,oBAAoB,EACpB,KAAK,kBAAkB,EACvB,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACrB,KAAK,sBAAsB,GAC5B,MAAM,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Secrets module (Phase 3.5)
|
|
3
|
+
*
|
|
4
|
+
* Provides secure storage and handling of API keys and sensitive configuration.
|
|
5
|
+
*/
|
|
6
|
+
// Types and interfaces
|
|
7
|
+
export * from './types.js';
|
|
8
|
+
// Detection utilities
|
|
9
|
+
export { isSecretKey, isPlaceholder, looksLikeRealSecret, detectSecret, scanEnvForSecrets, countSecrets, } from './detection.js';
|
|
10
|
+
// Redaction utilities
|
|
11
|
+
export { redactDeep, redactValue, redactEnv, redactionSummary, isRedacted, REDACTED, REDACTED_REF, } from './redaction.js';
|
|
12
|
+
// Store
|
|
13
|
+
export { SqliteSecretStore, getSecretStore, closeSecretStore, } from './store.js';
|
|
14
|
+
// Providers
|
|
15
|
+
export { PlainProvider, DpapiProvider, getBestProvider, getProvider, } from './providers/index.js';
|
|
16
|
+
// Secretize
|
|
17
|
+
export { secretizeEnv, formatSecretizeOutput, isSecretizeAvailable, } from './secretize.js';
|
|
18
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/secrets/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,uBAAuB;AACvB,cAAc,YAAY,CAAC;AAE3B,sBAAsB;AACtB,OAAO,EACL,WAAW,EACX,aAAa,EACb,mBAAmB,EACnB,YAAY,EACZ,iBAAiB,EACjB,YAAY,GAEb,MAAM,gBAAgB,CAAC;AAExB,sBAAsB;AACtB,OAAO,EACL,UAAU,EACV,WAAW,EACX,SAAS,EACT,gBAAgB,EAChB,UAAU,EACV,QAAQ,EACR,YAAY,GAGb,MAAM,gBAAgB,CAAC;AAExB,QAAQ;AACR,OAAO,EACL,iBAAiB,EACjB,cAAc,EACd,gBAAgB,GACjB,MAAM,YAAY,CAAC;AAEpB,YAAY;AACZ,OAAO,EACL,aAAa,EACb,aAAa,EACb,eAAe,EACf,WAAW,GACZ,MAAM,sBAAsB,CAAC;AAE9B,YAAY;AACZ,OAAO,EACL,YAAY,EACZ,qBAAqB,EACrB,oBAAoB,GAKrB,MAAM,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Windows DPAPI encryption provider (Phase 3.5)
|
|
3
|
+
*
|
|
4
|
+
* Uses Windows Data Protection API with CurrentUser scope.
|
|
5
|
+
* Secrets are encrypted using the user's Windows credentials.
|
|
6
|
+
*
|
|
7
|
+
* Implementation uses PowerShell to call .NET's ProtectedData class.
|
|
8
|
+
*/
|
|
9
|
+
import type { IEncryptionProvider, ProviderType } from '../types.js';
|
|
10
|
+
/**
|
|
11
|
+
* DPAPI provider - Windows Data Protection API
|
|
12
|
+
*
|
|
13
|
+
* Encrypts data using the current Windows user's credentials.
|
|
14
|
+
* Data can only be decrypted by the same user on the same machine.
|
|
15
|
+
*/
|
|
16
|
+
export declare class DpapiProvider implements IEncryptionProvider {
|
|
17
|
+
readonly type: ProviderType;
|
|
18
|
+
isAvailable(): boolean;
|
|
19
|
+
encrypt(plaintext: string): Promise<string>;
|
|
20
|
+
decrypt(ciphertext: string): Promise<string>;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=dpapi.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dpapi.d.ts","sourceRoot":"","sources":["../../../src/secrets/providers/dpapi.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAsBrE;;;;;GAKG;AACH,qBAAa,aAAc,YAAW,mBAAmB;IACvD,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAW;IAEtC,WAAW,IAAI,OAAO;IAKhB,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IA6B3C,OAAO,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CA+BnD"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Windows DPAPI encryption provider (Phase 3.5)
|
|
3
|
+
*
|
|
4
|
+
* Uses Windows Data Protection API with CurrentUser scope.
|
|
5
|
+
* Secrets are encrypted using the user's Windows credentials.
|
|
6
|
+
*
|
|
7
|
+
* Implementation uses PowerShell to call .NET's ProtectedData class.
|
|
8
|
+
*/
|
|
9
|
+
import { execSync } from 'child_process';
|
|
10
|
+
/** Maximum ciphertext length (100KB base64 encoded) */
|
|
11
|
+
const MAX_CIPHERTEXT_LENGTH = 100000;
|
|
12
|
+
/** Valid base64 pattern (strict validation for command injection prevention) */
|
|
13
|
+
const BASE64_PATTERN = /^[A-Za-z0-9+/]*={0,2}$/;
|
|
14
|
+
/**
|
|
15
|
+
* Validate that a string is valid base64 format
|
|
16
|
+
* Security: Prevents command injection by ensuring only safe characters
|
|
17
|
+
*/
|
|
18
|
+
function isValidBase64(value) {
|
|
19
|
+
if (!value || value.length === 0) {
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
if (value.length > MAX_CIPHERTEXT_LENGTH) {
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
return BASE64_PATTERN.test(value);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* DPAPI provider - Windows Data Protection API
|
|
29
|
+
*
|
|
30
|
+
* Encrypts data using the current Windows user's credentials.
|
|
31
|
+
* Data can only be decrypted by the same user on the same machine.
|
|
32
|
+
*/
|
|
33
|
+
export class DpapiProvider {
|
|
34
|
+
type = 'dpapi';
|
|
35
|
+
isAvailable() {
|
|
36
|
+
// Only available on Windows
|
|
37
|
+
return process.platform === 'win32';
|
|
38
|
+
}
|
|
39
|
+
async encrypt(plaintext) {
|
|
40
|
+
if (!this.isAvailable()) {
|
|
41
|
+
throw new Error('DPAPI is only available on Windows');
|
|
42
|
+
}
|
|
43
|
+
// Convert plaintext to base64 for safe PowerShell handling
|
|
44
|
+
const base64Input = Buffer.from(plaintext, 'utf-8').toString('base64');
|
|
45
|
+
// PowerShell script to encrypt using DPAPI
|
|
46
|
+
const script = `
|
|
47
|
+
Add-Type -AssemblyName System.Security
|
|
48
|
+
$bytes = [System.Convert]::FromBase64String("${base64Input}")
|
|
49
|
+
$encrypted = [System.Security.Cryptography.ProtectedData]::Protect($bytes, $null, [System.Security.Cryptography.DataProtectionScope]::CurrentUser)
|
|
50
|
+
[System.Convert]::ToBase64String($encrypted)
|
|
51
|
+
`.trim().replace(/\n/g, '; ');
|
|
52
|
+
try {
|
|
53
|
+
const result = execSync(`powershell -NoProfile -NonInteractive -Command "${script}"`, {
|
|
54
|
+
encoding: 'utf-8',
|
|
55
|
+
windowsHide: true,
|
|
56
|
+
timeout: 10000,
|
|
57
|
+
});
|
|
58
|
+
return result.trim();
|
|
59
|
+
}
|
|
60
|
+
catch (err) {
|
|
61
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
62
|
+
throw new Error(`DPAPI encryption failed: ${message}`);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
async decrypt(ciphertext) {
|
|
66
|
+
if (!this.isAvailable()) {
|
|
67
|
+
throw new Error('DPAPI is only available on Windows');
|
|
68
|
+
}
|
|
69
|
+
// Security: Validate ciphertext format to prevent command injection
|
|
70
|
+
if (!isValidBase64(ciphertext)) {
|
|
71
|
+
throw new Error('Invalid ciphertext format: must be valid base64');
|
|
72
|
+
}
|
|
73
|
+
// PowerShell script to decrypt using DPAPI
|
|
74
|
+
const script = `
|
|
75
|
+
Add-Type -AssemblyName System.Security
|
|
76
|
+
$encrypted = [System.Convert]::FromBase64String("${ciphertext}")
|
|
77
|
+
$bytes = [System.Security.Cryptography.ProtectedData]::Unprotect($encrypted, $null, [System.Security.Cryptography.DataProtectionScope]::CurrentUser)
|
|
78
|
+
[System.Convert]::ToBase64String($bytes)
|
|
79
|
+
`.trim().replace(/\n/g, '; ');
|
|
80
|
+
try {
|
|
81
|
+
const result = execSync(`powershell -NoProfile -NonInteractive -Command "${script}"`, {
|
|
82
|
+
encoding: 'utf-8',
|
|
83
|
+
windowsHide: true,
|
|
84
|
+
timeout: 10000,
|
|
85
|
+
});
|
|
86
|
+
// Result is base64 encoded plaintext
|
|
87
|
+
return Buffer.from(result.trim(), 'base64').toString('utf-8');
|
|
88
|
+
}
|
|
89
|
+
catch (err) {
|
|
90
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
91
|
+
throw new Error(`DPAPI decryption failed: ${message}`);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=dpapi.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dpapi.js","sourceRoot":"","sources":["../../../src/secrets/providers/dpapi.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Encryption providers index
|
|
3
|
+
*/
|
|
4
|
+
export { PlainProvider } from './plain.js';
|
|
5
|
+
export { DpapiProvider } from './dpapi.js';
|
|
6
|
+
import type { IEncryptionProvider, ProviderType } from '../types.js';
|
|
7
|
+
/**
|
|
8
|
+
* Get the best available encryption provider for the current platform
|
|
9
|
+
*
|
|
10
|
+
* Priority:
|
|
11
|
+
* 1. DPAPI on Windows
|
|
12
|
+
* 2. Keychain on macOS (future)
|
|
13
|
+
* 3. Plain fallback (no encryption, with warning)
|
|
14
|
+
*/
|
|
15
|
+
export declare function getBestProvider(): IEncryptionProvider;
|
|
16
|
+
/**
|
|
17
|
+
* Get a specific provider by type
|
|
18
|
+
*/
|
|
19
|
+
export declare function getProvider(type: ProviderType): IEncryptionProvider;
|
|
20
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/secrets/providers/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE3C,OAAO,KAAK,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAIrE;;;;;;;GAOG;AACH,wBAAgB,eAAe,IAAI,mBAAmB,CAgBrD;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,YAAY,GAAG,mBAAmB,CAYnE"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Encryption providers index
|
|
3
|
+
*/
|
|
4
|
+
export { PlainProvider } from './plain.js';
|
|
5
|
+
export { DpapiProvider } from './dpapi.js';
|
|
6
|
+
import { PlainProvider } from './plain.js';
|
|
7
|
+
import { DpapiProvider } from './dpapi.js';
|
|
8
|
+
/**
|
|
9
|
+
* Get the best available encryption provider for the current platform
|
|
10
|
+
*
|
|
11
|
+
* Priority:
|
|
12
|
+
* 1. DPAPI on Windows
|
|
13
|
+
* 2. Keychain on macOS (future)
|
|
14
|
+
* 3. Plain fallback (no encryption, with warning)
|
|
15
|
+
*/
|
|
16
|
+
export function getBestProvider() {
|
|
17
|
+
// Try DPAPI first (Windows)
|
|
18
|
+
const dpapi = new DpapiProvider();
|
|
19
|
+
if (dpapi.isAvailable()) {
|
|
20
|
+
return dpapi;
|
|
21
|
+
}
|
|
22
|
+
// TODO: Add macOS Keychain support
|
|
23
|
+
// const keychain = new KeychainProvider();
|
|
24
|
+
// if (keychain.isAvailable()) {
|
|
25
|
+
// return keychain;
|
|
26
|
+
// }
|
|
27
|
+
// Fallback to plain (no encryption)
|
|
28
|
+
console.warn('Warning: No secure encryption provider available. Secrets will be stored without encryption.');
|
|
29
|
+
return new PlainProvider();
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Get a specific provider by type
|
|
33
|
+
*/
|
|
34
|
+
export function getProvider(type) {
|
|
35
|
+
switch (type) {
|
|
36
|
+
case 'dpapi':
|
|
37
|
+
return new DpapiProvider();
|
|
38
|
+
case 'plain':
|
|
39
|
+
return new PlainProvider();
|
|
40
|
+
case 'keychain':
|
|
41
|
+
// Not yet implemented
|
|
42
|
+
throw new Error('Keychain provider not yet implemented');
|
|
43
|
+
default:
|
|
44
|
+
throw new Error(`Unknown provider type: ${type}`);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/secrets/providers/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAG3C,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE3C;;;;;;;GAOG;AACH,MAAM,UAAU,eAAe;IAC7B,4BAA4B;IAC5B,MAAM,KAAK,GAAG,IAAI,aAAa,EAAE,CAAC;IAClC,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;QACxB,OAAO,KAAK,CAAC;IACf,CAAC;IAED,mCAAmC;IACnC,2CAA2C;IAC3C,gCAAgC;IAChC,qBAAqB;IACrB,IAAI;IAEJ,oCAAoC;IACpC,OAAO,CAAC,IAAI,CAAC,8FAA8F,CAAC,CAAC;IAC7G,OAAO,IAAI,aAAa,EAAE,CAAC;AAC7B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,IAAkB;IAC5C,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,OAAO;YACV,OAAO,IAAI,aAAa,EAAE,CAAC;QAC7B,KAAK,OAAO;YACV,OAAO,IAAI,aAAa,EAAE,CAAC;QAC7B,KAAK,UAAU;YACb,sBAAsB;YACtB,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;QAC3D;YACE,MAAM,IAAI,KAAK,CAAC,0BAA0B,IAAI,EAAE,CAAC,CAAC;IACtD,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plain encryption provider (no encryption)
|
|
3
|
+
*
|
|
4
|
+
* This is a fallback provider for testing and platforms without
|
|
5
|
+
* native encryption support. It provides NO security and should
|
|
6
|
+
* only be used for development/testing purposes.
|
|
7
|
+
*/
|
|
8
|
+
import type { IEncryptionProvider, ProviderType } from '../types.js';
|
|
9
|
+
/**
|
|
10
|
+
* Plain provider - stores secrets as base64 without encryption
|
|
11
|
+
*
|
|
12
|
+
* WARNING: This provider offers NO security. Secrets are only
|
|
13
|
+
* base64 encoded, not encrypted. Use only for testing.
|
|
14
|
+
*/
|
|
15
|
+
export declare class PlainProvider implements IEncryptionProvider {
|
|
16
|
+
readonly type: ProviderType;
|
|
17
|
+
isAvailable(): boolean;
|
|
18
|
+
encrypt(plaintext: string): Promise<string>;
|
|
19
|
+
decrypt(ciphertext: string): Promise<string>;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=plain.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plain.d.ts","sourceRoot":"","sources":["../../../src/secrets/providers/plain.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAErE;;;;;GAKG;AACH,qBAAa,aAAc,YAAW,mBAAmB;IACvD,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAW;IAEtC,WAAW,IAAI,OAAO;IAKhB,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAK3C,OAAO,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAInD"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plain encryption provider (no encryption)
|
|
3
|
+
*
|
|
4
|
+
* This is a fallback provider for testing and platforms without
|
|
5
|
+
* native encryption support. It provides NO security and should
|
|
6
|
+
* only be used for development/testing purposes.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Plain provider - stores secrets as base64 without encryption
|
|
10
|
+
*
|
|
11
|
+
* WARNING: This provider offers NO security. Secrets are only
|
|
12
|
+
* base64 encoded, not encrypted. Use only for testing.
|
|
13
|
+
*/
|
|
14
|
+
export class PlainProvider {
|
|
15
|
+
type = 'plain';
|
|
16
|
+
isAvailable() {
|
|
17
|
+
// Always available as fallback
|
|
18
|
+
return true;
|
|
19
|
+
}
|
|
20
|
+
async encrypt(plaintext) {
|
|
21
|
+
// Just base64 encode - NO ENCRYPTION
|
|
22
|
+
return Buffer.from(plaintext, 'utf-8').toString('base64');
|
|
23
|
+
}
|
|
24
|
+
async decrypt(ciphertext) {
|
|
25
|
+
// Just base64 decode
|
|
26
|
+
return Buffer.from(ciphertext, 'base64').toString('utf-8');
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=plain.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plain.js","sourceRoot":"","sources":["../../../src/secrets/providers/plain.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH;;;;;GAKG;AACH,MAAM,OAAO,aAAa;IACf,IAAI,GAAiB,OAAO,CAAC;IAEtC,WAAW;QACT,+BAA+B;QAC/B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,SAAiB;QAC7B,qCAAqC;QACrC,OAAO,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAC5D,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,UAAkB;QAC9B,qBAAqB;QACrB,OAAO,MAAM,CAAC,IAAI,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IAC7D,CAAC;CACF"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Secret redaction utilities (Phase 3.5)
|
|
3
|
+
*
|
|
4
|
+
* Provides deep redaction of secrets in config output.
|
|
5
|
+
* Used by config show, export, and snapshot commands.
|
|
6
|
+
*/
|
|
7
|
+
/** Redacted placeholder for secrets */
|
|
8
|
+
export declare const REDACTED = "***REDACTED***";
|
|
9
|
+
/** Redacted placeholder for secret references */
|
|
10
|
+
export declare const REDACTED_REF = "***SECRET_REF***";
|
|
11
|
+
/**
|
|
12
|
+
* Result of redaction
|
|
13
|
+
*/
|
|
14
|
+
export interface RedactionResult {
|
|
15
|
+
/** Redacted value */
|
|
16
|
+
value: unknown;
|
|
17
|
+
/** Number of values redacted */
|
|
18
|
+
count: number;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Options for redaction
|
|
22
|
+
*/
|
|
23
|
+
export interface RedactionOptions {
|
|
24
|
+
/** Redact values for secret keys (default: true) */
|
|
25
|
+
redactSecretKeys?: boolean;
|
|
26
|
+
/** Redact secret references like "dpapi:xxx" (default: true) */
|
|
27
|
+
redactSecretRefs?: boolean;
|
|
28
|
+
/** Custom redaction string for values */
|
|
29
|
+
redactedValue?: string;
|
|
30
|
+
/** Custom redaction string for references */
|
|
31
|
+
redactedRef?: string;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Recursively redact secrets in a value
|
|
35
|
+
*
|
|
36
|
+
* Handles:
|
|
37
|
+
* - Secret references (dpapi:xxx, keychain:xxx)
|
|
38
|
+
* - Values for keys that match secret patterns
|
|
39
|
+
*
|
|
40
|
+
* @param value - Any JSON-serializable value
|
|
41
|
+
* @param options - Redaction options
|
|
42
|
+
* @returns Redacted value and count
|
|
43
|
+
*/
|
|
44
|
+
export declare function redactDeep(value: unknown, options?: RedactionOptions): RedactionResult;
|
|
45
|
+
/**
|
|
46
|
+
* Redact a single value based on key and options
|
|
47
|
+
*
|
|
48
|
+
* @param key - The key name
|
|
49
|
+
* @param value - The value to potentially redact
|
|
50
|
+
* @param options - Redaction options
|
|
51
|
+
* @returns Redacted value if applicable, original otherwise
|
|
52
|
+
*/
|
|
53
|
+
export declare function redactValue(key: string, value: string, options?: RedactionOptions): string;
|
|
54
|
+
/**
|
|
55
|
+
* Redact env variables object
|
|
56
|
+
*
|
|
57
|
+
* @param env - Environment variables
|
|
58
|
+
* @param options - Redaction options
|
|
59
|
+
* @returns Redacted env and count
|
|
60
|
+
*/
|
|
61
|
+
export declare function redactEnv(env: Record<string, string>, options?: RedactionOptions): {
|
|
62
|
+
env: Record<string, string>;
|
|
63
|
+
count: number;
|
|
64
|
+
};
|
|
65
|
+
/**
|
|
66
|
+
* Create a summary of redacted values
|
|
67
|
+
*
|
|
68
|
+
* @param count - Number of values redacted
|
|
69
|
+
* @returns Human-readable summary
|
|
70
|
+
*/
|
|
71
|
+
export declare function redactionSummary(count: number): string;
|
|
72
|
+
/**
|
|
73
|
+
* Check if a value has been redacted
|
|
74
|
+
*/
|
|
75
|
+
export declare function isRedacted(value: string): boolean;
|
|
76
|
+
//# sourceMappingURL=redaction.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redaction.d.ts","sourceRoot":"","sources":["../../src/secrets/redaction.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,uCAAuC;AACvC,eAAO,MAAM,QAAQ,mBAAmB,CAAC;AAEzC,iDAAiD;AACjD,eAAO,MAAM,YAAY,qBAAqB,CAAC;AAE/C;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,qBAAqB;IACrB,KAAK,EAAE,OAAO,CAAC;IACf,gCAAgC;IAChC,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,oDAAoD;IACpD,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,gEAAgE;IAChE,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,yCAAyC;IACzC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,6CAA6C;IAC7C,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AASD;;;;;;;;;;GAUG;AACH,wBAAgB,UAAU,CACxB,KAAK,EAAE,OAAO,EACd,OAAO,GAAE,gBAAqB,GAC7B,eAAe,CAkDjB;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CACzB,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,gBAAqB,GAC7B,MAAM,CAgBR;AAED;;;;;;GAMG;AACH,wBAAgB,SAAS,CACvB,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC3B,OAAO,GAAE,gBAAqB,GAC7B;IAAE,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAchD;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAQtD;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAEjD"}
|