fix(security): validate bedrock endpoint URLs

This commit is contained in:
ZacharyZhang-NY committed 2026-05-15 00:52:18 -04:00
1 parent 84b92c859e
commit 8b0b06f765
7 files changed
+141 -8

No files matched your search

+29 -2
View File
@@ -102,7 +102,7 @@ describe("CredentialResolver", () => {
region: "eu-west-1",
awsProfile: "production",
forceCache: true,
endpointUrl: "https://bedrock-runtime.example.com",
endpointUrl: "https://bedrock-runtime.eu-west-1.amazonaws.com",
skipAuth: true,
forceHttp1: true,
},
@@ -112,12 +112,39 @@ describe("CredentialResolver", () => {
AWS_REGION: "eu-west-1",
AWS_PROFILE: "production",
AWS_BEDROCK_FORCE_CACHE: "1",
AWS_ENDPOINT_URL_BEDROCK_RUNTIME: "https://bedrock-runtime.example.com",
AWS_ENDPOINT_URL_BEDROCK_RUNTIME: "https://bedrock-runtime.eu-west-1.amazonaws.com",
AWS_BEDROCK_SKIP_AUTH: "1",
AWS_BEDROCK_FORCE_HTTP1: "1",
});
});
it("rejects unsafe AWS endpointUrl values from stored credentials", async () => {
store.save("amazon-bedrock", {
kind: "aws",
value: {
authMode: "profile",
region: "us-east-1",
awsProfile: "default",
endpointUrl: "https://example.com",
},
});
let thrown: unknown;
try {
await resolver.resolve("amazon-bedrock");
} catch (error) {
thrown = error;
}
expect(thrown).toBeInstanceOf(CredentialError);
expect(thrown).toMatchObject({
kind: "upstream",
code: "CREDENTIAL_INVALID",
connectorId: "amazon-bedrock",
context: { connectorId: "amazon-bedrock" },
});
});
it("assembles Azure extraEnv with deploymentMap", async () => {
store.save("azure-openai", {
kind: "azure",
+41
View File
@@ -5,6 +5,7 @@ import {
azureCredentialSchema,
credentialPayloadSchema,
gcpAdcCredentialSchema,
isAwsBedrockEndpointUrl,
isLocalConnectorBaseUrl,
localCredentialSchema,
removeCredentialInputSchema,
@@ -51,6 +52,46 @@ describe("credentials Zod schemas", () => {
}
});
it("awsCredentialSchema accepts AWS Bedrock and private HTTPS endpointUrl values", () => {
for (const endpointUrl of [
"https://bedrock-runtime.us-east-1.amazonaws.com",
"https://bedrock-runtime.us-east-1.amazonaws.com/",
"https://bedrock-runtime-fips.us-gov-west-1.amazonaws.com",
"https://bedrock-runtime.cn-north-1.amazonaws.com.cn",
"https://vpce-123abc.bedrock-runtime.us-east-1.vpce.amazonaws.com",
"https://vpce-123abc-us-east-1a.bedrock-runtime.us-east-1.vpce.amazonaws.com",
"https://10.0.0.20",
"https://192.168.1.20",
"https://[fd12::1]",
]) {
const result = awsCredentialSchema.safeParse({ authMode: "profile", region: "us-east-1", awsProfile: "default", endpointUrl });
expect(result.success).toBe(true);
expect(isAwsBedrockEndpointUrl(endpointUrl)).toBe(true);
}
});
it("awsCredentialSchema rejects unsafe endpointUrl values", () => {
for (const endpointUrl of [
"http://bedrock-runtime.us-east-1.amazonaws.com",
"https://api.openai.com/v1",
"https://bedrock-runtime.example.com",
"https://user:pass@bedrock-runtime.us-east-1.amazonaws.com",
"https://bedrock-runtime.us-east-1.amazonaws.com/model/test",
"https://bedrock-runtime.us-east-1.amazonaws.com?proxy=1",
"ftp://bedrock-runtime.us-east-1.amazonaws.com",
"https://bedrock-runtime.us-east-1.amazonaws.com?",
"https://bedrock-runtime.us-east-1.amazonaws.com#",
"https://bedrock-runtime.us-east-1.amazonaws.com/%2e%2e",
"https://bedrock-runtime.us-east-1.amazonaws.com/a/..",
"https://bedrock-runtime.us-east-1.vpce.amazonaws.com",
"https://foo.bar.bedrock-runtime.us-east-1.vpce.amazonaws.com",
]) {
const result = awsCredentialSchema.safeParse({ authMode: "profile", region: "us-east-1", awsProfile: "default", endpointUrl });
expect(result.success).toBe(false);
expect(isAwsBedrockEndpointUrl(endpointUrl)).toBe(false);
}
});
it("azureCredentialSchema requires apiKey", () => {
expect(azureCredentialSchema.safeParse({}).success).toBe(false);
expect(azureCredentialSchema.safeParse({ apiKey: "azure-secret" }).success).toBe(true);