iflytek/astron-agent · error · IllegalArgumentException

unsupported workflow gateway request

Error message

unsupported workflow gateway request

What it means

WorkflowGatewayIdentity.requireAuthorizedPath validates the original public request metadata before signature binding: the request must be a POST to one of the whitelisted PUBLIC_WORKFLOW_PATHS, with no fragment. Anything else fails closed with IllegalArgumentException. Query strings are stripped, never decoded or normalized, so encoded or alternate paths are rejected.

Solutions

  1. Use POST against an exact whitelisted PUBLIC_WORKFLOW_PATHS entry, with no fragment in the URI
  2. Check the request URI for encoding/rewriting by proxies; send the raw original URI
  3. If the endpoint should be public, add its exact path to PUBLIC_WORKFLOW_PATHS (security-reviewed change)
  4. Catch IllegalArgumentException in the gateway filter and return 400/403

Example fix

// before
String path = WorkflowGatewayIdentity.requireAuthorizedPath(request.getMethod(), request.getRequestURI()); // GET /api/workflow/run
// after
// Only POST to an exact public path:
if ("POST".equals(request.getMethod()) && request.getRequestURI().startsWith("/api/workflow/public")) {
    String path = WorkflowGatewayIdentity.requireAuthorizedPath(request.getMethod(), request.getRequestURI());
}
Defensive patterns

Strategy: validation

Validate before calling

boolean ok = "POST".equals(method) && uri != null && !uri.isEmpty() && !uri.contains("#") && PUBLIC_WORKFLOW_PATHS.contains(uri.split("\\?")[0]);

Try / catch

try { path = WorkflowGatewayIdentity.requireAuthorizedPath(method, uri); } catch (IllegalArgumentException e) { response.sendError(400); }

Prevention

When it happens

Trigger: Forwarding a GET/PUT/DELETE request through the workflow gateway; passing an empty or null originalUri; a URI whose path is not in PUBLIC_WORKFLOW_PATHS; a URI containing a '#' fragment; percent-encoded path variants that don't byte-match the whitelist entries.

Common situations: Clients hitting non-whitelisted workflow endpoints through the public gateway; proxies rewriting or encoding the URI; misconfigured gateways forwarding fragments; version changes that moved a path off the whitelist.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of iflytek/astron-agent@5e758547a8 (2026-09-12). Data as JSON: /api/errors/4ac4ecf85a404ad7. Report an issue: GitHub.

Appendix: source

Thrown at console/backend/commons/src/main/java/com/iflytek/astron/console/commons/security/WorkflowGatewayIdentity.java:31

    public static final String TIMESTAMP_HEADER = "X-Workflow-Gateway-Timestamp";
    public static final String SIGNATURE_HEADER = "X-Workflow-Gateway-Signature";

    private static final String POST = "POST";
    private static final String HMAC_SHA_256 = "HmacSHA256";
    private static final Set<String> PUBLIC_WORKFLOW_PATHS = Set.of(
            "/workflow/v1/chat/completions", "/workflow/v1/resume");

    private WorkflowGatewayIdentity() {}

    /**
     * Validate the original public request metadata and return the exact path bound into the signature.
     * Query parameters are deliberately excluded; no decoding or path normalization is performed, so
     * encoded or alternate paths fail closed.
     */
    public static String requireAuthorizedPath(String originalMethod, String originalUri) {
        if (!POST.equals(originalMethod) || StringUtils.isEmpty(originalUri)) {
            throw new IllegalArgumentException("unsupported workflow gateway request");
        }
        int queryStart = originalUri.indexOf('?');
        String path = queryStart < 0 ? originalUri : originalUri.substring(0, queryStart);
        if (!PUBLIC_WORKFLOW_PATHS.contains(path) || originalUri.indexOf('#') >= 0) {
            throw new IllegalArgumentException("unsupported workflow gateway request");
        }
        return path;
    }

    /** Sign {@code method + newline + path + newline + appId + newline + epochSeconds}. */
    public static String sign(
            String configuredKey,
            String method,
            String path,
            String appId,
            long epochSeconds) {
        String internalKey = WorkflowInternalApiKey.requireConfigured(configuredKey);
        if (!POST.equals(method)

View on GitHub (pinned to 5e758547a8)