From 2c6d4c2de2d1c96c4d08d33e23a754f6693fb829 Mon Sep 17 00:00:00 2001 From: songkeyuan Date: Sun, 23 Aug 2026 20:57:31 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E6=93=A6=E9=99=A4want=E5=8F=82=E6=95=B0?= =?UTF-8?q?,=20Co-Authored-By:=20Agent?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: songkeyuan --- .../inner/napi_common/napi_common_want.cpp | 25 ++++--- test/unittest/napi_common_want_test/BUILD.gn | 2 + .../napi_common_want_test.cpp | 71 +++++++++++++++++++ 3 files changed, 90 insertions(+), 8 deletions(-) diff --git a/frameworks/js/napi/inner/napi_common/napi_common_want.cpp b/frameworks/js/napi/inner/napi_common/napi_common_want.cpp index 4e64e407b1..81a339dbff 100644 --- a/frameworks/js/napi/inner/napi_common/napi_common_want.cpp +++ b/frameworks/js/napi/inner/napi_common/napi_common_want.cpp @@ -1097,9 +1097,18 @@ napi_value WrapWant(napi_env env, const Want &want) napi_value jsObject = nullptr; napi_value jsValue = nullptr; + // PARAM_SET_URI_WITH_ORIGIN_STRING is an internal system parameter used to + // pass through an origin uri that bypasses scheme validation. It must not be + // exposed to third-party apps, so it is stripped here for non-system apps. + Want wrapWant = want; + auto selfToken = IPCSkeleton::GetSelfTokenID(); + if (!Security::AccessToken::TokenIdKit::IsSystemAppByFullTokenID(selfToken)) { + wrapWant.RemoveParam(Want::PARAM_SET_URI_WITH_ORIGIN_STRING); + } + NAPI_CALL(env, napi_create_object(env, &jsObject)); - napi_value jsElementName = WrapElementName(env, want.GetElement()); + napi_value jsElementName = WrapElementName(env, wrapWant.GetElement()); if (jsElementName == nullptr) { TAG_LOGI(AAFwkTag::JSNAPI, "null jsElementName"); return nullptr; @@ -1121,31 +1130,31 @@ napi_value WrapWant(napi_env env, const Want &want) SetPropertyValueByPropertyName(env, jsObject, "moduleName", jsValue); jsValue = nullptr; - jsValue = WrapStringToJS(env, want.GetUriString()); + jsValue = WrapStringToJS(env, wrapWant.GetUriString()); SetPropertyValueByPropertyName(env, jsObject, "uri", jsValue); jsValue = nullptr; - jsValue = WrapStringToJS(env, want.GetType()); + jsValue = WrapStringToJS(env, wrapWant.GetType()); SetPropertyValueByPropertyName(env, jsObject, "type", jsValue); jsValue = nullptr; - jsValue = WrapInt32ToJS(env, want.GetFlags()); + jsValue = WrapInt32ToJS(env, wrapWant.GetFlags()); SetPropertyValueByPropertyName(env, jsObject, "flags", jsValue); jsValue = nullptr; - jsValue = WrapStringToJS(env, want.GetAction()); + jsValue = WrapStringToJS(env, wrapWant.GetAction()); SetPropertyValueByPropertyName(env, jsObject, "action", jsValue); jsValue = nullptr; - jsValue = WrapWantParams(env, want.GetParams()); + jsValue = WrapWantParams(env, wrapWant.GetParams()); SetPropertyValueByPropertyName(env, jsObject, "parameters", jsValue); jsValue = nullptr; - jsValue = WrapWantParamsFD(env, want.GetParams()); + jsValue = WrapWantParamsFD(env, wrapWant.GetParams()); SetPropertyValueByPropertyName(env, jsObject, "fds", jsValue); jsValue = nullptr; - jsValue = WrapArrayStringToJS(env, want.GetEntities()); + jsValue = WrapArrayStringToJS(env, wrapWant.GetEntities()); SetPropertyValueByPropertyName(env, jsObject, "entities", jsValue); return handleEscape.Escape(jsObject); diff --git a/test/unittest/napi_common_want_test/BUILD.gn b/test/unittest/napi_common_want_test/BUILD.gn index 0306bc5511..0a5a71aca8 100644 --- a/test/unittest/napi_common_want_test/BUILD.gn +++ b/test/unittest/napi_common_want_test/BUILD.gn @@ -20,6 +20,7 @@ ohos_unittest("napi_common_want_test") { include_dirs = [ "${ability_runtime_path}/frameworks/js/napi/inner/napi_common", + "${ability_runtime_path}/interfaces/inner_api/runtime/include", ] sources = [ @@ -30,6 +31,7 @@ ohos_unittest("napi_common_want_test") { "${ability_runtime_innerkits_path}/runtime:runtime", "${ability_runtime_napi_path}/inner/napi_common:napi_common", "${ability_runtime_innerkits_path}/wantagent:wantagent_innerkits", + "${ability_runtime_path}/js_environment/frameworks/js_environment:js_environment", ] external_deps = [ diff --git a/test/unittest/napi_common_want_test/napi_common_want_test.cpp b/test/unittest/napi_common_want_test/napi_common_want_test.cpp index c7b2f37de9..b6dfbd9526 100644 --- a/test/unittest/napi_common_want_test/napi_common_want_test.cpp +++ b/test/unittest/napi_common_want_test/napi_common_want_test.cpp @@ -18,6 +18,8 @@ #include "access_token.h" #include "hilog_tag_wrapper.h" +#include "js_runtime_lite.h" +#include "napi_common_util.h" #include "napi_common_want.h" #include "napi/native_api.h" #include "token_setproc.h" @@ -240,5 +242,74 @@ HWTEST_F(NapiCommonWantTest, UnwrapWantParams_NullParam_0100, Function | MediumT bool result = UnwrapWantParams(env, param, wantParams); EXPECT_FALSE(result); } + +/** + * @tc.name: WrapWant_NonSystemApp_StripsPassThroughFlag_0100 + * @tc.desc: Non-system app is the final hop, the pass-through flag is stripped + * when the want is wrapped to the JS layer. + */ +HWTEST_F(NapiCommonWantTest, WrapWant_NonSystemApp_StripsPassThroughFlag_0100, Function | MediumTest | Level1) +{ + uint64_t originalToken = GetSelfTokenID(); + SetSelfTokenID(0); + + AbilityRuntime::Runtime::Options options; + std::shared_ptr jsEnv = nullptr; + AbilityRuntime::JsRuntimeLite::GetInstance().CreateJsEnv(options, jsEnv); + ASSERT_NE(jsEnv, nullptr); + napi_env env = reinterpret_cast(jsEnv->GetNativeEngine()); + ASSERT_NE(env, nullptr); + + AAFwk::Want want; + want.SetParam(AAFwk::Want::PARAM_SET_URI_WITH_ORIGIN_STRING, true); + napi_value jsWant = WrapWant(env, want); + ASSERT_NE(jsWant, nullptr); + + napi_value jsParams = GetPropertyValueByPropertyName(env, jsWant, "parameters", napi_object); + ASSERT_NE(jsParams, nullptr); + EXPECT_FALSE(IsExistsByPropertyName(env, jsParams, + AAFwk::Want::PARAM_SET_URI_WITH_ORIGIN_STRING.c_str())); + + AbilityRuntime::JsRuntimeLite::GetInstance().RemoveJsEnv(env); + SetSelfTokenID(originalToken); +} + +/** + * @tc.name: WrapWant_SystemApp_KeepsPassThroughFlag_0100 + * @tc.desc: System app may keep forwarding, the pass-through flag is preserved + * when the want is wrapped to the JS layer. + */ +HWTEST_F(NapiCommonWantTest, WrapWant_SystemApp_KeepsPassThroughFlag_0100, Function | MediumTest | Level1) +{ + uint64_t originalToken = GetSelfTokenID(); + + uint64_t systemAppMask = (static_cast(1) << 32); + uint32_t tokenID = Security::AccessToken::DEFAULT_TOKEN_VERSION; + Security::AccessToken::AccessTokenIDInner *idInner = + reinterpret_cast(&tokenID); + idInner->type = Security::AccessToken::TOKEN_HAP; + uint64_t fullTokenId = systemAppMask | tokenID; + SetSelfTokenID(fullTokenId); + + AbilityRuntime::Runtime::Options options; + std::shared_ptr jsEnv = nullptr; + AbilityRuntime::JsRuntimeLite::GetInstance().CreateJsEnv(options, jsEnv); + ASSERT_NE(jsEnv, nullptr); + napi_env env = reinterpret_cast(jsEnv->GetNativeEngine()); + ASSERT_NE(env, nullptr); + + AAFwk::Want want; + want.SetParam(AAFwk::Want::PARAM_SET_URI_WITH_ORIGIN_STRING, true); + napi_value jsWant = WrapWant(env, want); + ASSERT_NE(jsWant, nullptr); + + napi_value jsParams = GetPropertyValueByPropertyName(env, jsWant, "parameters", napi_object); + ASSERT_NE(jsParams, nullptr); + EXPECT_TRUE(IsExistsByPropertyName(env, jsParams, + AAFwk::Want::PARAM_SET_URI_WITH_ORIGIN_STRING.c_str())); + + AbilityRuntime::JsRuntimeLite::GetInstance().RemoveJsEnv(env); + SetSelfTokenID(originalToken); +} } // namespace AppExecFwk } // namespace OHOS