fix(secrets): reject inherited exec response ids (#101739)

* fix(secrets): check own exec response ids

* test(secrets): cover inherited exec response errors

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
(cherry picked from commit c765b5de3b)
This commit is contained in:
Alix-007
2026-07-09 18:13:13 +08:00
committed by Dallin Romney
parent e2498b8e00
commit e9ddf89fc2
2 changed files with 47 additions and 2 deletions
+45
View File
@@ -45,6 +45,7 @@ describe("secret ref resolver", () => {
let execPlainScriptPath = "";
let execProtocolV2ScriptPath = "";
let execMissingIdScriptPath = "";
let execInheritedErrorScriptPath = "";
let execInvalidJsonScriptPath = "";
let execFastExitScriptPath = "";
@@ -152,6 +153,16 @@ describe("secret ref resolver", () => {
0o700,
);
execInheritedErrorScriptPath = path.join(sharedExecDir, "resolver-inherited-error.sh");
await writeSecureFile(
execInheritedErrorScriptPath,
[
"#!/bin/sh",
'printf \'{"protocolVersion":1,"values":{"toString":"resolved"},"errors":{}}\'',
].join("\n"),
0o700,
);
execInvalidJsonScriptPath = path.join(sharedExecDir, "resolver-invalid-json.sh");
await writeSecureFile(
execInvalidJsonScriptPath,
@@ -400,6 +411,40 @@ describe("secret ref resolver", () => {
);
});
itPosix("rejects exec refs when missing response id is inherited", async () => {
await expect(
resolveSecretRefValue(
{ source: "exec", provider: "execmain", id: "toString" },
{
config: {
secrets: {
providers: {
execmain: createExecProviderConfig(execMissingIdScriptPath),
},
},
},
},
),
).rejects.toThrow('response missing id "toString"');
});
itPosix("ignores inherited exec response errors", async () => {
await expect(
resolveSecretRefValue(
{ source: "exec", provider: "execmain", id: "toString" },
{
config: {
secrets: {
providers: {
execmain: createExecProviderConfig(execInheritedErrorScriptPath),
},
},
},
},
),
).resolves.toBe("resolved");
});
itPosix("rejects exec refs with invalid JSON when jsonOnly is true", async () => {
await expect(resolveExecSecret(execInvalidJsonScriptPath, { jsonOnly: true })).rejects.toThrow(
"returned invalid JSON",
+2 -2
View File
@@ -664,7 +664,7 @@ function parseExecValues(params: {
const responseErrors = isRecord(parsed.errors) ? parsed.errors : null;
const out: Record<string, unknown> = {};
for (const id of params.ids) {
if (responseErrors && id in responseErrors) {
if (responseErrors && Object.hasOwn(responseErrors, id)) {
const entry = responseErrors[id];
if (isRecord(entry) && typeof entry.message === "string" && entry.message.trim()) {
throw refResolutionError({
@@ -681,7 +681,7 @@ function parseExecValues(params: {
message: `Exec provider "${params.providerName}" failed for id "${id}".`,
});
}
if (!(id in responseValues)) {
if (!Object.hasOwn(responseValues, id)) {
throw refResolutionError({
source: "exec",
provider: params.providerName,