Skip to content

feat: Add Lambda-Runtime-Invocation-Id support for cross-wiring protection#221

Open
vip-amzn wants to merge 1 commit into
masterfrom
feat/invocation-id-cross-wiring
Open

feat: Add Lambda-Runtime-Invocation-Id support for cross-wiring protection#221
vip-amzn wants to merge 1 commit into
masterfrom
feat/invocation-id-cross-wiring

Conversation

@vip-amzn

Copy link
Copy Markdown

Summary

Add Lambda-Runtime-Invocation-Id header support for cross-wiring protection.

The runtime now parses the invocation ID from RAPID's /next response headers and echoes it back on /response and /error, enabling RAPID to detect and reject stale responses from timed-out invocations.

Problem

On Lambda Managed Instances (LMI) and On-Demand (OD), when an invoke times out, the runtime process continues running in the background. If a new invoke arrives with the same requestId, RAPID accepts it. The still-running old invocation eventually posts its response, and RAPID delivers the wrong response to the new invoke (cross-wiring).

Solution

RAPID sends a unique per-invoke identifier via Lambda-Runtime-Invocation-Id header on /next. The runtime echoes it back on /response and /error. RAPID validates the match before accepting the response.

Backward Compatibility

Fully backward compatible in both directions:

  • If RAPID doesn't send the header → field is empty → not echoed → no behavior change
  • If runtime doesn't echo it (old version) → RAPID skips validation → no behavior change

Related PRs

@vip-amzn
vip-amzn force-pushed the feat/invocation-id-cross-wiring branch from c5ac8ea to 9462974 Compare July 23, 2026 11:08
@vip-amzn
vip-amzn requested a review from maxday July 23, 2026 11:13
Comment thread src/runtime.cpp Outdated

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

here I think we need the invocation id as well, failing to do it will result in "" being passed?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks a lot for catching this, updated.

Comment thread src/runtime.cpp Outdated

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here, we need the invocation_id as well?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated.

Comment thread src/runtime.cpp Outdated
Comment thread tests/unit/unit_tests.cpp
EXPECT_TRUE(req.cognito_identity.empty());
EXPECT_TRUE(req.function_arn.empty());
EXPECT_TRUE(req.tenant_id.empty());
EXPECT_TRUE(req.invocation_id.empty());

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we expect it to be empty? or does it reflect the missing req.invocation_id being passed in run_handler?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this test asserts the default-constructed state of invocation_request (all fields empty before get_next() populates them)

@vip-amzn
vip-amzn force-pushed the feat/invocation-id-cross-wiring branch from 9462974 to 6ab9992 Compare July 23, 2026 14:23
…ction

Parse the invocation ID from /next response headers, store in
invocation_request, and echo it back on /response and /error via
do_post. Header only sent when non-empty (backward compatible).
@vip-amzn
vip-amzn force-pushed the feat/invocation-id-cross-wiring branch from 6ab9992 to 3a639bf Compare July 23, 2026 16:12

@maxday maxday left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! thanks 🥳

post_outcome post_failure(
std::string const& request_id,
invocation_response const& handler_response,
std::string const& invocation_id = "");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please don't use default argument values. Instead, add an overload and make this one call it with a default value.
Parameters with default values make it hard to change this API without breaking backwards compatibility.

@marcomagdy marcomagdy Jul 23, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same comment goes for post_success

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for your input, you're right, let's do that

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants