diff --git a/draft-nennemann-wimse-execution-context-00.html b/draft-nennemann-wimse-execution-context-00.html index 621b7b8..6a28406 100644 --- a/draft-nennemann-wimse-execution-context-00.html +++ b/draft-nennemann-wimse-execution-context-00.html @@ -1490,6 +1490,11 @@ regulatory frameworks.

  • 10.2.  Self-Assertion Limitation

    +
  • 10.3.  Organizational Prerequisites

    @@ -2290,14 +2295,15 @@ hash algorithm identifier MUST be a lowercase value f IANA Named Information Hash Algorithm Registry (e.g., "sha-256", "sha-384", "sha-512"). Implementations MUST support "sha-256" and SHOULD use "sha-256" unless a stronger algorithm is -required. The hash MUST be computed over the raw octets of the -input data.

    +required. Implementations MUST NOT accept hash algorithms +weaker than SHA-256 (e.g., MD5, SHA-1). The hash MUST be +computed over the raw octets of the input data.

    out_hash:

    OPTIONAL. String. A cryptographic hash of the output data, -using the same format as "inp_hash".

    +using the same format and algorithm requirements as "inp_hash".

    inp_classification:
    @@ -2347,11 +2353,17 @@ used to perform the task, if applicable.witnessed_by:

    OPTIONAL. Array of StringOrURI. Identifiers of third-party -entities that observed or attested to the execution of this -task. When present, each element SHOULD use SPIFFE ID format. -In regulated environments, implementations SHOULD use witness -attestation for critical decision points to mitigate the risk -of single-agent false claims.

    +entities that the issuing agent claims observed or attested to +the execution of this task. When present, each element SHOULD +use SPIFFE ID format. Note that this claim is self-asserted by +the ECT issuer; witnesses listed here do not co-sign this ECT. +For stronger assurance, witnesses SHOULD submit independent +signed ECTs to the ledger attesting to their observation (see +Section 10.2.1). In regulated environments, +implementations SHOULD use witness attestation for critical +decision points to mitigate the risk of single-agent false +claims. See also Section 10.2 for the security +implications of self-asserted witness claims.

    @@ -2373,6 +2385,10 @@ compensation or rollback action for a previous task.

    OPTIONAL. String. A human-readable reason for the compensation action. MUST be present if "compensation_required" is true. +Values SHOULD use structured identifiers (e.g., +"policy_violation_in_parent_trade") rather than free-form text +to minimize the risk of embedding sensitive information. See +Section 11.2 for privacy guidance. If "compensation_reason" is present, "compensation_required" MUST be true.

    @@ -2402,7 +2418,12 @@ that do not understand extension claims MUST ignore t

    To avoid key collisions between different domains, extension key names MUST use reverse domain notation (e.g., "com.example.custom_field"). Implementations MUST NOT use -unqualified key names within the "ext" object.

    +unqualified key names within the "ext" object. To prevent +abuse and excessive token size, the serialized JSON +representation of the "ext" object SHOULD NOT exceed 4096 +bytes, and the JSON nesting depth within the "ext" object +SHOULD NOT exceed 5 levels. Implementations SHOULD reject +ECTs whose "ext" claim exceeds these limits.

    @@ -2597,14 +2618,19 @@ function validate_dag(ect, ledger, clock_skew_tolerance): if parent.iat >= ect.iat + clock_skew_tolerance: return error("Parent task not earlier than current") - // Step 3: Cycle detection + // Step 3: Cycle detection (with traversal limit) visited = set() - if has_cycle(ect.tid, ect.par, ledger, visited): - return error("Circular dependency detected") + result = has_cycle(ect.tid, ect.par, ledger, visited, + max_ancestor_limit) + if result is error or result is true: + return error("Circular dependency or depth limit exceeded") return success -function has_cycle(target_tid, parent_ids, ledger, visited): +function has_cycle(target_tid, parent_ids, ledger, visited, + max_depth): + if visited.size() >= max_depth: + return error("Maximum ancestor traversal limit exceeded") for parent_id in parent_ids: if parent_id == target_tid: return true @@ -2613,8 +2639,10 @@ function has_cycle(target_tid, parent_ids, ledger, visited): visited.add(parent_id) parent = ledger.get(parent_id) if parent is not null: - if has_cycle(target_tid, parent.par, ledger, visited): - return true + result = has_cycle(target_tid, parent.par, ledger, + visited, max_depth) + if result is error or result is true: + return result return false @@ -2626,7 +2654,11 @@ function has_cycle(target_tid, parent_ids, ledger, visited): current task's parents. The complexity is O(V) where V is the number of ancestor nodes reachable from the current task's parent references. For typical workflows with shallow DAGs, this is -efficient. Implementations SHOULD cache cycle detection results +efficient. To prevent denial-of-service via extremely deep or +wide DAGs, implementations SHOULD enforce a maximum ancestor +traversal limit (RECOMMENDED: 10000 nodes). If the limit is +reached before cycle detection completes, the ECT SHOULD be +rejected. Implementations SHOULD cache cycle detection results for previously verified tasks to avoid redundant traversals.

    @@ -2665,43 +2697,52 @@ public key from a WIT within the trust domain.[RFC7515] Section 5.2.

  • -

    Verify the "alg" header parameter matches the algorithm in the -corresponding WIT.

    +

    Verify that the signing key identified by "kid" has not been +revoked within the trust domain. Implementations MUST check +the key's revocation status using the trust domain's key +lifecycle mechanism (e.g., certificate revocation list, OCSP, +or SPIFFE trust bundle updates).

  • -

    Verify the "iss" claim matches the "sub" claim of the WIT -associated with the "kid" public key.

    +

    Verify the "alg" header parameter matches the algorithm in the +corresponding WIT.

  • -

    Verify the "aud" claim contains the verifier's own workload +

    Verify the "iss" claim matches the "sub" claim of the WIT +associated with the "kid" public key.

    +
  • +
  • +

    Verify the "aud" claim contains the verifier's own workload identity. When "aud" is an array, it is sufficient that the verifier's identity appears as one element; the presence of other audience values does not cause verification failure. When the verifier is the audit ledger, the ledger's own -identity MUST appear in "aud".

    -
  • -
  • -

    Verify the "exp" claim indicates the ECT has not expired.

    +identity MUST appear in "aud".

  • -

    Verify the "iat" claim is not unreasonably far in the past -(implementation-specific threshold, RECOMMENDED maximum of -15 minutes).

    +

    Verify the "exp" claim indicates the ECT has not expired.

  • -

    Verify all required claims ("jti", "tid", "exec_act", "par", -"pol", "pol_decision") are present and well-formed.

    +

    Verify the "iat" claim is not unreasonably far in the past +(implementation-specific threshold, RECOMMENDED maximum of +15 minutes) and is not unreasonably far in the future +(RECOMMENDED: no more than 30 seconds ahead of the +verifier's current time, to account for clock skew).

  • -

    Verify "pol_decision" is one of "approved", "rejected", or -"pending_human_review".

    +

    Verify all required claims ("jti", "tid", "exec_act", "par", +"pol", "pol_decision") are present and well-formed.

  • -

    Perform DAG validation per Section 6.

    +

    Verify "pol_decision" is one of "approved", "rejected", or +"pending_human_review".

  • -

    If all checks pass, the ECT MUST be appended to the audit -ledger.

    +

    Perform DAG validation per Section 6.

    +
  • +
  • +

    If all checks pass, the ECT MUST be appended to the audit +ledger.

  • If any verification step fails, the ECT MUST be rejected and the @@ -2749,6 +2790,10 @@ function verify_ect(ect_jws, verifier_id, signature, public_key): return reject("Invalid signature") + // Verify key not revoked + if is_key_revoked(header.kid, trust_domain_keys): + return reject("Signing key has been revoked") + // Verify algorithm alignment wit = get_wit_for_key(header.kid) if header.alg != wit.alg: @@ -2766,9 +2811,11 @@ function verify_ect(ect_jws, verifier_id, if payload.exp < current_time(): return reject("ECT has expired") - // Verify iat freshness + // Verify iat freshness (not too old, not in the future) if payload.iat < current_time() - max_age_threshold: return reject("ECT issued too long ago") + if payload.iat > current_time() + clock_skew_tolerance: + return reject("ECT issued in the future") // Verify required claims for claim in ["jti", "tid", "exec_act", "par", @@ -2879,7 +2926,10 @@ workflow agents to reduce the risk of collusion.

    +payload takes precedence. Implementations SHOULD validate that +convenience index fields match the corresponding values in the +JWS payload at write time to prevent desynchronization between +the authoritative JWS and the indexed fields.

    @@ -3223,7 +3273,49 @@ evaluating the policy).

    of the signing agent. To mitigate single-agent false claims, regulated environments SHOULD use the "witnessed_by" mechanism to include independent third-party observers at critical decision -points.

    +points. However, the "witnessed_by" claim is self-asserted by +the ECT issuer: the listed witnesses do not co-sign the ECT and +there is no cryptographic proof within a single ECT that the +witnesses actually observed the task. An issuing agent could +list witnesses that did not participate.

    +
    +
    +

    +10.2.1. Witness Attestation Model +

    +

    To address the self-assertion limitation of the "witnessed_by" +claim, witnesses SHOULD submit their own independent signed ECTs +to the audit ledger attesting to the observed task. A witness +attestation ECT:

    + +

    When a task's "witnessed_by" claim lists one or more witnesses, +auditors SHOULD verify that corresponding witness attestation +ECTs exist in the ledger for each listed witness. A mismatch +between the "witnessed_by" list and the set of independent witness +ECTs in the ledger SHOULD be flagged during audit review.

    +

    This model converts witness attestation from a self-asserted claim +to a cryptographically verifiable property of the ledger: the +witness independently signs their own ECT using their own key, +and the ledger records both the original task ECT and the witness +attestation ECTs.

    +
    +
    @@ -3264,9 +3356,11 @@ in a manner that preserves their integrity.MUST verify the ECT signature against the WIT public key before processing any claims. Receivers MUST verify that the signing key has not been -revoked within the trust domain.

    -

    If signature verification fails, the ECT MUST be rejected entirely -and the failure MUST be logged.

    +revoked within the trust domain (see step 6 in +Section 7).

    +

    If signature verification fails or if the signing key has been +revoked, the ECT MUST be rejected entirely and the failure MUST +be logged.

    Implementations MUST use established JWS libraries and MUST NOT implement custom signature verification.

    @@ -3402,9 +3496,14 @@ Clock skew between agents can lead to incorrect ordering judgments. Implementations SHOULD use synchronized time sources (e.g., NTP) and SHOULD allow a configurable clock skew tolerance (RECOMMENDED: 30 seconds).

    -

    The temporal ordering check in DAG validation incorporates the +

    Cross-organizational deployments where agents span multiple trust +domains with independent time sources MAY require a higher clock +skew tolerance. Deployments using trust domain federation SHOULD +document their configured clock skew tolerance value and SHOULD +ensure all participating trust domains agree on a common tolerance.

    +

    The temporal ordering check in DAG validation incorporates the clock skew tolerance to account for minor clock differences -between agents.

    +between agents.

    @@ -3414,8 +3513,11 @@ between agents.

    ECTs with many parent tasks or large extension objects can increase HTTP header size. Implementations SHOULD limit the "par" -array to a reasonable size and SHOULD set maximum size limits for -the "ext" object to prevent abuse.

    +array to a maximum of 256 entries. Workflows requiring more +parent references SHOULD introduce intermediate aggregation +tasks. The "ext" object SHOULD NOT exceed 4096 bytes when +serialized as JSON and SHOULD NOT exceed a nesting depth of +5 levels (see also Section 4.2.8).

    @@ -3474,6 +3576,15 @@ The "exec_act" claim SHOULD use structured identifier "process_payment") rather than natural language descriptions. The "pol" claim SHOULD reference policy identifiers rather than embedding policy content.

    +

    The "compensation_reason" claim (Section 4.2.7) +deserves particular attention: because it is human-readable and +may describe the circumstances of a failure or policy violation, +it risks exposing sensitive operational details. Implementations +SHOULD use short, structured reason codes (e.g., +"policy_violation_in_parent_trade") rather than free-form +natural language explanations. Implementers SHOULD review +"compensation_reason" values for potential information leakage +before deploying to production.