• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# ArkGuard for Code Obfuscation
2
3## Overview
4
5Source code obfuscation helps reduce the risk of application hacking as well as the application package size by shortening class names and member names.
6
7>**NOTE**
8>
9> 1. In DevEco Studio versions prior to 5.0.3.600, code obfuscation is enabled by default for new projects, and code developed on the stage model using API version 10 or later is automatically obfuscated. This applies only to code compiled in [release mode](#remarks), and obfuscation applies only to parameter names and local variable names.
10> 2. In DevEco Studio 5.0.3.600 and later versions, code obfuscation is disabled by default for new projects. If you want to enable obfuscation, set the **ruleOptions.enable** field in the **build-profile.json5** file of the module to **true**. The **obfuscation-rules.txt** file has the following options enabled by default: **-enable-property-obfuscation**, **-enable-toplevel-obfuscation**, **-enable-filename-obfuscation**, and **-enable-export-obfuscation**. You can customize the obfuscation settings as needed. Enabling the four options may cause the application to crash at runtime. You are advised to read [Enabling Code Obfuscation](#enabling-code-obfuscation) to rectify the fault.
11
12### Constraints
13
14* Only the projects developed on the stage model are supported.
15* The build mode of the project is release.
16
17### Code Obfuscation Scope
18
19In a project, the following files can be obfuscated, and the cache files after obfuscation are stored in **build/[...]/release** in the module directory.
20
21* ArkTS files
22* TS files
23* JS files
24
25### Limitations
26
27**Language Limitations**
28
29Code obfuscation tools vary in type analysis mechanisms, obfuscation strategies, and execution efficiency based on the target language. For example, ProGuard targets strongly-typed languages like Java, where each type has a clear definition source. This feature makes the type relationship tracing and processing in the obfuscation process more accurate, greatly reducing the need for retention rules.
30
31In contrast, ArkGuard targets JS, TS, and ArkTS. JS supports dynamic modification of objects and functions at runtime, but obfuscation is a static process in the compilation phase. This difference may cause a failure in parsing obfuscated named at runtime, resulting in runtime exceptions. TS and ArkTS use a structural type system, where different named types with the same structure are considered as equivalent types. Therefore, it is difficult to trace the exact source of types. As such, when using ArkGuard, you need to configure trustlists for more syntax scenarios. Moreover, ArkGuard uses a global property retention mechanism that retains all properties with the same name according to the trustlist. It does not support precise retention settings for specific types.
32
33To illustrate, consider this example:
34
35Assume that ArkGuard allows the configuration of a trustlist for specific types. If class A1 is configured in a trustlist with its property prop1, but prop1 in class A2 is not in the trustlist, passing an instance of A2 (a2) to the **test** function would cause issues when accessing the prop1 property.
36
37```typescript
38// Before obfuscation:
39class A1 {
40  prop1: string = '';
41}
42
43class A2 {
44  prop1: string = '';
45}
46
47function test(input: A1) {
48  console.log(input.prop1);
49}
50
51let a2 = new A2();
52a2.prop1 = 'prop a2';
53test(a2);
54```
55
56```typescript
57// After obfuscation:
58class A1 {
59  prop1: string = '';
60}
61
62class A2 {
63  a: string = '';
64}
65
66function test(input: A1) {
67  console.log(input.prop1);
68}
69
70let a2 = new A2();
71a2.a = 'prop a2';
72test(a2);
73```
74
75You should be aware of these differences and use unique names to achieve better obfuscation results.
76
77**Limited Security Assurance**
78
79Like other obfuscation tools, ArkGuard increases reverse engineering difficulty but cannot prevent it entirely.
80
81You should not rely solely on ArkGuard for security. For higher security requirements, consider [application encryption](https://developer.huawei.com/consumer/en/doc/harmonyos-guides-V5/code-protect-V5) and third-party hardening measures.
82
83## Enabling Code Obfuscation
84
85### How to Use
86Code obfuscation has been integrated into the system and can be enabled for use in DevEco Studio.
87
88* Enabling the obfuscation switch
89
90   To enable obfuscation, set the **enable** field to **true** under **arkOptions.obfuscation.ruleOptions** in the **build-profile.json5** file of your module. The default values of the **enable** field may vary across different versions of DevEco Studio. For details, see [version differences](#overview).
91    ```
92    "arkOptions": {
93      "obfuscation": {
94        "ruleOptions": {
95          "enable": true,
96          "files": ["./obfuscation-rules.txt"],
97        }
98      }
99    }
100    ```
101
102* Configuring obfuscation rules
103
104   Enabling the obfuscation switch activates the default settings, which include obfuscation of local variables and parameters. To enable additional obfuscation features, customize the **obfuscation-rules.txt** file specified in the **files** field. The default values in the **obfuscation-rules.txt** file may vary across different versions of DevEco Studio. For details, see [version differences](#overview).
105
106* Specifying release compilation
107
108   Currently, code obfuscation is supported only for release builds, not for debug builds. This means that obfuscation will only be applied when a module is compiled in release mode, not in debug mode. You can view and modify the build mode by referring to [Specifying a Build Mode](https://developer.huawei.com/consumer/en/doc/harmonyos-guides-V5/ide-hvigor-compilation-options-customizing-guide-V5#section192461528194916).
109
110    > **NOTE**
111    >
112    > The differences between release and debug builds extend beyond obfuscation. To determine whether application behavior differences are due to obfuscation, you should enable or disable the obfuscation switch rather than simply switching between release and debug builds.
113
114### Obfuscation Configuration Files
115* `obfuscation-rules.txt`
116
117   For HAP, HAR, and HSP modules, the **arkOptions.obfuscation.ruleOptions.files** field in the **build-profile.json5** file specifies obfuscation rules applied during module compilation. A default **obfuscation-rules.txt** file is created when a new project is set up.
118
119* `consumer-rules.txt`
120
121   For HAR modules, an additional **arkOptions.obfuscation.consumerFiles** field is available in the **build-profile.json5** file. This field specifies obfuscation rules that should be applied when this package is depended upon in other modules. A default **consumer-rules.txt** file is created when a new HAR module is set up. The key difference between **consumer-rules** and **obfuscation-rules** is as follows: **obfuscation-rules** applies to the compilation of the current module, whereas **consumer-rules** applies to the compilation of other modules that depend on the current module.
122    ```
123    "arkOptions": {
124      "obfuscation": {
125        "ruleOptions": {
126          "enable": true,
127          "files": ["./obfuscation-rules.txt"],
128        }
129        "consumerFiles": ["./consumer-rules.txt"]
130      }
131    }
132    ```
133
134* `obfuscation.txt`
135
136   Unlike the above two files, **obfuscation.txt** is automatically generated based on **consumer-rules.txt** and the obfuscation rules of dependent modules during HAR compilation. It exists as a compilation product within the released HAR package and used to apply obfuscation rules when other applications use this package. For details about the generation and logic of **obfuscation.txt**, see [Obfuscation Rule Merging Strategies](#obfuscation-rule-merging-strategies).
137
138  > **NOTE**
139  >
140  > For third-party libraries, the **obfuscation.txt** file only takes effect when the module's **oh-package.json5** file depends on the library. If the dependency is specified in the project's **oh-package.json5** file, the **obfuscation.txt** file in the third-party library will not take effect.
141
142The following table summarizes the differences between these configuration files.
143
144| Configuration File| Configuration Type|  Modifiable |  Affects Obfuscation of This Module |  Affects Obfuscation of Other Modules |
145| --- | --- | --- | --- | --- |
146| obfuscation-rules.txt | Customizable | Yes| Yes| No|
147| consumer-rules.txt    | Customizable | Yes| No| Yes|
148| obfuscation.txt       | Compilation product| Not applicable (automatically generated during HAR compilation)| Not applicable| Yes|
149
150## Obfuscation Rules
151
152There are two types of obfuscation rules: [obfuscation options](#obfuscation-options) and [retention options](#retention-options). The former provides a switch for multiple obfuscation capabilities, such as obfuscation of top-level scope names, property names, and file names. The latter provides the trustlist configuration of various obfuscation capabilities.
153
154**NOTE**
155
156Any modification to the obfuscation configuration file takes effect only after a full build.
157
158### Obfuscation Options
159
160#### -disable-obfuscation
161
162Disables code obfuscation. If this option is used, the built HAP, HSP, or HAR is not obfuscated.
163
164#### -enable-property-obfuscation
165
166Enables property obfuscation. If this option is used, all property names except the following are obfuscated:
167
168* Property names of classes and objects that are directly imported or exported by using **import** or **export**. For example, the property name **data** in the following example is not obfuscated.
169
170    ```
171    export class MyClass {
172       data: string;
173    }
174    ```
175
176* Property names in ArkUI components. For example, **message** and **data** in the following example are not obfuscated.
177
178    ```
179    @Component struct MyExample {
180        @State message: string = "hello";
181        data: number[] = [];
182        // ...
183    }
184    ```
185
186* Property names specified by [retention options](#retention-options).
187* Property names in the SDK API list. The SDK API list is a set of names automatically extracted from the SDK during build. Its cache file is **systemApiCache.json**, which is stored in **build/default/cache/{...}/release/obfuscation** in the project directory.
188* String literal property names. For example, **"name"** and **"age"** in the following example are not obfuscated.
189
190    ```
191    let person = {"name": "abc"};
192    person["age"] = 22;
193    ```
194
195    If you want to obfuscate the string literal property name, use the **-enable-string-property-obfuscation** option in addition to the current option, Example:
196
197    ```
198    -enable-property-obfuscation
199    -enable-string-property-obfuscation
200    ```
201
202    **NOTE**
203
204    **1.** If a string literal property name in the code contains special characters, for example, **let obj = {"\n": 123, "": 4, " ": 5}**, you are advised not to use the **-enable-string-property-obfuscation** option because these names may fail to be kept using [retention options](#retention-options). Special characters refer to characters other than lowercase letters a-z, uppercase letters A-Z, digits 0-9, and underscores (_).
205    **2.** The property trustlist of the SDK API list does not contain the string constants used in the declaration file. For example, the string **'ohos.want.action.home'** in the example is not included in the property trustlist.
206
207    ```
208    // Part of the SDK API file @ohos.app.ability.wantConstant:
209    export enum Params {
210      ACTION_HOME = 'ohos.want.action.home'
211    }
212    // Source code example:
213    let params = obj['ohos.want.action.home'];
214    ```
215
216    When the **-enable-string-property-obfuscation** option is used, use the retention option if you want to retain the property names of the SDK API string constants used in the source code, for example, **obj['ohos.want.action.home']**.
217
218#### -enable-toplevel-obfuscation
219
220Enables top-level scope name obfuscation. If this option is used, all names of all top-level scopes except the following are obfuscated:
221
222* Top-level scope names imported or exported using the **import** or **export** statement.
223* Top-level scope names that are not declared in the current file.
224* Top-level scope names specified by [retention options](#retention-options).
225* Top-level scope names in the SDK API list.
226
227#### -enable-filename-obfuscation
228
229Enables file or folder name obfuscation. If this option is used, all file or folder names are obfuscated. For example:
230
231```
232// Both directory and filename are confused.
233import func from '../directory/filename';
234import { foo } from '../directory/filename';
235const module = import('../directory/filename');
236```
237
238In addition to the following scenarios:
239
240* File or folder names specified by the **main** and **types** fields in the **oh-package.json5** file.
241* File or folder names specified by the **srcEntry** field in the **module.json5** file of the module.
242* File or folder names specified by [-keep-file-name](#retention-options).
243* File or folder names in non-ECMAScript module reference mode (for example, const module = require('./module')).
244* File or folder names in non-path reference mode. For example, **json5** in the example **import module from 'json5'** is not obfuscated.
245
246**NOTE**
247
248For files that the system needs to load files during application running, manually configure them into a trustlist using the [-keep-file-name](#retention-options) option. Otherwise, the application may fail to run.
249
250The names of the compilation entry file, ability component file, and Worker multithreaded file cannot be obfuscated and have been automatically added to the trustlist in DevEco Studio 5.0.3.500. No manual configuration is required. For other files that cannot be obfuscated, you need to manually configure their names in the trustlist.
251
252#### -enable-export-obfuscation
253
254Enables obfuscation for names of classes or objects that are directly imported or exported and their property names. If this option is used, the names directly imported or exported in the module are obfuscated, except the following:
255
256* Names of classes or objects exported from remote HARs (packages whose real paths are in **oh_modules**) and their property names are not obfuscated.
257* Names and property names specified by [retention options](#retention-options) are not obfuscated.
258* Names in the SDK API list are not obfuscated.
259
260**NOTE**
261
2621. To obfuscate property names in imported or exported classes, use both the **-enable-property-obfuscation** and **-enable-export-obfuscation** options.
2632. If the **-enable-export-obfuscation** option is used during HSP build, the externally exposed interfaces must be kept in the **obfuscation-rules.txt** file of the module.
2643. During the build of an HAP, an HSP, and an HSP-dependent HAR, if the **-enable-export-obfuscation** option is used, the interfaces imported from the HSP must be kept in the **obfuscation-rules.txt** file in the module.
265
266    ```
267    // Code example (entry file Index.ets in the HSP):
268    export { add, customApiName } from './src/main/ets/utils/Calc'
269
270    // Example of retaining an interface name:
271    // Configuration of the obfuscation-rules.txt file in the HSP and modules that depend on the HSP:
272    -keep-global-name
273    add
274    customApiName
275    ```
276
277#### -compact
278
279Removes unnecessary spaces and all line feeds. If this option is used, all code is compressed to one line.
280
281**NOTE**
282
283The stack information built in release mode contains the line number of code, but not the column number. Therefore, when the **compact** option is used, the source code cannot be located based on the line number in the stack information.
284
285#### -remove-log
286
287Removes the expressions involving direct calls to the **console.** statement in the following scenarios:
288
2891. Calls at the top layer of a file.
2902. Calls within a code block.
291   Example:
292   ```
293   function foo() {
294    console.log('in block');
295   }
296   ```
2973. Calls with a module or namespace.
298   Example:
299   ```
300   namespace ns {
301    console.log('in ns');
302   }
303   ```
3044. Calls within a **switch** statement.
305
306#### -print-namecache *filepath*
307
308Saves the name cache to the specified file path. The name cache contains mappings before and after name obfuscation.
309
310**NOTE**
311
312A new **namecache.json** file is generated each time the module if fully built. Therefore, save a copy of the file each time you publish a new version.
313
314#### -apply-namecache *filepath*
315
316Reuses the specified name cache file. The names will be obfuscated according to the cache mappings. If there is no corresponding name, a new random segment name is used.
317This option should be used in incremental build scenarios.
318
319By default, DevEco Studio saves cache files in a temporary cache directory and automatically applies the cache files during incremental build.
320Default cache directory: **build/default/cache/{...}/release/obfuscation**
321
322#### -remove-comments
323
324Removes JsDoc comments from the declaration file generated after compilation.
325
326**NOTE**
327
328By default, all comments in the source code file generated after the compilation are removed and cannot be retained.
329You can configure **keep-comments** to retain the JsDoc comments in the declaration file.
330
331### Retention Options
332
333#### -keep-property-name *[,identifiers,...]*
334
335Retains the specified property names. Name wildcards are supported. An example is as follows.
336
337```
338-keep-property-name
339age
340firstName
341lastName
342```
343
344> **NOTE**
345>
346> - This option takes effect when **-enable-property-obfuscation** is used.
347>
348> - The property trustlist applies globally. That is, if multiple properties with the same name exist in the code, they will not be confused as long as they match the names in the trustlist configured in **-keep-property-name**.
349
350**Which property names should be retained?**
351
3521. To ensure correct obfuscation, you are advised to retain all properties that are not accessed using dot notation. For example, object properties accessed via strings:
353
354```
355var obj = {x0: 0, x1: 0, x2: 0};
356for (var i = 0; i <= 2; i++) {
357    console.info(obj['x' + i]);  // x0, x1, and x2 should be retained.
358}
359
360Object.defineProperty(obj, 'y', {});  // y should be retained.
361Object.getOwnPropertyDescriptor(obj, 'y');  // y should be retained.
362console.info(obj.y);
363
364obj.s = 0;
365let key = 's';
366console.info(obj[key]);        // The variable value s corresponding to key should be retained.
367
368obj.t1 = 0;
369console.info(obj['t' + '1']);        // t1 should be retained.
370```
371
372For the following string literal property calls, you can choose to retain them.
373
374```
375// Obfuscation configuration:
376// -enable-property-obfuscation
377// -enable-string-property-obfuscation
378
379obj.t = 0;
380console.info(obj['t']); // 't' will be correctly confused, and t can be retained.
381
382obj.['v'] = 0;
383console.info(obj['v']); // 'v' will be correctly confused, and v can be retained.
384```
385
3862. In the case of indirect exports, for example, **export MyClass** and **let a = MyClass; export {a}**, if you do not want to obfuscate property names, use [retention options](#retention-options) to retain them. For property names of directly exported classes or objects, such as **name** and **age** in the following example, if you do not want to obfuscate them, use [retention options](#retention-options) to retain them.
387
388   ```
389   export class MyClass {
390       person = {name: "123", age: 100};
391   }
392   ```
393
3943. If an API (for example, **foo** in the example) of the .so library needs to be used in the ArkTS/TS/JS file, manually retain the API name.
395
396   ```
397   import testNapi from 'library.so'
398   testNapi.foo() // foo should be retained Example: -keep-property-name foo
399   ```
400
4014. Fields used in JSON parsing and object serialization should be retained.
402
403   ```
404   // Example JSON file structure (test.json):
405   /*
406   {
407     "jsonProperty": "value",
408     "otherProperty": "value2"
409   }
410   */
411
412   const jsonData = fs.readFileSync('./test.json', 'utf8');
413   let jsonObj = JSON.parse(jsonData);
414   let jsonProp = jsonObj.jsonProperty; // jsonProperty should be retained.
415
416   class jsonTest {
417     prop1: string = '';
418     prop2: number = 0
419   }
420
421   let obj = new jsonTest();
422   const jsonStr = JSON.stringify(obj); // prop1 and prop2 will be obfuscated and should be retained.
423   ```
424
4255. Database-related fields should be manually retained. For example, properties in the database key-value pair type (ValuesBucket):
426
427   ```
428   const valueBucket: ValuesBucket = {
429     'ID1': ID1, // ID1 should be retained.
430     'NAME1': name, // NAME1 should be retained.
431     'AGE1': age, // AGE1 should be retained.
432     'SALARY1': salary // SALARY1 should be retained.
433   }
434   ```
435
4366. When custom decorators are used on member variables, member methods, or parameters in the source code, and the intermediate product of source code compilation is a JS file (for example, compiling release-mode source code HAR or source code containing @ts-ignore or @ts-nocheck), the names of these member variables or member methods should be retained. This is because the names of these member variables/methods are hardcoded as string literals during conversion from TS syntax to standard JS syntax.
437
438   Example:
439
440   ```
441   class A {
442     // 1. Member variable decorator
443     @CustomDecoarter
444     propertyName: string = ""   // propertyName should be retained.
445     // 2. Member method decorator
446     @MethodDecoarter
447     methodName1(){} // methodName1 should be retained.
448     // 3. Method parameter decorator
449     methodName2(@ParamDecorator param: string): void { // methodName2 should be retained.
450     }
451   }
452   ```
453
454#### -keep-global-name *[,identifiers,...]*
455
456Retains the specified top-level scope names or imported/exported element names. Name wildcards are supported. Example:
457
458```
459-keep-global-name
460Person
461printPersonName
462```
463
464Names exported from the namespace can also be retained using the **-keep-global-name** option. The following is an example:
465
466```
467export namespace Ns {
468  export const age = 18; // -keep-global-name age: retains variable age.
469  export function myFunc () {}; // -keep-global-name myFunc: retains function myFunc.
470}
471```
472
473> **NOTE**
474>
475> The trustlist specified by `-keep-global-name` applies globally. That is, if multiple top-level scope names or exported names exist in the code, they will not be confused as long as they match the names in the trustlist configured in **-keep-global-name**.
476
477**Which top-level scope names should be retained?**
478
479In JavaScript, variables in the top-level scope are properties of **globalThis**. If **globalThis** is used to access a global variable in the code, the variable name should be retained.
480
481Example:
482
483```
484var a = 0;
485console.info(globalThis.a);  // a should be retained.
486
487function foo(){}
488globalThis.foo();           // foo should be retained.
489
490var c = 0;
491console.info(c);             // c can be correctly obfuscated.
492
493function bar(){}
494bar();                      // bar can be correctly obfuscated.
495
496class MyClass {}
497let d = new MyClass();      // MyClass can be correctly obfuscated.
498```
499
500When importing API names from .so libraries using named imports, if both **-enable-toplevel-obfuscation** and **-enable-export-obfuscation** are configured, the API names should be manually retained.
501
502```
503import { testNapi, testNapi1 as myNapi } from 'library.so' // testNapi and testNapi1 should be retained.
504```
505
506#### -keep-file-name *[,identifiers,...]*
507
508Retains the file or folder names. You do not need to specify the file name extension. Name wildcards are supported. Example:
509
510```
511-keep-file-name
512index
513entry
514```
515
516**Which file names should be retained?**
517
5181. When **require** is used to import file paths, the path should be retained. This is because ArkTS does not support [CommonJS](../arkts-utils/module-principle.md#commonjs module) syntax.
519
520   ```
521   const module1 = require('./file1')   // file1 should be retained.
522   ```
523
5242. For dynamically imported paths, since it is impossible to determine whether the parameter in the **import** function is a path, the path should be retained.
525
526   ```
527   const moduleName = './file2'         // The path name file2 corresponding to moduleName should be retained.
528   const module2 = import(moduleName)
529   ```
530
5313. When [dynamic routing](../ui/arkts-navigation-navigation.md#cross-package-dynamic-routing) is used for navigation, the path passed to the dynamic routing should be retained. Dynamic routing provides two modes: system routing table and custom routing table. If a custom routing table is used for redirection, the way to configure a trustlist is consistent with the second dynamic reference scenario. However, if the system routing table is used for redirection, the path corresponding to the **pageSourceFile** field in the **resources/base/profile/route_map.json** file of the module should be added to the trustlist.
532
533   ```
534     {
535       "routerMap": [
536         {
537           "name": "PageOne",
538           "pageSourceFile": "src/main/ets/pages/directory/PageOne.ets",  // The path should be retained.
539           "buildFunction": "PageOneBuilder",
540           "data": {
541             "description" : "this is PageOne"
542           }
543         }
544       ]
545     }
546   ```
547
548#### -keep-comments *[,identifiers,...]*
549
550Retains the classes, functions, namespaces, enums, structs, interfaces, modules, types, and JsDoc comments above properties in the declaration file generated after compilation. Name wildcards are supported. For example, to retain the JSDoc comments above the **Human** class in the declaration file, use the following configuration:
551
552```
553-keep-comments
554Human
555```
556
557**NOTE**
558
5591. This option takes effect when **-remove-comments** is used.
5602. If the classes, functions, namespaces, enums, structs, interfaces, modules, types, and property names in the declaration file generated after compilation are confused, the JsDoc comments above the element cannot be retained using **-keep-comments**. For example, when **exportClass** is configured in **-keep-comments**, if the class name is **exportClass** obfuscated, its JSDoc comments cannot be retained:
561
562```
563/*
564 * @class exportClass
565 */
566export class exportClass {}
567```
568
569#### -keep-dts *filepath*
570
571Adds names (such as variable names, class names, and property names) in the .d.ts file of the specified file path into the trustlist of **-keep-global-name** and **-keep-property-name**. Note that **filepath** supports only absolute paths and can be specified as a directory. In this case, the names in all .d.ts files in the directory are retained.
572
573#### -keep *filepath*
574
575Retains all names (such as variable names, class names, and property names) in the specified relative path. The path can be a file or directory. If the path is a directory, the files in the directory and subdirectories are not obfuscated.
576
577The path must be a relative path. **./** and **../** are relative to the directory where the obfuscation configuration file is located. Path wildcards are supported.
578
579```
580-keep
581./src/main/ets/fileName.ts   // Names in the fileName.ts file are not obfuscated.
582../folder                    // Names in all the files under the folder directory and its subdirectories are not obfuscated.
583../oh_modules/json5          // Names in all the files in the imported third-party library json5 are not obfuscated.
584```
585
586**How to retain remote HAR packages in modules?**
587
588Method 1: Specify the exact path of the remote HAR package in the module-level oh_modules. This path is a symbolic link to the real path in the project-level oh_modules. When configuring the path in the module-level oh_modules as a trustlist, you should specify the bundle name or a directory following the bundle name to correctly link to the real directory path. Therefore, configuring only the parent directory name of the HAR package is not supported.
589
590```
591// Positive example:
592-keep
593./oh_modules/harName1         // Names in all the files under the harName1 directory and its subdirectories are not confused.
594./oh_modules/harName1/src     // Names in all the files under the src directory and its subdirectories are not confused.
595./oh_modules/folder/harName2  // Names in all the files under the harName2 directory and its subdirectories are not confused.
596
597// Negative example:
598-keep
599./oh_modules                  // To retain the HAR package in the module-level oh_modules, configuring the parent directory name of the HAR package is not supported.
600```
601
602Method 2: Specify the exact path of the remote HAR package in the project-level oh_modules. Since the file paths in the project-level oh_modules are all real paths, any path can be configured.
603
604```
605-keep
606../oh_modules                  // Names in all the files under the project-level oh_modules and its subdirectories are not confused.
607../oh_modules/harName3          // Names in all the files under the harName3 directory and its subdirectories are not confused.
608```
609
610The following figure shows the directory structure of module-level oh_moudles and project-level oh_modules in DevEco Studio.
611
612![oh_modules](./figures/oh_modules.png)
613
614**NOTE**
615
6161. For files retained by **-keep filepath**, all exported names and their properties in the dependency chain of these files are also retained.
6172. This option does not affect the capability provided by the **-enable-filename-obfuscation** option.
618
619#### Wildcards Supported by Retention Options
620
621##### Name Wildcards
622
623The table below lists the name wildcards supported.
624
625| Wildcard| Description                  | Example                                      |
626| ------ | ---------------------- | ------------------------------------------ |
627| ?      | Matches any single character.      | "AB?" matches "ABC", but not "AB".        |
628| \*     | Matches any number of characters.| "\*AB\*" matches "AB", "aABb", "cAB", and "ABc".|
629
630**Use Example**
631
632Retain all property names that start with **a**.
633
634```
635-keep-property-name
636a*
637```
638
639Retain all single-character property names.
640
641```
642-keep-property-name
643?
644```
645
646Retain all property names.
647
648```
649-keep-property-name
650*
651```
652
653##### Path Wildcards
654
655The table below lists the path wildcards supported.
656
657| Wildcard| Description                                                                    | Example                                             |
658| ------ | ------------------------------------------------------------------------ | ------------------------------------------------- |
659| ?     | Matches any single character except the path separator (/).                                     | "../a?" matches "../ab", but not "../a/".        |
660| \*      | Matches any number of characters except the path separator (/).                               | "../a*/c" matches "../ab/c", but not "../ab/d/s/c".|
661| \*\*   | Matches any number of characters.                                                  | "../a**/c" matches "../ab/c" and "../ab/d/s/c". |
662| !      | Negation. It can only be placed at the beginning of a path to exclude a certain case configured in the trustlist.| "!../a/b/c.ets" indicates all paths other than "../a/b/c.ets".          |
663
664**Use Example**
665
666Retain the **c.ets** file in the **../a/b/** directory (excluding subdirectories).
667
668```
669-keep
670../a/b/*/c.ets
671```
672
673Retain the **c.ets** file in the **../a/b/** directory and its subdirectories.
674
675```
676-keep
677../a/b/**/c.ets
678```
679
680Retain all files except the **c.ets** file in the **../a/b/** directory. The exclamation mark (!) cannot be used alone. It can only be used to exclude existing cases in the trustlist.
681
682```
683-keep
684../a/b/
685!../a/b/c.ets
686```
687
688Retain all the files in the **../a/** directory (excluding subdirectories).
689
690```
691-keep
692../a/*
693```
694
695Retain all the files in the **../a/** directory and its subdirectories.
696
697```
698-keep
699../a/**
700```
701
702Retain all the files in the module.
703
704```
705-keep
706./**
707```
708
709**NOTE**
710
711(1) In these options, the wildcards *, ?, and ! cannot be used for other meanings.
712Example:
713
714```
715class A {
716  '*'= 1
717}
718
719-keep-property-name
720*
721```
722
723In this example, * indicates any number of characters, and all property names are retained (not obfuscated). It does not mean that only the * property is retained.
724
725(2) In the **-keep** option, only the path format / is allowed. The path format \ or \\ is not.
726
727### Comments
728
729You can use **#** to comment out an obfuscation rule file. The line that starts with **#** is treated as a comment. Example:
730
731```
732# white list for MainAbility.ets
733-keep-global-name
734MyComponent
735GlobalFunction
736
737-keep-property-name # white list for dynamic property names
738firstName
739lastName
740age
741```
742
743During HAR build, comments are not merged into the final **obfuscation.txt** file.
744
745### Obfuscation Rule Merging Strategies
746
747When a module in a project is built, the obfuscation rules used are a combination of the obfuscation rules in the following files:
748
749* File specified by the **ruleOptions.files** field in the **build-profile.json5** file of the module
750* File specified by the **consumerFiles** field in the local dependent libraries
751* **obfuscation.txt** file in remote dependent HARs
752
753The priorities of obfuscation rules in the preceding files are the same. When building a module, these files are merged according to the following merging strategies (pseudo code).
754
755```
756let `listRules` indicates the list of all obfuscation rule files mentioned above.
757let finalRule = {
758    disableObfuscation: false,
759    enablePropertyObfuscation: false,
760    enableToplevelObfuscation: false,
761    compact: false,
762    removeLog: false,
763    keepPropertyName: [],
764    keepGlobalName: [],
765    keepDts: [],
766    printNamecache: string,
767    applyNamecache: string
768}
769for each file in `listRules`:
770    for each option in file:
771        switch(option) {
772            case -disable-obfuscation:
773                finalRule.disableObfuscation = true;
774                continue;
775            case -enable-property-obfuscation:
776                finalRule.enablePropertyObfuscation = true;
777                continue;
778            case -enable-toplevel-obfuscation:
779                finalRule.enableToplevelObfuscation = true;
780                continue;
781            case -compact:
782                finalRule.compact = true;
783                continue;
784            case -remove-log:
785                finalRule.removeLog = true;
786                continue;
787            case -print-namecache:
788                finalRule.printNamecache = #{specifiedPathName};
789                continue;
790            case -apply-namecache:
791                finalRule.applyNamecache = #{specifiedPathName};
792                continue;
793            case -keep-property-name:
794                finalRule.keepPropertyName.push(#{specifiedName});
795                continue;
796            case -keep-global-name:
797                finalRule.keepGlobalName.push(#{specifiedName});
798                continue;
799            case -keep-dts:
800                finalRule.keepDts.push(#{specifiedPath});
801                continue;
802        }
803    end-for
804end-for
805```
806
807The final obfuscation rule comes from the object **finalRule**.
808
809During HAR build, the final **obfuscation.txt **file comes from the combination of the **consumerFiles** field of the HDR and the local dependent libraries, and the **obfuscation.txt** file of the dependent HARs.
810
811When the obfuscation configuration file specified by **consumerFiles** contains the following obfuscation rules, these rules will be merged into the **obfuscation.txt** file of a HAR, whereas other obfuscation rules will not.
812
813```
814// Obfuscation options
815-enable-property-obfuscation
816-enable-string-property-obfuscation
817-enable-toplevel-obfuscation
818-compact
819-remove-log
820
821// Retention options
822-keep-property-name
823-keep-global-name
824```
825
826**Precautions for Obfuscation in the Library**
827
8281. If the obfuscation configuration file specified by **consumerFiles** contains the above obfuscation options, when other modules depend on this HAR, these obfuscation options will be merged with the main module's obfuscation rules, thereby affecting the main module. Therefore, you are not advised to configure obfuscation options in the **consumer-rules.txt** file. Instead, configure only retention options in the file.
829
8302. If the **-keep-dts** option is added to the obfuscation configuration file specified by **consumerFiles**, it will be converted into **-keep-global-name** and **-keep-property-name**.
831
832## Deobfuscating Error Stacks
833
834In applications that have undergone obfuscation, code names are changed, making the error stacks printed during crashes harder to understand because they do not match the source code exactly. You can use the hstack plugin in DevEco Studio Command Line Tools to restore the source stack trace and analyze problems. The deobfuscation tool requires the **sourceMaps.map** file and the obfuscation name mapping file **nameCache.json** generated during compilation. Be sure to back them up locally.
835
836![obfuscation-product](figures/obfuscation-product.png)
837
838## Enabling Code Obfuscation
839
8401. Prerequisites for using obfuscation:
841    1. Check whether obfuscation is enabled for the current module and whether the release build mode is selected.
842    2. Before using obfuscation, you are advised to learn about the capabilities of [obfuscation options](obfuscation-options) and [retention options](retention-options).
8433. Enable the obfuscation options in sequence to adapt and verify application functionalities one by one.
844    1. When **-enable-toplevel-obfuscation** is configured, access to global variables using **globalThis** fails. To rectify the fault, use **-keep-global-name** to retain the global variable name.
845    2. After the preceding adaptation is successful, configure **-enable-property-obfuscation**, and perform adaptation in the following scenarios:
846        1. If the code statically defines properties but dynamically accesses them (or vice versa), use **-keep-property-name** to retain the property names. Example:
847            ```
848            // Static definition, dynamic access: The property name is static during object definition, but is accessed by dynamically constructing the property name (usually using string concatenation).
849            const obj = {
850              staticName: value  // Static definition
851            };
852            const fieldName = 'static' + 'Name';  // Dynamic construction of the property name
853            console.log(obj[fieldName]);  // Use square bracket notation to dynamically access the property.
854            ```
855            ```
856            // Dynamic definition, static access: The property name is determined during object definition through a dynamic expression, but is statically accessed using dot notation (assuming that you know the result of the property name).
857            const obj = {
858              [dynamicExpression]: value  // Dynamic definition
859            };
860            console.log(obj.dynamicPropertyName);  // Use dot notation to statically access the property.
861            ```
862        2. If the code uses dot notation to access fields not defined in ArkTS/TS/JS code (for example, native so libraries, fixed JSON files, or database fields):
863            1. For API calls to so libraries (for example, **import testNapi from 'library.so'; testNapi.foo();**), use **-keep-property-name** to retain the property name **foo**.
864            2. For fields in JSON files, use **-keep-property-name** to retain the JSON field names.
865            3. For database-related fields, use **-keep-property-name** to retain the database field names.
866        3. When building a HAR module for use by other modules, use **-keep-property-name** in the **consumer-rules.txt** file of the HAR module to retain properties that should not be re-obfuscated. The **consumer-rules.txt** file generates the **obfuscation.txt** file during HAR compilation. When the HAR module is depended upon by other modules, DevEco Studio parses the **obfuscation.txt** file to read the trustlist.
867        4. Verify application functionality and identify any missed scenarios. If the application functionality is abnormal, find the code of the error line in the corresponding [intermediate products](#viewing-obfuscation-effects) based on the obfuscated error stack, identify the necessary trustlist configurations, and use **-keep-property-name** to retain them.
868    3. After the preceding adaptations are successful, configure **-enable-export-obfuscation**, and perform adaptation in the following scenarios:
869        1. For HSP modules that provide interfaces and properties to other modules, use **-keep-global-name** to retain the interface names and **-keep-property-name** to retain the property names in exposed classes/interfaces.
870        2. When building HAR modules for use by other modules, use **-keep-global-name** to retain interface names and **-keep-property-name** to retain the property names in exposed classes/interfaces in the **obfuscation-rules.txt** file.
871        3. For API calls to so libraries (for example, **import { napiA } from 'library.so'**), use **-keep-global-name** to retain the so interface name **napiA**.
872        4. Verify application functionality and interface call functionality when the module is depended upon, and identify any missed scenarios. If the application functionality is abnormal, find the code of the error line in the corresponding [intermediate products](#viewing-obfuscation-effects) based on the obfuscated error stack, identify the necessary trustlist configurations, and retain them.
873    4. After the preceding adaptations are successful, configure **-enable-filename-obfuscation**, and perform adaptation in the following scenarios:
874        1. If the code contains dynamic import statements (for example, **const path = './filePath'; import(path)**), use **-keep-file-name filePath** to retain the file path.
875        2. If the application has a [routerMap configuration](https://developer.huawei.com/consumer/en/doc/harmonyos-guides-V5/module-configuration-file-V5#routermap) that describes routing information, use **-keep-file-name** to retain the page source file path, which is specified by **pageSourceFile** field in the routing information.
876        3. If the code uses **ohmUrl** for page navigation (for example, **router.pushUrl({url: '@bundle:com.example.routerPage/Library/Index'})**), use **-keep-file-name** to retain the path.
877        4. Verify application functionality and identify any missed scenarios. If the application function is abnormal and the error stack contains obfuscated paths, you can query the original path in the **build/default/[...]/release/obfuscation/nameCache.json** file within the module and then locate the source code file. You can also use the [hstack plugin](https://developer.huawei.com/consumer/en/doc/harmonyos-guides-V5/ide-command-line-hstack-V5) to trigger automatic deobfuscation of error stacks. After locating the paths to retain, use **-keep-file-name** to retain them.
878
879## Remarks
880
881* Currently, custom obfuscation plugins are not supported in the hvigor build process.
882* If a module that depends on an obfuscated HAR enables obfuscation, the HAR will be obfuscated again.
883* To enable the release build mode, select **Product** in the upper right corner of DevEco Studio and set **Build Mode** to **release**.
884![product-release](figures/product-release.png)
885
886## FAQs
887
888### Mappings Between Obfuscation Options and Minimum SDK Versions
889
890| Obfuscation Option| Description | Minimum SDK Version|
891| ------- | --------- | ------ |
892| -disable-obfuscation         | Disables obfuscation.| 4.0.9.2 |
893| -enable-property-obfuscation | Enables property name obfuscation.| 4.0.9.2 |
894| -enable-string-property-obfuscation | Enables obfuscation for string literal property names.| 4.0.9.2 |
895| -enable-toplevel-obfuscation | Enables top-level scope name obfuscation.| 4.0.9.2 |
896| -enable-filename-obfuscation | Enables file or folder name obfuscation for the HAR.<br> Enables file or folder name obfuscation for the HAP/HSP.| 4.1.5.3 <br> 5.0.0.19 |
897| -enable-export-obfuscation   | Enables obfuscation for imported/exported names.| 4.1.5.3 |
898| -compact                     | Removes unnecessary spaces and all line feeds.| 4.0.9.2 |
899| -remove-log                  | Removes the expressions involving direct calls to the console. statement in specific scenarios.| 4.0.9.2 |
900| -print-namecache             | Saves the name cache to the specified file path.| 4.0.9.2 |
901| -apply-namecache             | Reuses the specified name cache file.| 4.0.9.2 |
902| -remove-comments             | Removes all comments in the file.| 4.1.5.3 |
903| -keep-property-name          | Retains property names.| 4.0.9.2 |
904| -keep-global-name            | Retains top-level scope names.| 4.0.9.2 |
905| -keep-file-name              | Retains file or folder names in the HAR.<br> Retains file or folder names in the HAP/HSP.| 4.1.5.3 <br> 5.0.0.19 |
906| -keep-dts                    | Retains the names in the .d.ts file in the specified path.| 4.0.9.2 |
907| -keep-comments               | Retains the classes, functions, namespaces, enums, structs, interfaces, modules, types, and JsDoc comments above properties in the declaration file generated after compilation.| 4.1.5.3 |
908| -keep                        | Retains all names in the specified path.| 5.0.0.18 |
909| Wildcard                      | The retention options of the name classes and path classes support wildcards.| 5.0.0.24 |
910
911### Viewing Obfuscation Effects
912The following figure shows a simplified compilation process.
913
914![compilation-process](figures/compilation-process.png)
915
916After obfuscation is complete, intermediate products are generated. You can find the obfuscated intermediate products in the **build** directory of the compilation output, as well as the name mapping file and system API trustlist files.
917
918* Obfuscated file directory: build/default/[...]/release/moduleName
919* Directory of the name mapping file and system API trustlist file: build/default/[...]/release/obfuscation
920  * The name mapping file, named **nameCache.json**, records the mappings between source code names and names after obfuscation.
921  * The system API trustlist file, named **systemApiCache.json**, records the APIs and property names that will be kept.
922
923  ![build-product](figures/build-product.png)
924
925### Troubleshooting Functional Issues
926#### Procedure
9271. Configure the **-disable-obfuscation** option in the **obfuscation-rules.txt** file to disable obfuscation, and check whether the issue is caused by obfuscation.
9282. If the function is abnormal after obfuscation is enabled, read the document to understand the capabilities of obfuscation rules, such as [-enable-property-obfuscation](#retention-options), [-enable-toplevel-obfuscation](#retention-options), [-enable-filename-obfuscation](#retention-options), and [-enable-export-obfuscation](#retention-options), and the syntax scenarios that require the configuration of a trustlist to ensure that the application functions properly. The following briefly describes the four retention options that are enabled by default. For details, see the complete description of the corresponding options.
929    1. [-enable-toplevel-obfuscation](#retention-options): retains top-level scope name.
930    2. [-enable-property-obfuscation](#retention-options): retains properties. You need to use [-keep-property-name](#retention-options) to configure a trustlist for specified property names in scenarios where obfuscation is not allowed, such as network data access, JSON field access, dynamic property access, and .so library API calls.
931    3. [-enable-export-obfuscation](#retention-options): retains exported names. Generally, this option is used together with **-enable-toplevel-obfuscation** and **-enable-property-obfuscation**. You need to use [-keep-global-name](#retention-options) to configure a trustlist for exported or imported names in scenarios where external APIs of the module cannot be obfuscated.
932    4. [-enable-filename-obfuscation]: retains file names. You need to use [-keep-file-name](#retention-options) to configure a trustlist for file paths and names in scenarios where file paths are dynamically imported or directly loaded at runtime.
9333. If your problem matches any troubleshooting cases listed in [Common Issues](common-issues), apply the suggested solutions.
9344. If the issue is not covered, use a positive approach to identify the problem (remove specific configuration items if the corresponding functionality is not needed).
9355. Analyze runtime crashes as follows:
936    1. Open the application runtime logs or the **Crash** dialog box in DevEco Studio to find the crash stack.
937    2. The line number in the crash stack is the line number of the [build product](#viewing-obfuscation-effects), and the method name may also be the obfuscated name. Therefore, you are advised to check the build product based on the crash stack, analyze the names that cannot be obfuscated, and add them to the trustlist.
9386. Analyze functional exceptions (for example, white screens) as follows:
939    1. Opening the application runtime logs: Select HiLog and search for logs directly related to the exceptions.
940    2. Locating the problematic code segment: Identify the specific code block causing the exceptions through log analysis.
941    3. Enhancing log output: Add log records for data fields in the suspected code segment.
942    4. Analyzing and identifying critical fields: Determine if the data exception is caused by obfuscation through the enhanced log output.
943    5. Configuring a trustlist for critical fields: Add fields that directly affect application functionality after obfuscation to the trustlist.
944
945#### Troubleshooting Unexpected Obfuscation Behavior
946If unexpected obfuscation behavior occurs, check whether certain obfuscation options are configured for the dependent local modules or third-party libraries.
947
948Example:
949If **-compact** is not configured for the current module, but the code in the obfuscated intermediate product is compressed into a single line, perform the following steps:
950
9511. Check the **dependencies** field in the **oh-package.json5** file of the current module to identify dependencies.
9522. Search for **-compact** in the obfuscation configuration file of the dependent modules or third-party libraries.
953    * Search for **-compact** in the **consumer-rules.txt** file in the local libraries.
954    * Search for **-compact** in all **obfuscation.txt** files in the project-level **oh_modules** directory.
955
956**NOTE**
957
958You are not advised to configure the following options in the **obfuscation.txt** file of third-party libraries, as they can cause unexpected behavior or crashes when the main module is obfuscated. Contact the library providers to remove these options and repackage the libraries.
959
960```
961-enable-property-obfuscation
962-enable-string-property-obfuscation
963-enable-toplevel-obfuscation
964-remove-log
965-compact
966```
967
968### Common Issues
969
970#### Errors That May Occur When -enable-property-obfuscation Is Configured
971
972Case 1: The error message "Cannot read property 'xxx' of undefined" is reported.
973
974```
975// Before obfuscation:
976const jsonData = ('./1.json')
977let jsonStr = JSON.parse(jsonData)
978let jsonObj = jsonStr.jsonProperty
979
980// After obfuscation:
981const jsonData = ('./1.json')
982let jsonStr = JSON.parse(jsonData)
983let jsonObj = jsonStr.i
984```
985
986After property name obfuscation is enabled, **jsonProperty** is obfuscated as a random character **i**. However, the original name is used in the JSON file, causing the error.
987
988**Solution**: Use the **-keep-property-name** option to add the fields used in JSON files to the trustlist.
989
990Case 2: An error message is reported when database-related fields are used and property obfuscation is enabled.
991
992The error message is "table Account has no column named a23 in 'INSET INTO Account(a23)'."
993
994The SQL statement uses database field names that are obfuscated, whereas the database expects the original names.
995
996**Solution**: Use the **-keep-property-name** option to add the database fields to the trustlist.
997
998**Case 3: Properties Obfuscated When Record<string, Object> Is Used as an Object Type**
999
1000**Symptom**
1001
1002When **Record<string, Object>** is used as an object type, properties like **linkSource** are obfuscated, causing the error. Example:
1003
1004```
1005// Before obfuscation:
1006import { Want } from '@kit.AbilityKit';
1007let petalMapWant: Want = {
1008  bundleName: 'com.example.myapplication',
1009  uri: 'maps://',
1010  parameters: {
1011    linkSource: 'com.other.app'
1012  }
1013}
1014
1015// After obfuscation:
1016import type Want from "@ohos:app.ability.Want";
1017let petalMapWant: Want = {
1018    bundleName: 'com.example.myapplication',
1019    uri: 'maps://',
1020    parameters: {
1021        i: 'com.other.app'
1022    }
1023};
1024```
1025
1026**Possible Causes**
1027
1028In this example, the object's properties need to be passed to the system to load a specific page, so the property names should not be obfuscated. The type **Record<string, Object>** is a generic definition for an object with string keys and does not describe the internal structure or property types in detail. Therefore, the obfuscation tool cannot identify which properties should not be obfuscated, leading to the obfuscation of internal property names like **linkSource**.
1029
1030**Solution**
1031
1032Add the problematic property names to the property trustlist. The following is an example:
1033
1034```
1035-keep-property-name
1036linkSource
1037```
1038
1039#### Errors That May Occur When -enable-export-obfuscation and -enable-toplevel-obfuscation Are Configured
1040
1041When the two options are configured, method name confusion in the following scenarios is involved when the main module calls the methods of other modules:
1042
1043| Main Module| Dependent Module| Imported/Exported Name Obfuscation|
1044| ------- | ------- | ----------------------------|
1045| HAP/HSP | HSP     | The HSP and main module are independently compiled, resulting in inconsistent obfuscated names. Both need trustlist configurations.|
1046| HAP/HSP | Local HAR| The local HAR is compiled together with the main module, resulting in consistent obfuscated names.|
1047| HAP/HSP | Third-party library | Exported names and their properties in third-party libraries are collected into the trustlist, so they are not obfuscated during import/export.|
1048
1049For the HSP, you must add the methods used by other modules to the trustlist. You must add the same trustlist for the main module. Therefore, you are advised to add the obfuscation file configured with the trustlist (for example, **hsp-white-list.txt**) to the obfuscation configuration item of the module that depends on the obfuscation file, that is, the **files** field shown in the following figure.
1050
1051![obfuscation-config](figures/obfuscation-config.png)
1052
1053Case 1: When a class is dynamically imported, the class definition is confused, but the class name is not, causing an error.
1054
1055```
1056// Before obfuscation:
1057export class Test1 {}
1058
1059let mytest = (await import('./file')).Test1
1060
1061// After obfuscation:
1062export class w1 {}
1063
1064let mytest = (await import('./file')).Test1
1065```
1066
1067The exported class **Test1** is a top-level domain name. When being dynamically used, it is a property. Because the **-enable-property-obfuscation** option is not configured, the class name is confused, but the property name is not.
1068
1069**Solution**: Use the **-keep-global-name** option to add **Test1** to the trustlist.
1070
1071Case 2: For a method in a namespace, the method definition is confused, but the statement that uses the method is not, causing an error.
1072
1073```
1074// Before obfuscation:
1075export namespace ns1 {
1076  export class person1 {}
1077}
1078
1079import {ns1} from './file1'
1080let person1 = new ns1.person1()
1081
1082// After obfuscation:
1083export namespace a3 {
1084  export class b2 {}
1085}
1086
1087import {a3} from './file1'
1088let person1 = new a3.person1()
1089```
1090
1091**person1** in the namespace is an exported element. When being called through **ns1.person1**, it is a property. Because the **-enable-property-obfuscation** option is not configured, the property name is not obfuscated during the call.
1092
1093**Solution**
1094
10951. Configure the **-enable-property-obfuscation** option.
10962. Use the **-keep-global-name** option to add the methods exported from the namespace to the trustlist.
1097
1098Case 3: When declare global is used, a syntax error is reported after obfuscation.
1099
1100```
1101// Before obfuscation:
1102declare global {
1103  var age : string
1104}
1105
1106// After obfuscation:
1107declare a2 {
1108  var b2 : string
1109}
1110```
1111
1112The error message "SyntaxError: Unexpected token" is reported.
1113
1114**Solution**: Use **-keep-global-name** to **add __global** to the trustlist.
1115
1116#### The **-enable-string-property-obfuscation** option is not configured, but the string literal property name is obfuscated. As a result, the value of the string literal property name is undefined.
1117
1118```
1119person["age"] = 22; // Before obfuscation
1120
1121person["b"] = 22; // After obfuscation
1122```
1123
1124**Solution**
1125
11261. Check whether **-enable-string-property-obfuscation** is configured for the dependent HAR. If it is configured, the main project will be affected, and you should disable it.
11272. If it must be configured, add the property name to the trustlist.
11283. If it is not configured and the SDK version is earlier than 4.1.5.3, update the SDK.
1129
1130#### Errors That May Occur When -enable-filename-obfuscation Is Configured
1131
1132Case 1: The error message "Error Failed to get a resolved OhmUrl for 'D:code/MyApplication/f12/library1/pages/d.ets' imported by 'undefined'" is reported.
1133
1134As shown below, the outer layer of the **library1** module contains a directory named **directory**. When file name obfuscation is enabled, **directory** is obfuscated as **f12**, causing the error indicating that the path is not found.
1135
1136![directory-offuscation](figures/directory-obfuscation.png)
1137
1138**Solution**
1139
11401. If the project directory structure and error message are similar, update the SDK to 5.0.0.26 or later.
11412. Use the **-keep-file-name** option to add the directory name **directory** of the module to the trustlist.
1142
1143Case 2: The error message "Cannot find module 'ets/appability/AppAbility' which is application Entry Point" is reported.
1144
1145The system loads the ability file when the application is running. Therefore, you must manually configure the trustlist to prevent the specified file from being obfuscated.
1146
1147**Solution**: Use the **-keep-file-name** option to add the path corresponding to the **srcEntry** field in the **src/main/module.json5** file to the trustlist.
1148
1149```
1150-keep-file-name
1151appability
1152AppAbility
1153```
1154
1155#### Errors That May Occur When -keep-global-name and a Trustlist Are Configured
1156
1157The error message "Cannot read properties of undefined (reading 'has')" is reported.
1158
1159**Solution**: Upgrade the SDK to 4.1.6.3 or later.
1160
1161#### The HAP and HSP depend on the same local source code HAR module.
1162
1163* If file name obfuscation is enabled, the following issue may occur:
1164  * Singleton function exceptions: The reason is that the HAP and HSP modules execute independent build and obfuscation processes. The same file names in the shared local source code HAR may be obfuscated differently in the HAP and HSP packages.
1165  * Interface call failures: The reason is that the HAP and HSP modules execute independent build and obfuscation processes. Different file names in the shared local source code HAR may be obfuscated to the same name in the HAP and HSP packages.
1166* If **-enable-export-obfuscation** and **-enable-toplevel-obfuscation** are configured, the interface loading failures may occur at runtime.
1167The HAP and HSP modules execute independent build and obfuscation processes, resulting in different obfuscated names for the interfaces exposed by the shared local source code HAR.
1168
1169**Solution**
1170
11711. Change the shared local source code HAR to a [bytecode HAR](https://developer.huawei.com/consumer/en/doc/harmonyos-guides-V5/ide-hvigor-build-har-V5#section179161312181613). This prevents the HAR from being re-obfuscated when being depended upon.
11722. Build the shared local source code HAR in [release mode](https://developer.huawei.com/consumer/en/doc/harmonyos-guides-V5/ide-hvigor-build-har-V5#section19788284410). This ensures that file names and exported interfaces are not obfuscated when the HAR is depended upon.
1173
1174#### Problems that may occur when **both -enable-property-obfuscation** and **-keep** are enabled.
1175
1176**Symptom**
1177
1178The following obfuscation configuration is used:
1179
1180```
1181-enable-property-obfuscation
1182-keep
1183./file1.ts
1184```
1185
1186**file2.ts** imports an interface from **file1.ts**, and the interface contains object-type properties. As a result, these properties are retained in **file1.ts** but obfuscated in **file2.ts**, leading to function exceptions. Example:
1187
1188```
1189// Before obfuscation:
1190// file1.ts
1191export interface MyInfo {
1192  age: number;
1193  address: {
1194    city1: string;
1195  }
1196}
1197
1198// file2.ts
1199import { MyInfo } from './file1';
1200const person: MyInfo = {
1201  age: 20,
1202  address: {
1203    city1: "shanghai"
1204  }
1205}
1206
1207// After obfuscation, the code of file1.ts is retained.
1208// file2.ts
1209import { MyInfo } from './file1';
1210const person: MyInfo = {
1211  age: 20,
1212  address: {
1213    i: "shanghai"
1214  }
1215}
1216```
1217
1218**Possible Causes**
1219
1220The **-keep** option retains the code in the **file1.ts** file, but properties within exported types (for example, **address**) are not automatically added to the property trustlist. Therefore, these properties are obfuscated when being used in other files.
1221
1222**Solution**
1223
1224Solution 1: Define the property type using **interface** and export it. This will automatically add the property to the trustlist. Example:
1225
1226```
1227// file1.ts
1228export interface AddressType {
1229  city1: string
1230}
1231export interface MyInfo {
1232  age: number;
1233  address: AddressType;
1234}
1235```
1236
1237Solution 2: Use the **-keep-property-name** option to add properties within types that are not directly exported to the trustlist. Example:
1238
1239```
1240-keep-property-name
1241city1
1242```
1243