Skip to content

Fix LHOST validation rejecting tunnel hostnames when DNS lookup fails#21552

Open
stzifkas wants to merge 14 commits into
rapid7:masterfrom
stzifkas:fix/lhost-hostname-validation-dns-fallback
Open

Fix LHOST validation rejecting tunnel hostnames when DNS lookup fails#21552
stzifkas wants to merge 14 commits into
rapid7:masterfrom
stzifkas:fix/lhost-hostname-validation-dns-fallback

Conversation

@stzifkas

@stzifkas stzifkas commented Jun 8, 2026

Copy link
Copy Markdown

Summary

  • OptAddress#valid? was catching all DNS lookup failures and immediately returning false
  • This broke msfvenom payload generation when LHOST is set to a tunnel service hostname (ngrok, pinggy, etc.) that doesn't resolve from the attacker's machine but is perfectly valid syntax
  • Fix: on DNS failure, fall back to Rex::Socket.is_name? for hostname syntax validation — syntactically valid hostnames are accepted, garbage is still rejected

Verification steps

  1. Reproduce with the installed framework before the fix:

    msfvenom -p android/meterpreter/reverse_tcp LHOST=qhuoq-106-219-171-165.run.pinggy-free.link LPORT=4444 -o /tmp/test.apk
    # Error: One or more options failed to validate: LHOST.
    
  2. After the fix, the same command generates the APK successfully.

  3. IPs, invalid hostnames, and garbage strings still fail validation as expected.

Related issues

See #21539

@smcintyre-r7

Copy link
Copy Markdown
Contributor

I'm pretty sure this is a regression I added with the work I did in #20989. I understand that payloads need a way to connect to a hostname, but having OptAddress pass validation for a hostname instead of either an IPv4 or IPv6 address seems like the type of thing that would cause issues down the line. Now the context here is the work in 20989 was intended to adjust SRVHOST which is similar to LHOST in the sense that typically they're the only address/hostname the target is supposed to use when connecting back to Metasploit. Both can be overridden by a different option (ListenerBindAddress for SRVHOST and ReverseListenerBindAddress for LHOST) which is what Metasploit binds to. When set, these must be resolvable by the local host, e.g. localhost.localdomain -> 127.0.0.1 is expected to work.

I think what we need here is possibly a new option that permits the hostname resolution to be deferred. It shouldn't be OptAddress though because it is fundamentally not an address. ReverseListenerBindAddress and ListenerBindAddress should stay OptAddress and resolve the hostname locally, failing when it's unable to. LHOST and SRVHOST should be something else, that's more permissive and either an address or a hostname. When it's a hostname, Metasploit shouldn't resolve it unless it needs to because ReverseListenerBindAddress and ListenerBindAddress are unset. I should note that this would be the default case, not an edge case.

@smcintyre-r7 smcintyre-r7 added library rn-fix release notes fix labels Jun 8, 2026
@dwelch-r7

Copy link
Copy Markdown
Contributor

@smcintyre-r7 does this change make sense as is as a first step and we can create an issue to address the root issue more in depth? or are there specific issues you're concerned this will introduce that need to be addressed first?

Just thinking since this addresses a real problem now we could link the issue in a comment by the change while we work on a more holistic fix

@smcintyre-r7

Copy link
Copy Markdown
Contributor

If that ticket explicitly called out reverting the changes contained herein as part of the work and we pulled it into the next sprint then sure. Ideally though, we'd just fix it correctly the first time so it's up to @stzifkas on if they're up for the additional work that's necessary.

@stzifkas stzifkas force-pushed the fix/lhost-hostname-validation-dns-fallback branch from 1fe205f to 12708c2 Compare June 8, 2026 20:14
@stzifkas

stzifkas commented Jun 8, 2026

Copy link
Copy Markdown
Author

