fullcourtdefense-cli 1.21.31 → 1.21.32
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/config.d.ts +10 -0
- package/dist/config.js +20 -3
- package/dist/version.json +1 -1
- package/package.json +1 -1
package/dist/config.d.ts
CHANGED
|
@@ -32,6 +32,16 @@ export interface PowershellHealth {
|
|
|
32
32
|
checkedAt: string;
|
|
33
33
|
}
|
|
34
34
|
export declare function getPowershellHealth(): PowershellHealth | undefined;
|
|
35
|
+
/**
|
|
36
|
+
* PSCredential.GetNetworkCredential() instead of Marshal::SecureStringToBSTR:
|
|
37
|
+
* hardened fleets run PowerShell in Constrained Language Mode, where the
|
|
38
|
+
* [Runtime.InteropServices.Marshal] calls are forbidden (script fails ->
|
|
39
|
+
* exit 1 -> "Shield key not available" -> every hook 401s fail-closed). The
|
|
40
|
+
* PSCredential technique is on CLM's approved-type list and decrypts the same
|
|
41
|
+
* DPAPI-protected SecureString in every language mode. Exported so the CLM
|
|
42
|
+
* regression test runs this EXACT text inside a ConstrainedLanguage session.
|
|
43
|
+
*/
|
|
44
|
+
export declare const DPAPI_DECRYPT_SNIPPET = "$secure=ConvertTo-SecureString -String $env:FCD_DPAPI_VALUE; (New-Object System.Management.Automation.PSCredential('fcd', $secure)).GetNetworkCredential().Password";
|
|
35
45
|
export declare function getHomeConfigPath(): string;
|
|
36
46
|
export declare function loadConfig(configPath?: string): BotGuardConfig;
|
|
37
47
|
export declare function getDefaultConfigPath(): string;
|
package/dist/config.js
CHANGED
|
@@ -33,6 +33,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.DPAPI_DECRYPT_SNIPPET = void 0;
|
|
36
37
|
exports.getPowershellHealth = getPowershellHealth;
|
|
37
38
|
exports.getHomeConfigPath = getHomeConfigPath;
|
|
38
39
|
exports.loadConfig = loadConfig;
|
|
@@ -204,8 +205,18 @@ function powershellDpapi(script, value) {
|
|
|
204
205
|
function protectShieldKeyForCurrentWindowsUser(value) {
|
|
205
206
|
return powershellDpapi('$secure=ConvertTo-SecureString -String $env:FCD_DPAPI_VALUE -AsPlainText -Force; ConvertFrom-SecureString -SecureString $secure', value);
|
|
206
207
|
}
|
|
208
|
+
/**
|
|
209
|
+
* PSCredential.GetNetworkCredential() instead of Marshal::SecureStringToBSTR:
|
|
210
|
+
* hardened fleets run PowerShell in Constrained Language Mode, where the
|
|
211
|
+
* [Runtime.InteropServices.Marshal] calls are forbidden (script fails ->
|
|
212
|
+
* exit 1 -> "Shield key not available" -> every hook 401s fail-closed). The
|
|
213
|
+
* PSCredential technique is on CLM's approved-type list and decrypts the same
|
|
214
|
+
* DPAPI-protected SecureString in every language mode. Exported so the CLM
|
|
215
|
+
* regression test runs this EXACT text inside a ConstrainedLanguage session.
|
|
216
|
+
*/
|
|
217
|
+
exports.DPAPI_DECRYPT_SNIPPET = "$secure=ConvertTo-SecureString -String $env:FCD_DPAPI_VALUE; (New-Object System.Management.Automation.PSCredential('fcd', $secure)).GetNetworkCredential().Password";
|
|
207
218
|
function unprotectShieldKeyForCurrentWindowsUser(value) {
|
|
208
|
-
return powershellDpapi(
|
|
219
|
+
return powershellDpapi(exports.DPAPI_DECRYPT_SNIPPET, value);
|
|
209
220
|
}
|
|
210
221
|
function mergeConfig(base, override) {
|
|
211
222
|
return {
|
|
@@ -352,9 +363,15 @@ function writeSetupConfig(target, input) {
|
|
|
352
363
|
const protectedShieldKey = input.shieldKey && process.platform === 'win32'
|
|
353
364
|
? protectShieldKeyForCurrentWindowsUser(input.shieldKey)
|
|
354
365
|
: undefined;
|
|
355
|
-
|
|
366
|
+
// Roundtrip-verify before trusting DPAPI: encryption is cmdlet-only and
|
|
367
|
+
// succeeds even where decryption is blocked (Constrained Language Mode /
|
|
368
|
+
// EDR), which used to delete the plaintext key on a machine that could
|
|
369
|
+
// never read the encrypted one back — every hook then 401'd fail-closed.
|
|
370
|
+
const dpapiVerified = !!protectedShieldKey
|
|
371
|
+
&& unprotectShieldKeyForCurrentWindowsUser(protectedShieldKey) === input.shieldKey;
|
|
372
|
+
if (protectedShieldKey && dpapiVerified) {
|
|
356
373
|
setTopLevel('shieldKeyDpapi', protectedShieldKey);
|
|
357
|
-
// Remove legacy plaintext key on a
|
|
374
|
+
// Remove legacy plaintext key on a VERIFIED Windows DPAPI migration.
|
|
358
375
|
const plaintextIndex = lines.findIndex(line => /^shieldKey:/.test(line.trim()));
|
|
359
376
|
if (plaintextIndex >= 0)
|
|
360
377
|
lines.splice(plaintextIndex, 1);
|
package/dist/version.json
CHANGED