Overview
This Skill is used for ArkWeb/Chromium C++ single-file thread-safety auditing, and only reports clear violations of the 10 standard rules in this document. The core goal is not to enumerate suspicious APIs, but to determine whether the current file simultaneously provides evidence of thread/sequence, asynchronous boundaries, object ownership, and lifecycle.
Pre-Audit Determination
- Confirm whether the file type and audit scope fall under ArkWeb/Chromium C++ single-file auditing.
- First determine the thread/sequence on which a function or callback may run, especially UI, IO, GPU, Audio, DrDC, IPC, or external callback threads.
- For asynchronous tasks, first confirm the execution path and object lifecycle, then determine the risk of a raw
this、base::Unretained(this)or cross-thread retention. - For UI thread objects, NWeb objects, GPU/Audio resources, and
mojo::Connector, first confirm whether the accessing thread and the object's owning thread are consistent. - Only report a violation when a clear object, thread path, asynchronous boundary, or lifecycle evidence can be identified.
Audit Decision Path
- Identify trigger points: prioritize searching for asynchronous boundaries, thread switches, mojo/IPC, external callbacks, UI/GPU/Audio/NWeb object access, and
scoped_refptrcross-thread passing. - Determine the executing thread: infer the current sequence from
CurrentlyOn、task runner、CEF_POST_TASK, BrowserThread, the binding location of the mojo receiver/connector, and function naming; if it cannot be inferred, do not directly report a violation. - Determine object ownership: confirm whether the accessed object requires use on the UI, GPU, Audio, DrDC, or creating thread.
- Determine lifecycle: in asynchronous tasks, report only when there is a raw
this、base::Unretained(this), cross-threadscoped_refptr, and the current file shows no owner, cancellation mechanism, orWeakPtrguarantee. - Choose a rule: assign the same evidence only to the most specific standard_rule; do not repeatedly report multiple generalized rules.
Scan Execution Order
Search for trigger points -> establish thread/sequence evidence -> confirm object ownership and lifecycle -> apply the rule matrix -> read only the examples of matched rules -> read team_mapping if necessary -> output complete JSON.
Evidence Strength and Rule Selection
- Strong evidence: the current file simultaneously contains a clear trigger point, thread or asynchronous boundary, constrained object, and missing forwarding/lifecycle guarantee, so a violation may be reported.
- Weak evidence: only a suspicious API or object can be seen, but the current file cannot confirm the executing thread, owner lifecycle, or cross-thread path, so no violation is reported.
- Prohibited reports: synchronous immediate calls, copying only within the same sequence
scoped_refptr, objects such as WebContents/Profile being passed across threads only after conversion to an ID, and existingWeakPtr/cancellation mechanism/clear owner covering the asynchronous task. - Self-check before reporting: each violation must be able to answer what the object is, what the current thread/sequence is, where the asynchronous or cross-thread boundary is, what guarantee is missing, and which line in the current file provides the evidence.
- When rules overlap, choose the more specific rule:
mojo::Connectorcross-thread prioritizes rule7, GPU mojo thread errors prioritize rule2,compositor_gpu_thread_prioritizes rule3, NWeb/BrowserContext/NavigationController prioritizes rule5, general Chromium UI object access falls under rule6, asynchronous rawthislifecycle falls under rule1, and cross-thread reference-counted objects fall under rule10. - Conflict example: cross-thread use in a GPU mojo callback
mojo::ConnectorWhen the core evidence is that connector sequence-affinity is broken, report rule7; when the core evidence is that an IPC callback directly handles GPU resources, report rule2. - Conflict example: the same asynchronous task both captures a raw
thisand holdsscoped_refptr<T>, the UAF evidence for the rawthisis reported as rule1; only when the cross-thread reference counting/destruction model is unsafe is rule10 additionally reported, to avoid reporting the same root cause twice. - When three or more rules overlap, choose the root cause in the order "object-specific thread constraints > resource thread constraints > general lifecycle/reference counting"; for the same code fragment, report only the most specific rule fully supported by the evidence in the current file.
- Complex overlap example: when an IPC callback both touches GPU resources, uses
mojo::Connector, and captures a rawthis, if the current file only proves the GPU resource is on the wrong thread, report rule2; only when it also proves the connector creation/use sequence is inconsistent is rule7 additionally reported; only when it proves the asynchronous callback may occur later than object destruction is rule1 additionally reported.
Uncertain Evidence Triage
- Missing creation/binding thread evidence: for
mojo::Connector, NWeb, Audio, GPU/DrDC objects, do not report cross-thread violations, because the object's owning thread cannot be proven. - Missing task runner ownership: when only
PostTaskis seen but the target runner's corresponding UI/GPU/Audio/DrDC cannot be seen, do not treat it as fixed or violating; continue searching forCurrentlyOn、RunsTasksInCurrentSequence, BrowserThread, or naming evidence, and if none is found, do not report. - Missing owner lifetime: when an asynchronous callback captures an object but the current file cannot show the destruction path, cancellation mechanism, or owner relationship, report only when raw
this/base::Unretained(this)and an asynchronous boundary both hold; otherwise do not extend to non-standard lifecycle issues. - Missing managed object type: when only a
scoped_refptr<T>variable is seen but the reference-counting base class, destruction sequence, or cross-thread usage path ofTcannot be seen, do not report rule10.
Recheck Before Determining No Violation
Before outputting an empty violations , at minimum recheck whether the current file omits the following evidence:
- Constructors, binding points for sequence, task runner, receiver, or connector in
Init*、Start*、Bind*、BindReceiver. - The initialization location, usage thread, and destruction/cancellation path of member
*_task_runner_、receiver_、connector_、weak_factory_. - Whether the callback is forwarded a second time through helpers such as
On*、Did*、Notify*、Run*、Create*On*Thread, causing the real execution thread to be hidden in other functions in the same file. - Whether object destruction,
InvalidateWeakPtrs, task cancellation, and owner holding relationships are visible in the current file; when there is still no evidence, keep violations empty and do not output guessed fields.
False Positive Control
- Do not report a violation based only on "missing thread check" or "possible multithreaded call".
- Do not misjudge a synchronous call as an asynchronous lifecycle problem.
- When the evidence is insufficient to confirm a violation, do not report a violation; risks that require cross-file confirmation should also be based on the evidence visible in the current file.
- Issues that do not belong to the 10 standard rules in this document must not be output as violations.
- The final review result may only output JSON, and must not output Markdown, explanatory text, or code fences.
Never Report Boundary
- rule1: only
base::Unretained(this)is seen, but the callback executes synchronously and immediately, the object lifetime is covered by an owner visible in the current file, or it already usesWeakPtrWhen the mechanism is cancelled, do not report; otherwise performance optimizations or synchronous bindings will be misjudged as UAF. - rule5/rule6: Only pass value types such as frame tree node id, process id, routing id, URL, strings, and configuration snapshots across threads; do not report cross-thread access to UI objects; these values are detached from the UI object lifecycle and are not equivalent to cross-thread dereferencing.
- rule7: When only seeing
mojo::Connectormember declarations or use within the same sequence, and it cannot be confirmed that the creation and use sequences are inconsistent, do not report;mojo::Connectorrisk comes from sequence-affinity being broken, which may cause DCHECKs, out-of-order messages, or race crashes, rather than the type itself. - rule8: When only seeing an Audio method name, and it cannot be confirmed that the current entry comes from a non-Audio thread or has already been posted through the audio task runner, do not report; Audio lifecycle method names are often encapsulated, and evidence of the entry thread is required.
- rule10:
scoped_refptr<T>itself is not a violation; only report whenT's reference counting, destruction sequence, or method access model does not support cross-threading, and the current file has evidence of cross-thread holding/passing; otherwise normal reference-counting lifecycle management will be misjudged as a cross-thread memory risk.
Supplementary Materials
examples/ stores good/bad self-contained examples split according to the standard rules.
Example reading rules:
- MANDATORY READ: When a key code pattern of a standard rule is hit and you are preparing to determine whether to report, you must read the bad example corresponding to that rule; when you need to confirm boundaries or remediation methods, then read the corresponding good example.
- When you need to distinguish false-positive boundaries, read the bad example first, then compare it with the good example.
- DO NOT LOAD: When a rule keyword is not hit, do not load that rule's example; do not load examples for irrelevant rules, and do not use paths, class names, or line numbers from examples to replace evidence from the file currently under review.
| Triggering Rule | Key Pattern | Required Example |
|---|---|---|
| standard_rule1 | base::Unretained(this)、BindOnce、BindRepeating, executed after being saved by an asynchronous callback |
examples/bad/standard_rule1_unretained_this.md; if necessary, compare with examples/good/standard_rule1_unretained_this.md |
| standard_rule2 | GPU mojo callback, IPC thread handling GPU resources | examples/bad/standard_rule2_gpu_mojo_thread.md; if necessary, compare with examples/good/standard_rule2_gpu_mojo_thread.md |
| standard_rule3 | compositor_gpu_thread_ direct call |
examples/bad/standard_rule3_drdc_thread.md; if necessary, compare with examples/good/standard_rule3_drdc_thread.md |
| standard_rule4 | NDK interface, out-of-domain callback, non-UI thread call | examples/bad/standard_rule4_ndk_ui_thread.md; if necessary, compare with examples/good/standard_rule4_ndk_ui_thread.md |
| standard_rule5 | Perf, BrowserContext, NavigationController, NWeb object access | examples/bad/standard_rule5_nweb_ui_thread.md; if necessary, compare with examples/good/standard_rule5_nweb_ui_thread.md |
| standard_rule6 | Access to Chromium UI objects such as WebContents, Profile, RenderFrameHost | examples/bad/standard_rule6_ui_object_access.md; if necessary, compare with examples/good/standard_rule6_ui_object_access.md |
| standard_rule7 | mojo::Connector creation thread and use thread are inconsistent |
examples/bad/standard_rule7_mojo_connector.md; if necessary, compare with examples/good/standard_rule7_mojo_connector.md |
| standard_rule8 | Audio start, pause, stop, close operations | examples/bad/standard_rule8_audio_thread.md; if necessary, compare with examples/good/standard_rule8_audio_thread.md |
| standard_rule9 | CEF_POST_TASK depends on the Web instance |
examples/bad/standard_rule9_cef_post_task.md; if necessary, compare with examples/good/standard_rule9_cef_post_task.md |
| standard_rule10 | scoped_refptr cross-thread passing or multi-thread holding |
examples/bad/standard_rule10_scoped_refptr.md; if necessary, compare with examples/good/standard_rule10_scoped_refptr.md |
| Insufficient evidence | Only suspicious APIs, value types passed across threads, missing thread/owner evidence | Compare with examples/good/no_violation_uncertain_thread.md and examples/good/no_violation_id_transfer.md |
Rule Determination Matrix
| Rule | Triggering Evidence | Required Reporting Evidence | Do Not Report Condition |
|---|---|---|---|
| standard_rule1 | PostTask, delay, ThreadPool, mojo/IPC, NDK or external callback binding a raw this/base::Unretained(this) |
The current file does not show WeakPtr, cancellation mechanism, or owner lifecycle coverage, and the callback may execute after the object is destroyed |
Synchronous immediate execution, sufficient lifecycle evidence, and already uses WeakPtr or a cancellation mechanism |
| standard_rule2 | GPU mojo callback, IPC thread receives GPU operation | GPU resources or GPU interfaces are used directly on the IPC/current callback thread and are not posted to the GPU thread | Only forwards parameters without touching GPU resources, or has been posted to the target GPU task runner |
| standard_rule3 | compositor_gpu_thread_ member call |
The call occurs at a UI/IPC/non-DrDC entry point and is not forwarded through the DrDC task runner | The current code is already executing on the DrDC task runner |
| standard_rule4 | NDK interface, cross-domain interaction callback, application-side callback entry point | The current entry point is not the UI thread, yet it still directly calls the NDK/external callback | The UI thread has been checked or it has already been PostTask to the UI thread |
| standard_rule5 | Perf, BrowserContext, NavigationController, NWeb object access | The current entry point is not the UI thread and directly reads/writes these UI-owned objects | Only passes ID/value snapshots, or access has already been forwarded to the UI thread |
| standard_rule6 | Chromium UI objects such as WebContents, Profile, RenderFrameHost, RenderProcessHost | A non-UI thread directly dereferences or calls object methods | Only passes stable IDs/weak reference tokens across threads, or returns to the UI thread before accessing |
| standard_rule7 | mojo::Connector creation, binding,Accept、Close, sending messages |
The current file simultaneously shows that the creation/binding sequence and the usage sequence are inconsistent | Only declaration, use on the same sequence, or missing creation thread evidence |
| standard_rule8 | Audio start/pause/stop/close, audio callback entry point, audio task runner | A non-Audio thread directly performs audio lifecycle operations | Has been posted through the audio task runner, or the entry point can be confirmed to be on the Audio thread |
| standard_rule9 | CEF_POST_TASK posts a task that depends on a Web instance |
Before posting, it does not check that the corresponding Web instance has been created/is still available; the current file has an initialization race | Before posting, there is already an instance check, or the task does not depend on a Web instance |
| standard_rule10 | scoped_refptr<T> cross-thread passing, multi-thread holding, async task capture |
Must confirm whether T 's reference-counted base class and object access path are thread-safe;base::RefCounted objects must not be held/released across threads |
Only copied within the same sequence, or T explicitly uses base::RefCountedThreadSafe and supports cross-thread access |
Rule level
The rule level is used to indicate the priority of violation risk and does not affect whether a violation is reported. All violations must still meet the explicit evidence requirements in this document.
| Level | Standard rule ID | Reporting policy |
|---|---|---|
| P1 | standard_rule1, standard_rule2, standard_rule3, standard_rule6, standard_rule7, standard_rule10 | Prioritize reporting and fixing; usually involves UAF, cross-thread UI/GPU/DrDC/mojo sequence corruption, or reference-count races |
| P2 | standard_rule4, standard_rule5, standard_rule8, standard_rule9 | Normal reporting; usually involves UI/Audio thread contracts, NWeb/BrowserContext access constraints, or Web instance lifecycle preconditions |
Reporting requirements:
- All violations must include the
rule_levelfield and remain consistent with the table above. - Do not report based solely on "missing thread check" or "possible multi-threaded call"; you must point out a clear object, cross-thread path, or lifecycle evidence.
Standard rule index
Use the "rule decision matrix" as the primary rule source; this section only provides rule_id and rule_name, to avoid drift from the matrix.
| rule_id | rule_name |
|---|---|
| standard_rule1 | Async task bare this lifecycle constraint |
| standard_rule2 | GPU mojo task thread constraint |
| standard_rule3 | compositor_gpu_thread_ DrDC thread constraint |
| standard_rule4 | NDK interface and out-of-domain callback UI thread constraint |
| standard_rule5 | NWeb-related object UI thread constraint |
| standard_rule6 | Chromium UI thread object access constraint |
| standard_rule7 | mojo::Connector cross-thread constraint |
| standard_rule8 | Audio operation Audio thread constraint |
| standard_rule9 | CEF_POST_TASK Web instance creation constraint |
| standard_rule10 | scoped_refptr thread safety constraint |
Module responsibility division
Prioritize selecting the team based on the functional module and file path to which the code belongs; if a rule is related to multiple teams, the team that directly owns the accessed object or interface prevails. When the current file cannot be reliably determined, choose the closest functional team and write the basis in issue ; do not add non-standard rules because ownership is uncertain.
When outputting a violation, you must fill in team. If the team cannot be directly determined from the path, object, or interface, you must read references/team_mapping.md; if it still cannot be determined, fill in the closest team and explain the basis in issue .
Review output format
This Skill focuses onsingle-file scanning。
Output uses JSON only, facilitating toolchain parsing and result aggregation.
Format constraints (must be strictly followed)
- Output JSON only; do not add Markdown, explanatory text, code fences, or extra sections.
- Violation rules must come from the standard rules defined in this document。
- The rule number must be attached:
rule_idusestandard_rule<N>,rule_nameuse the corresponding standard rule name. - The rule severity must be attached: each violation must output according to the "rule severity" table
rule_level。 - When there are no violations, the complete JSON structure must still be output,
violationsthe array is empty. - When evidence is insufficient, the schema must not be extended: do not output
uncertain、finding、note、riskand other custom fields; insufficient evidence means no violation. - Output fields must not be fabricated:
anti_patternmay only excerpt code visible in the current file;required_fixwhen precise code cannot be given, write the minimal fix direction, such as "PostTask to the target thread" or "switch to WeakPtr"; do not invent nonexistent function names, runner names, paths, or team ownership. - When the output is uncertain, read examples as needed: if you are unsure how the no-violation JSON,
required_fixor multi-rule conflicts should fit the schema, readreferences/output_examples.md。
JSON format
{
"scan_info": {
"file_path": "<文件绝对路径>",
"skill": "arkweb-thread-safety-review"
},
"summary": {
"total_violations": 0,
"by_rule": {
"<规则编号>": <数量>
},
"by_team": {
"<团队名称>": <数量>
}
},
"violations": [
{
"id": 1,
"rule_id": "<规则编号,如 standard_rule1>",
"rule_name": "<规则名称>",
"rule_level": "<规则等级,如 P2>",
"location": {
"file": "<文件名>",
"line": <行号>,
"function": "<函数名>"
},
"issue": "<问题描述>",
"anti_pattern": "<违规代码片段>",
"required_fix": "<最小修复方向或当前文件可见的修复片段>",
"impact": "<违反后果>",
"team": "<责任团队>"
}
]
}
When there are no violations:violations the array is empty [],summary.total_violations is 0,by_rule and by_team are empty objects {}。