@smcintyre-r7 , @dwelch-r7 thanks for the feedback. Went ahead with the architectural approach you outlined. Here's what changed:

  • added OptAddressOrHostname as a new option type for LHOST. Validates via Rex::Socket.is_name? for hostname syntax and Rex::Socket.is_ip_addr? for IPs/interfaces, no DNS lookup at all. ReverseListenerBindAddress / ListenerBindAddress stay on OptAddress unchanged.

  • reverse.rb and reverse_udp.rb now skip resolv_nbo(LHOST) entirely when ReverseListenerBindAddress is explicitly set, since the bind address is already fully determined at that point.

  • tab_complete_source_interface changed to respond_to?(:interfaces) so interface name completion still works for LHOST.

  • SRVHOST is a separate story, its semantics vary per module (some want a local bind address, others a callback address) so is intentionally left out from this PR's scope.

Comment thread lib/msf/core/handler/reverse.rb Outdated
# resolving LHOST (LHOST may be a tunnel hostname not locally resolvable).
bind_addr = datastore['ReverseListenerBindAddress']
any = Rex::Socket.is_ipv6?(bind_addr) ? "::0" : "0.0.0.0"
return [ (bind_addr == "0.0.0.0" || bind_addr == "::0") ? any : bind_addr ]

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.

These checks for the any address should always normalize with addr_atoi then compare to zero. I know it's a preexisting issue but we shouldn't propagate it. The reason is actually apparent here, :: is typically the bind-any IPv6 address not ::0, but they're equivalent since per the RFC, the 0s can be omitted.

This comparison should always be:
Rex::Socket.addr_atoi(bind_addr) == 0 not bind_addr == "0.0.0.0" || bind_addr == "::0"). This is not the only location that needs to be updated with the correct pattern.

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.

Done, using Rex::Socket.addr_atoi(bind_addr) == 0 throughout.

Comment thread lib/msf/core/handler/reverse_udp.rb Outdated
Comment on lines +264 to +265
addr = Rex::Socket.resolv_nbo(datastore['LHOST'])
any = (addr.length == 4) ? "0.0.0.0" : "::0"

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.

Use Rex::Socket.is_ipv4? not Rex::Socket.resolv_nbo(datastore['LHOST']).length == 4

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.

Using Rex::Socket.is_ipv4? now.

Comment on lines +11 to +13
# syntactically valid hostname. Unlike OptAddress, DNS resolution is NOT
# performed during validation, so tunnel service hostnames (ngrok, pinggy,
# etc.) that are not resolvable from the local machine are accepted.

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.

This would do well to allow an option like resolve_names: false and allow the caller to specify whether or not we should be resolving hostnames to IP addresses as part of the validation process. If we're performing a connection to the value or binding to it, that would allow us to fail earlier which would be extremely helpful.

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.

resolve_names: is already there, defaults to false.

@github-project-automation github-project-automation Bot moved this from Todo to Waiting on Contributor in Metasploit Kanban Jun 8, 2026
@stzifkas

stzifkas commented Jun 8, 2026

Copy link
Copy Markdown
Author

Addressed in the latest push

resolve_names: added to OptAddressOrHostname, and all wildcard address comparisons now use Rex::Socket.addr_atoi == 0 / Rex::Socket.is_ipv4? consistently across both handlers.

