fix(skill): blacklist Object.prototype member names as skill keys

napi_has_own_property does not catch toString/valueOf/etc. when the
ArkTS class instance already owns those names (injected by the Stage
model base class or by ArkTS compilation). Add an explicit blacklist of
Object.prototype member names plus __proto__ and the legacy dunder
accessors, and reject them in TryLoadSkillEntry and BuildSkillCallArgs
for both JsUIAbility and JsServiceExtension before the own-property
check.

Co-Authored-By: Agent
Signed-off-by: RuiChen_01 <chenrui193@huawei.com>

🤖‍ AI[100%] 👌 AI Adopted[100%] 🧑 Human[0%]
Co-authored-by: claude (glm-5.2) <ai@local>
This commit is contained in:
RuiChen_01
2026-06-21 17:14:25 +08:00
parent b80ed55df4
commit 434a65b3e4
2 changed files with 41 additions and 0 deletions
@@ -17,6 +17,7 @@
#include <cstdlib>
#include <regex>
#include <unordered_set>
#include "ability_business_error.h"
#include "ability_delegator_registry.h"
@@ -2611,6 +2612,16 @@ std::string ExtractBaseName(const std::string &path)
}
return path.substr(slashPos, dotPos - slashPos);
}
bool IsBlockedSkillKeyName(const std::string &name)
{
static const std::unordered_set<std::string> BLOCKED = {
"constructor", "__proto__", "__defineGetter__", "__defineSetter__",
"__lookupGetter__", "__lookupSetter__", "toString", "toLocaleString",
"valueOf", "hasOwnProperty", "isPrototypeOf", "propertyIsEnumerable"
};
return BLOCKED.count(name) > 0;
}
} // namespace
napi_value JsUIAbility::LoadSkillFunction(
@@ -2651,6 +2662,11 @@ bool JsUIAbility::TryLoadSkillEntry(const std::string &srcEntry,
const std::shared_ptr<AppExecFwk::SkillExecuteParam> &param,
napi_env env, napi_value &outJsObj, napi_value &method)
{
if (IsBlockedSkillKeyName(param->functionName_)) {
TAG_LOGW(AAFwkTag::UIABILITY, "blocked skill function name:%{public}s",
param->functionName_.c_str());
return false;
}
std::string srcPath(param->moduleName_ + "/" + srcEntry);
auto pos = srcPath.rfind('.');
if (pos == std::string::npos) {
@@ -2699,6 +2715,10 @@ std::vector<napi_value> JsUIAbility::BuildSkillCallArgs(napi_env env,
auto valStr = AppExecFwk::WantParams::GetStringByType(value, typeId);
TAG_LOGI(AAFwkTag::UIABILITY, "skillArg key:%{public}s value:%{public}s",
key.c_str(), valStr.c_str());
if (IsBlockedSkillKeyName(key)) {
TAG_LOGW(AAFwkTag::UIABILITY, "skip blocked skillArg key:%{public}s", key.c_str());
continue;
}
napi_value keyName = nullptr;
napi_create_string_utf8(env, key.c_str(), NAPI_AUTO_LENGTH, &keyName);
bool hasOwn = false;
@@ -15,6 +15,8 @@
#include "js_service_extension.h"
#include <unordered_set>
#include "ability_business_error.h"
#include "ability_handler.h"
#include "ability_info.h"
@@ -594,6 +596,16 @@ std::string ExtractBaseName(const std::string &path)
}
return path.substr(slashPos, dotPos - slashPos);
}
bool IsBlockedSkillKeyName(const std::string &name)
{
static const std::unordered_set<std::string> BLOCKED = {
"constructor", "__proto__", "__defineGetter__", "__defineSetter__",
"__lookupGetter__", "__lookupSetter__", "toString", "toLocaleString",
"valueOf", "hasOwnProperty", "isPrototypeOf", "propertyIsEnumerable"
};
return BLOCKED.count(name) > 0;
}
} // namespace
napi_value JsServiceExtension::LoadSkillFunction(
@@ -634,6 +646,11 @@ bool JsServiceExtension::TryLoadSkillEntry(const std::string &srcEntry,
const std::shared_ptr<AppExecFwk::SkillExecuteParam> &param,
napi_env env, napi_value &outJsObj, napi_value &method)
{
if (IsBlockedSkillKeyName(param->functionName_)) {
TAG_LOGW(AAFwkTag::SERVICE_EXT, "blocked skill function name:%{public}s",
param->functionName_.c_str());
return false;
}
std::string srcPath(param->moduleName_ + "/" + srcEntry);
auto pos = srcPath.rfind('.');
if (pos == std::string::npos) {
@@ -682,6 +699,10 @@ std::vector<napi_value> JsServiceExtension::BuildSkillCallArgs(napi_env env,
auto valStr = AppExecFwk::WantParams::GetStringByType(value, typeId);
TAG_LOGI(AAFwkTag::SERVICE_EXT, "skillArg key:%{public}s value:%{public}s",
key.c_str(), valStr.c_str());
if (IsBlockedSkillKeyName(key)) {
TAG_LOGW(AAFwkTag::SERVICE_EXT, "skip blocked skillArg key:%{public}s", key.c_str());
continue;
}
napi_value keyName = nullptr;
napi_create_string_utf8(env, key.c_str(), NAPI_AUTO_LENGTH, &keyName);
bool hasOwn = false;