Check url parsing error

This commit is contained in:
Fang-Pen Lin
2025-11-12 09:12:21 -08:00
parent 37fc100ff7
commit ebc041ad9d
5 changed files with 63 additions and 58 deletions
@@ -3,7 +3,6 @@ Feature: Authorization
Scenario: Get authorization Scenario: Get authorization
Given I have an ACME cert profile as "acme_profile" Given I have an ACME cert profile as "acme_profile"
When I have an ACME client connecting to {BASE_URL}/api/v1/pki/acme/profiles/{acme_profile.id}/directory When I have an ACME client connecting to {BASE_URL}/api/v1/pki/acme/profiles/{acme_profile.id}/directory
# # TODO: make it I have an account already instead?
Then I register a new ACME account with email fangpen@infisical.com and EAB key id "{acme_profile.eab_kid}" with secret "{acme_profile.eab_secret}" as acme_account Then I register a new ACME account with email fangpen@infisical.com and EAB key id "{acme_profile.eab_kid}" with secret "{acme_profile.eab_secret}" as acme_account
When I create certificate signing request as csr When I create certificate signing request as csr
Then I add names to certificate signing request csr Then I add names to certificate signing request csr
@@ -5,10 +5,10 @@ Feature: Directory
When I send a "GET" request to "/api/v1/pki/acme/profiles/{acme_profile.id}/directory" When I send a "GET" request to "/api/v1/pki/acme/profiles/{acme_profile.id}/directory"
Then the response status code should be "200" Then the response status code should be "200"
Then the response body should match JSON value Then the response body should match JSON value
""" """
{ {
"newNonce": "{BASE_URL}/api/v1/pki/acme/profiles/{acme_profile.id}/new-nonce", "newNonce": "{BASE_URL}/api/v1/pki/acme/profiles/{acme_profile.id}/new-nonce",
"newAccount": "{BASE_URL}/api/v1/pki/acme/profiles/{acme_profile.id}/new-account", "newAccount": "{BASE_URL}/api/v1/pki/acme/profiles/{acme_profile.id}/new-account",
"newOrder": "{BASE_URL}/api/v1/pki/acme/profiles/{acme_profile.id}/new-order" "newOrder": "{BASE_URL}/api/v1/pki/acme/profiles/{acme_profile.id}/new-order"
} }
""" """
+33 -33
View File
@@ -23,17 +23,17 @@ Feature: Nonce
Then I submit the certificate signing request PEM csr_pem certificate order to the ACME server as order Then I submit the certificate signing request PEM csr_pem certificate order to the ACME server as order
Then I memorize <src_var> with jq "<jq>" as <dest_var> Then I memorize <src_var> with jq "<jq>" as <dest_var>
When I send a raw ACME request to "<url>" When I send a raw ACME request to "<url>"
""" """
{ {
"protected": { "protected": {
"alg": "RS256", "alg": "RS256",
"nonce": "oFvnlFP1wIhRlYS2jTaXbA", "nonce": "oFvnlFP1wIhRlYS2jTaXbA",
"url": "<url>", "url": "<url>",
"kid": "{acme_account.uri}" "kid": "{acme_account.uri}"
}, },
"payload": {} "payload": {}
} }
""" """
Then the value response.status_code should be equal to 400 Then the value response.status_code should be equal to 400
Then the value response with jq ".status" should be equal to 400 Then the value response with jq ".status" should be equal to 400
Then the value response with jq ".type" should be equal to "urn:ietf:params:acme:error:badNonce" Then the value response with jq ".type" should be equal to "urn:ietf:params:acme:error:badNonce"
@@ -66,31 +66,31 @@ Feature: Nonce
Then I submit the certificate signing request PEM csr_pem certificate order to the ACME server as order Then I submit the certificate signing request PEM csr_pem certificate order to the ACME server as order
Then I peak and memorize the next nonce as nonce_value Then I peak and memorize the next nonce as nonce_value
When I send a raw ACME request to "/api/v1/pki/acme/profiles/{acme_profile.id}/accounts/{account_id}/orders" When I send a raw ACME request to "/api/v1/pki/acme/profiles/{acme_profile.id}/accounts/{account_id}/orders"
""" """
{ {
"protected": { "protected": {
"alg": "RS256", "alg": "RS256",
"nonce": "{nonce_value}", "nonce": "{nonce_value}",
"url": "{BASE_URL}/api/v1/pki/acme/profiles/{acme_profile.id}/accounts/{account_id}/orders", "url": "{BASE_URL}/api/v1/pki/acme/profiles/{acme_profile.id}/accounts/{account_id}/orders",
"kid": "{acme_account.uri}" "kid": "{acme_account.uri}"
}, },
"payload": {} "payload": {}
} }
""" """
Then the value response.status_code should be equal to 200 Then the value response.status_code should be equal to 200
Then I memorize <src_var> with jq "<jq>" as <dest_var> Then I memorize <src_var> with jq "<jq>" as <dest_var>
When I send a raw ACME request to "<url>" When I send a raw ACME request to "<url>"
""" """
{ {
"protected": { "protected": {
"alg": "RS256", "alg": "RS256",
"nonce": "{nonce_value}", "nonce": "{nonce_value}",
"url": "<url>", "url": "<url>",
"kid": "{acme_account.uri}" "kid": "{acme_account.uri}"
}, },
"payload": {} "payload": {}
} }
""" """
Then the value response.status_code should be equal to 400 Then the value response.status_code should be equal to 400
Then the value response with jq ".status" should be equal to 400 Then the value response with jq ".status" should be equal to 400
Then the value response with jq ".type" should be equal to "urn:ietf:params:acme:error:badNonce" Then the value response with jq ".type" should be equal to "urn:ietf:params:acme:error:badNonce"
+14 -14
View File
@@ -112,21 +112,21 @@ Feature: Order
Then I register a new ACME account with email fangpen@infisical.com and EAB key id "{acme_profile.eab_kid}" with secret "{acme_profile.eab_secret}" as acme_account Then I register a new ACME account with email fangpen@infisical.com and EAB key id "{acme_profile.eab_kid}" with secret "{acme_profile.eab_secret}" as acme_account
Then I peak and memorize the next nonce as nonce Then I peak and memorize the next nonce as nonce
When I send a raw ACME request to "{BASE_URL}/api/v1/pki/acme/profiles/{acme_profile.id}/new-order" When I send a raw ACME request to "{BASE_URL}/api/v1/pki/acme/profiles/{acme_profile.id}/new-order"
""" """
{ {
"protected": { "protected": {
"alg": "RS256", "alg": "RS256",
"nonce": "{nonce}", "nonce": "{nonce}",
"url": "{BASE_URL}/api/v1/pki/acme/profiles/{acme_profile.id}/new-order", "url": "{BASE_URL}/api/v1/pki/acme/profiles/{acme_profile.id}/new-order",
"kid": "{acme_account.uri}" "kid": "{acme_account.uri}"
}, },
"payload": { "payload": {
"identifiers": [ "identifiers": [
{ "type": "dns", "value": "<identifier_value>" } { "type": "dns", "value": "<identifier_value>" }
] ]
}
} }
} """
"""
Examples: Bad Identifier Vluaes Examples: Bad Identifier Vluaes
| identifier_value | | identifier_value |
@@ -41,7 +41,6 @@ import {
AcmeMalformedError, AcmeMalformedError,
AcmeOrderNotReadyError, AcmeOrderNotReadyError,
AcmeServerInternalError, AcmeServerInternalError,
AcmeUnauthorizedError,
AcmeUnsupportedIdentifierError AcmeUnsupportedIdentifierError
} from "./pki-acme-errors"; } from "./pki-acme-errors";
import { buildUrl, extractAccountIdFromKid } from "./pki-acme-fns"; import { buildUrl, extractAccountIdFromKid } from "./pki-acme-fns";
@@ -171,9 +170,16 @@ export const pkiAcmeServiceFactory = ({
const { protectedHeader: rawProtectedHeader, payload: rawPayload } = result; const { protectedHeader: rawProtectedHeader, payload: rawPayload } = result;
try { try {
const protectedHeader = ProtectedHeaderSchema.parse(rawProtectedHeader); const protectedHeader = ProtectedHeaderSchema.parse(rawProtectedHeader);
const parsedUrl = (() => {
try {
return new URL(protectedHeader.url);
} catch (error) {
throw new AcmeMalformedError({ message: "Invalid URL in the protected header" });
}
})();
// Validate the URL // Validate the URL
if (new URL(protectedHeader.url).href !== url.href) { if (parsedUrl.href !== url.href) {
throw new AcmeUnauthorizedError({ message: "URL mismatch in the protected header" }); throw new AcmeMalformedError({ message: "URL mismatch in the protected header" });
} }
// Consume the nonce // Consume the nonce
if (!protectedHeader.nonce) { if (!protectedHeader.nonce) {