Loading...
Loading...
Use when reviewing OpenHarmony C++ system service code for security vulnerabilities, particularly IPC handlers, multithreaded components, or code handling sensitive user data
npx skill4agent add openharmonyinsight/openharmony-skills openharmony-security-reviewdigraph when_to_use {
"Reviewing OpenHarmony code?" [shape=diamond];
"Is it C++ system service?" [shape=diamond];
"Handles IPC/network data?" [shape=diamond];
"Has shared state?" [shape=diamond];
"Logs data?" [shape=diamond];
"Use this skill" [shape=box];
"Different skill needed" [shape=box];
"Reviewing OpenHarmony code?" -> "Different skill needed" [label="no"];
"Reviewing OpenHarmony code?" -> "Is it C++ system service?" [label="yes"];
"Is it C++ system service?" -> "Different skill needed" [label="no"];
"Is it C++ system service?" -> "Handles IPC/network data?" [label="yes"];
"Handles IPC/network data?" -> "Use this skill" [label="yes"];
"Handles IPC/network data?" -> "Has shared state?" [label="no"];
"Has shared state?" -> "Use this skill" [label="yes"];
"Has shared state?" -> "Logs data?" [label="no"];
"Logs data?" -> "Use this skill" [label="yes"];
"Logs data?" -> "Different skill needed" [label="no"];
}| Category | Critical Checks | Severity |
|---|---|---|
| IPC Deserialization | All MessageParcel reads checked for success | HIGH |
| Logical Validation | Array lengths/indices validated AFTER deserialization | HIGH |
| Integer Bounds | Size variables: | HIGH |
| Object Lifecycle | RemoteObjects/fd validated before use (nullptr check) | HIGH |
| Parser Security | Network parsers reject malformed input, prevent recursion attacks | HIGH |
| Container Thread Safety | All container operations protected (read/write, write/write) | HIGH |
| Iterator Invalidation** | No modification while iterating | HIGH |
| Lock Consistency | All shared state access protected by mutex | HIGH |
| Deadlock Risk | Nested locks acquired in consistent order | HIGH |
| TOCTOU | State checks immediately followed by dependent action | HIGH |
| PII in Logs | No phone numbers, contacts, SMS, biometrics in logs | HIGH |
| Input Events in Logs** | No raw KeyEvents, touch coordinates, screen bounds | HIGH |
| Pointer Addresses | No | HIGH |
| Permission Check | All privileged operations validate caller permissions | HIGH |
// ❌ VULNERABLE: No validation
parcel.ReadInt32(val);
int32_t size = parcel.ReadInt32();// ✅ SECURE: Always check return value
if (!parcel.ReadInt32(val)) {
HILOG_ERROR("Failed to read value");
return ERR_INVALID_DATA;
}
if (!parcel.ReadInt32(size)) {
HILOG_ERROR("Failed to read size");
return ERR_INVALID_DATA;
}size = 0xFFFFFFFFnew char[size]// ❌ VULNERABLE: No bounds validation
int32_t size = parcel.ReadInt32();
std::vector<char> buffer(size); // May allocate gigabytes or overflow// ✅ SECURE: Validate bounds immediately
int32_t size = 0;
if (!parcel.ReadInt32(size)) {
return ERR_INVALID_DATA;
}
constexpr int32_t MAX_ALLOWED_BUFFER = 1024 * 1024; // 1MB
if (size < 0 || size > MAX_ALLOWED_BUFFER) {
HILOG_ERROR("Invalid size: %{public}d", size);
return ERR_INVALID_DATA;
}
std::vector<char> buffer(size);// ✅ SECURE: Validate before use
if (remoteObject == nullptr) {
HILOG_ERROR("Received null RemoteObject");
return ERR_NULL_OBJECT;
}
if (fd < 0) {
HILOG_ERROR("Invalid file descriptor");
return ERR_INVALID_FD;
}// ❌ VULNERABLE: Unprotected concurrent access
std::vector<int> items_;
void AddItem(int item) {
items_.push_back(item); // Unsafe if called concurrently
}
void ProcessItems() {
for (auto& item : items_) { // Iteration
// If AddItem called here, iterator invalidates → CRASH
}
}// ✅ SECURE: All access protected
std::vector<int> items_;
std::mutex itemsMutex_;
void AddItem(int item) {
std::lock_guard<std::mutex> lock(itemsMutex_);
items_.push_back(item);
}
void ProcessItems() {
std::lock_guard<std::mutex> lock(itemsMutex_);
for (auto& item : items_) {
// Safe - lock held during iteration
}
}std::vectorstd::mapstd::liststd::unordered_mapstd::stringpush_backinserteraseoperator[]atstd::mutexstd::shared_mutexSpinLock// ❌ VULNERABLE: Inconsistent protection
class Service {
std::map<int, Data> dataMap_;
std::mutex mutex_;
void Update(int key, const Data& data) {
std::lock_guard<std::mutex> lock(mutex_);
dataMap_[key] = data;
}
Data Lookup(int key) {
// ❌ NO LOCK - race condition with Update
return dataMap_[key];
}
};// ✅ SECURE: Consistent protection
class Service {
std::map<int, Data> dataMap_;
std::mutex mutex_;
void Update(int key, const Data& data) {
std::lock_guard<std::mutex> lock(mutex_);
dataMap_[key] = data;
}
Data Lookup(int key) {
std::lock_guard<std::mutex> lock(mutex_);
return dataMap_[key];
}
};// ❌ VULNERABLE: Deadlock risk
void Path1() {
std::lock_guard<std::mutex> lock1(mutex1_);
std::lock_guard<std::mutex> lock2(mutex2_); // Order: 1 then 2
}
void Path2() {
std::lock_guard<std::mutex> lock2(mutex2_);
std::lock_guard<std::mutex> lock1(mutex1_); // Order: 2 then 1 → DEADLOCK
}// ✅ SECURE: Consistent lock order
void Path1() {
std::lock_guard<std::mutex> lock1(mutex1_);
std::lock_guard<std::mutex> lock2(mutex2_); // Order: 1 then 2
}
void Path2() {
std::lock_guard<std::mutex> lock1(mutex1_); // Same order: 1 then 2
std::lock_guard<std::mutex> lock2(mutex2_);
}// ❌ VULNERABLE: TOCTOU window
if (fileExists(path)) {
// Attacker can delete/replace file here
file = openFile(path); // May open different file
}// ✅ SECURE: Atomic check-and-use
file = openFile(path);
if (file.isValid()) {
// Use file
}// ❌ VULNERABLE: Logs PII
HILOG_INFO("Phone: %{public}s", phoneNumber.c_str());
HILOG_ERROR("Touch at (%{public}d, %{public}d)", x, y);// ✅ SECURE: Redact or suppress
HILOG_INFO("Phone: %{private}s", phoneNumber.c_str()); // Redacted
// Better: Don't log PII at all
HILOG_INFO("Processing phone number");%{private}// ❌ VULNERABLE: Leaks addresses for ASLR bypass
HILOG_INFO("Object at %p", &object);
HILOG_DEBUG("Buffer address: %{public}p", buffer);// ✅ SECURE: No address logging
HILOG_INFO("Object created");
// Use opaque IDs instead of pointers
HILOG_INFO("Object ID: %{public}d", object.id_);// ❌ VULNERABLE: No permission check
int32_t Service::DeleteFile(const std::string& path) {
// Any caller can delete any file!
return unlink(path.c_str());
}// ✅ SECURE: Validate permissions
int32_t Service::DeleteFile(const std::string& path) {
// Verify caller has permission to access this path
if (!HasPermission(callerToken_, path, Permission::DELETE)) {
HILOG_ERROR("Permission denied for path: %{private}s", path.c_str());
return ERR_PERMISSION_DENIED;
}
// Verify path is within allowed sandbox
if (!IsPathInSandbox(path)) {
HILOG_ERROR("Path outside sandbox: %{private}s", path.c_str());
return ERR_INVALID_PATH;
}
return unlink(path.c_str());
}| Mistake | Consequence | Fix |
|---|---|---|
| Forgetting to check MessageParcel return values | Uninitialized data use, crashes | Always check return value |
| Validating size but not lower bound (negative) | Negative sizes pass validation | Check |
| Protecting write but not read on shared container | Race condition during reads | Protect ALL access |
| Using iterator after container modification | Iterator invalidation, crashes | Hold lock during iteration |
Logging with | Information leakage | Use |
| Printing pointer addresses for debugging | ASLR bypass | Use opaque IDs |
| Skipping permission check "because it's internal" | Privilege escalation if called externally | Always validate |
**[HIGH SECURITY RISK] <Category>**
Location: <file_path>:<line_number>
Issue: <description>
Anti-pattern:
```cpp
<code><code>
## Real-World Impact
**Container race conditions:** Use-after-free crashes, privilege escalation through corrupted state
**IPC validation failures:** Remote code execution via deserialization exploits, memory exhaustion DoS
**PII leakage:** Privacy violations, GDPR compliance failures
**ASLR bypass:** Enables exploitation of memory corruption vulnerabilities
**Missing permission checks:** Unauthorized access to sensitive data, system modification