@stzifkas stzifkas requested a review from smcintyre-r7 June 10, 2026 12:38
register_options(
[
OptAddressLocal.new('LHOST', [true, 'The local listener hostname']),
OptAddressOrHostname.new('LHOST', [true, 'The local listener hostname']),

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.

For R7 reviewers: Going forward, we might look into modifying the option name here.

Comment thread lib/msf/core/opt.rb Outdated
# @return [OptAddressOrHostname]
def self.LHOST(default=nil, required=true, desc="The listen address (an interface may be specified)")
Msf::OptAddressLocal.new(__method__.to_s, [ required, desc, default ])
Msf::OptAddressOrHostname.new(__method__.to_s, [ required, desc, default ])

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.

I think we don't want to change the default type for this option across all of MSF.

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.

Reverted. Opt::LHOST is back to OptAddress. OptAddressOrHostname is only applied in the Reverse and ReverseUdp handlers.

Comment thread lib/msf/core/opt_address_or_hostname.rb Outdated
# a locally-resolvable address.
#
###
class OptAddressOrHostname < OptBase

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.

Can we deduplicate the validation and normalisation here and other options? Modifying the validation logic here to e.g. fix a bug, means other options don't get the same fix applied.

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.

Now inherits from OptAddressRoutable. Duplicate interfaces, normalize_interface, and normalize_ip methods removed.

Comment thread lib/msf/core/opt_address_or_hostname.rb Outdated
private

def normalize_interface(value)
addrs = NetworkInterface.addresses(value).values.flatten

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.

This looks to be copy-pasted from opt_address_routable. Can we do any code deduplication here?

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.

Removed, inherited from OptAddressRoutable now.

end
end
end

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.

Looks like we can restore this change

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.

Restored.

{ value: 5 },
{ value: [] },
{ value: [1, 2] },
{ value: {} },

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.

Can we test nil 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.

Added nil to the invalid values list.

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.

Removed nil from invalid_values - OptBase defaults required to false when attrs is empty, so nil is valid for that subject. The shared example already covers nil for both required and non-required cases.

# XXX: We repurpose OptAddressLocal#interfaces, so we can't put this in Rex
def tab_complete_source_interface(o)
return [] unless o.is_a?(Msf::OptAddressLocal)
return [] unless o.respond_to?(:interfaces)

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.

We need to confirm if this change makes sense; or should we only tab complete when the option is an OptAddressLocal explicitly

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.

Changed to is_a?(Msf::OptAddressRoutable) so it covers both OptAddressLocal and OptAddressOrHostname explicitly.

context 'with tunnel hostnames' do
it 'accepts without requiring DNS resolution' do
allow(::Rex::Socket).to receive(:getaddress).and_raise(::SocketError)
expect(opt.valid?('qhuoq-106-219-171-165.run.pinggy-free.link')).to be_truthy

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.

Can we use any placeholder addresses here such as example.com as opposed to what looks like a real live link?

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.

Replaced with tunnel.example.com throughout the spec.

Comment thread lib/msf/core/opt_address_or_hostname.rb Outdated
# a locally-resolvable address.
#
###
class OptAddressOrHostname < OptBase

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.

Could we either:
Inherit from OptAddress
or
Have the OptAddress as a member variable
in an effort to deduplicate?

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.

Went with inheriting from OptAddressRoutable (which itself extends OptAddress). Deduplicates interfaces, normalize_interface, and normalize_ip_address.

@stzifkas

Copy link
Copy Markdown
Author

Reverted Opt::LHOST back to OptAddress globally. OptAddressOrHostname is now only applied in Reverse and ReverseUdp handlers, which is where tunnel hostname support is actually needed. Rest of MSF is unaffected.

@bwatters-r7 bwatters-r7 moved this from Waiting on Contributor to In Progress in Metasploit Kanban Jun 15, 2026
@bwatters-r7 bwatters-r7 moved this from In Progress to Ready in Metasploit Kanban Jun 15, 2026
@dwelch-r7 dwelch-r7 self-assigned this Jun 22, 2026
@dwelch-r7

Copy link
Copy Markdown
Contributor

@stzifkas I'm gonna be looking at this PR shortly but just to let you know you've got some failing tests that will need to be addressed

@stzifkas stzifkas force-pushed the fix/lhost-hostname-validation-dns-fallback branch from 01061b6 to 8bb40b3 Compare June 23, 2026 16:39
@stzifkas

Copy link
Copy Markdown
Author

Rebased on master. The python 3.8 macos build failure is pre-existing and unrelated to this PR.

@dwelch-r7 dwelch-r7 requested a review from Copilot June 24, 2026 12:53

Copilot AI 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.

Pull request overview

This PR introduces a new option type to allow LHOST values that are syntactically valid hostnames even when they don’t resolve locally (common with tunnel providers), and updates reverse handlers to better separate “callback host” (LHOST) from “bind address” (ReverseListenerBindAddress).

Changes:

  • Added Msf::OptAddressOrHostname (accepts IP/interface/hostname without DNS by default, with an opt-in DNS resolution mode).
  • Updated reverse handlers to use the new option and to avoid resolving LHOST when ReverseListenerBindAddress is explicitly set.
  • Added RSpec coverage for the new option behavior (including tunnel-style hostnames) and updated interface tab completion to work with the new option’s superclass.

Impact Analysis:

  • Blast radius: medium; affects option validation for reverse handlers (and potentially any code using Opt::LHOST), impacting payload generation (msfvenom) and listener startup paths.
  • Data and contract effects: option validation semantics change for LHOST (hostname acceptance and when DNS is consulted); handler binding behavior changes when ReverseListenerBindAddress is set.
  • Rollback and test focus: validate msfvenom generation for staged and single reverse payloads, and validate listener bind behavior for IPv4/IPv6 + interface-name LHOST with/without ReverseListenerBindAddress.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
spec/lib/msf/core/opt_address_or_hostname_spec.rb Adds specs covering tunnel hostname validation and normalization behaviors.
lib/msf/ui/console/module_option_tab_completion.rb Broadens interface-name tab completion to OptAddressRoutable-derived options.
lib/msf/core/option_container.rb Autoloads the new OptAddressOrHostname option type.
lib/msf/core/opt.rb Changes the framework Opt::LHOST shortcut implementation.
lib/msf/core/opt_address_or_hostname.rb Introduces the new option class implementing hostname-without-DNS validation.
lib/msf/core/handler/reverse.rb Uses the new option for LHOST and adjusts bind address selection logic.
lib/msf/core/handler/reverse_udp.rb Uses the new option for LHOST and adjusts bind address selection logic.
lib/msf/core/handler/reverse_http.rb Switches LHOST option type to accept non-resolving hostnames.

Comment thread lib/msf/core/opt.rb
Comment on lines +27 to 30
# @return [OptAddress]
def self.LHOST(default=nil, required=true, desc="The listen address (an interface may be specified)")
Msf::OptAddressLocal.new(__method__.to_s, [ required, desc, default ])
Msf::OptAddress.new(__method__.to_s, [ required, desc, default ])
end

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.

Fixed - now calls for IP addresses, so they go through OptAddressRoutable's multicast/reserved/broadcast checks. Wildcard IPs (0.0.0.0, 0::0) are now invalid for this option.

Comment thread lib/msf/core/opt_address_or_hostname.rb Outdated
Comment on lines +45 to +59
if value =~ /^\d+(\.\d+)+$/
return Rex::Socket.is_ipv4?(value)
end

return true if Rex::Socket.is_ip_addr?(value)

if Rex::Socket.is_name?(value)
return true unless @resolve_names
begin
::Rex::Socket.getaddress(value, true)
return true
rescue
return false
end
end

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.

I think you just need to call super to address this, copilot is a bit wordy, but will need to verify that's all that's needed

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.

Done. IP addresses now call super so they go through OptAddressRoutable for the multicast/reserved/broadcast checks. 0.0.0.0 and 0::0 are now invalid as a side effect (removed from the spec valid_values, added to invalid_values).

Comment on lines +1 to +3
# -*- coding: binary -*-
require 'network_interface'

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 address this

Comment thread lib/msf/core/opt.rb
Comment on lines -27 to +29
# @return [OptAddressLocal]
# @return [OptAddress]
def self.LHOST(default=nil, required=true, desc="The listen address (an interface may be specified)")
Msf::OptAddressLocal.new(__method__.to_s, [ required, desc, default ])
Msf::OptAddress.new(__method__.to_s, [ required, desc, default ])

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.

I think we want to revert this change, if LHOST needs to be something else it should be up to the individual modules to override that like like you're doing elsewhere in the PR

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.

Already done - Opt::LHOST is back to OptAddress. OptAddressOrHostname is only on the reverse handlers.

@dwelch-r7 dwelch-r7 Jul 6, 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.

This has still changed? I think it needs to be reverted back to OptAddressLocal

Comment thread lib/msf/core/opt_address_or_hostname.rb Outdated
Comment on lines +45 to +59
if value =~ /^\d+(\.\d+)+$/
return Rex::Socket.is_ipv4?(value)
end

return true if Rex::Socket.is_ip_addr?(value)

if Rex::Socket.is_name?(value)
return true unless @resolve_names
begin
::Rex::Socket.getaddress(value, true)
return true
rescue
return false
end
end

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.

I think you just need to call super to address this, copilot is a bit wordy, but will need to verify that's all that's needed

Comment thread lib/msf/core/handler/reverse.rb Outdated

# No ReverseListenerBindAddress set — resolve LHOST to determine the
# bind address and whether to use IPv4 or IPv6 ANY as fallback.
addr_nbo = Rex::Socket.resolv_nbo(datastore['LHOST'])

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.

Won't this hit the same issue if LHOST is a domain name?

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.

Good catch. Added a rescue around the resolv_nbo call in both reverse.rb and reverse_udp.rb - if LHOST is a hostname that cannot be resolved locally, it falls back to binding on 0.0.0.0 and prints a warning suggesting ReverseListenerBindAddress.

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.

I think we're missing tests for when resolve_names is true

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.

Added - two tests: one where getaddress succeeds (hostname accepted) and one where it raises SocketError (hostname rejected).

Comment on lines -258 to +266
# Switch to IPv6 ANY address if the LHOST is also IPv6
addr = Rex::Socket.resolv_nbo(datastore['LHOST'])
# First attempt to bind LHOST. If that fails, the user probably has
# something else listening on that interface. Try again with ANY_ADDR.
any = (addr.length == 4) ? "0.0.0.0" : "::0"

addrs = [ Rex::Socket.addr_ntoa(addr), any ]

if not datastore['ReverseListenerBindAddress'].to_s.empty?
# Only try to bind to this specific interface
addrs = [ datastore['ReverseListenerBindAddress'] ]

# Pick the right "any" address if either wildcard is used
addrs[0] = any if (addrs[0] == "0.0.0.0" or addrs == "::0")
bind_addr = datastore['ReverseListenerBindAddress']
any = Rex::Socket.is_ipv6?(bind_addr) ? "::0" : "0.0.0.0"
return [ Rex::Socket.addr_atoi(bind_addr) == 0 ? any : bind_addr ]
end

addrs
addr_nbo = Rex::Socket.resolv_nbo(datastore['LHOST'])
addr = Rex::Socket.addr_ntoa(addr_nbo)
any = Rex::Socket.is_ipv4?(addr) ? "0.0.0.0" : "::0"

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.

This is missing some of the functionality of the bind_addresses method, namely missing is_loopback_address?

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.

Added - bind_address now warns if LHOST resolves to a loopback address. ReverseUdp does not include the Reverse module so is_loopback_address? is not available there; inlined the equivalent check.

Comment thread lib/msf/core/opt_address_or_hostname.rb Outdated
Comment on lines +41 to +50
# Reject anything that looks like a dotted-decimal number sequence
# (e.g. "192.0.2", "192.0.2.0.0") - Rex::Socket.is_name? accepts numeric
# DNS labels, so these would pass without this guard. Require it to be a
# valid IPv4 address, then delegate to parent for routable checks.
if value =~ /^\d+(\.\d+)+$/
return false unless Rex::Socket.is_ipv4?(value)
return super
end

return super if Rex::Socket.is_ip_addr?(value)

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.

Suggested change
# Reject anything that looks like a dotted-decimal number sequence
# (e.g. "192.0.2", "192.0.2.0.0") - Rex::Socket.is_name? accepts numeric
# DNS labels, so these would pass without this guard. Require it to be a
# valid IPv4 address, then delegate to parent for routable checks.
if value =~ /^\d+(\.\d+)+$/
return false unless Rex::Socket.is_ipv4?(value)
return super
end
return super if Rex::Socket.is_ip_addr?(value)
return super if Rex::Socket.is_ip_addr?(value)

I think most of this is redundant

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.

Done, removed the regex block. Also dropped 192.0.2 / 192.0.2.0.0 / 1.2.3.4.5 from invalid_values in the spec since those now pass as hostnames.

@dwelch-r7

Copy link
Copy Markdown
Contributor

@stzifkas seems like we have another test failure here, I think we're close to getting this landed though once that's passing I can give it one more manual test and we should be good to go

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

Labels

library rn-fix release notes fix

Projects

Status: In Progress

Development

Successfully merging this pull request may close these issues.

6 participants