shiplint 1.3.0 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.js +1 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/core/scanner.d.ts.map +1 -1
- package/dist/core/scanner.js +5 -1
- package/dist/core/scanner.js.map +1 -1
- package/dist/core/suppression.d.ts +23 -0
- package/dist/core/suppression.d.ts.map +1 -0
- package/dist/core/suppression.js +183 -0
- package/dist/core/suppression.js.map +1 -0
- package/dist/formatters/text.d.ts +1 -0
- package/dist/formatters/text.d.ts.map +1 -1
- package/dist/formatters/text.js +92 -15
- package/dist/formatters/text.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -1
- package/dist/index.js.map +1 -1
- package/dist/rules/base.d.ts +2 -0
- package/dist/rules/base.d.ts.map +1 -1
- package/dist/rules/base.js +2 -0
- package/dist/rules/base.js.map +1 -1
- package/dist/rules/code/dynamic-code-execution.d.ts +13 -0
- package/dist/rules/code/dynamic-code-execution.d.ts.map +1 -0
- package/dist/rules/code/dynamic-code-execution.js +212 -0
- package/dist/rules/code/dynamic-code-execution.js.map +1 -0
- package/dist/rules/code/index.d.ts +6 -0
- package/dist/rules/code/index.d.ts.map +1 -0
- package/dist/rules/code/index.js +11 -0
- package/dist/rules/code/index.js.map +1 -0
- package/dist/rules/code/private-api-usage.d.ts +12 -0
- package/dist/rules/code/private-api-usage.d.ts.map +1 -0
- package/dist/rules/code/private-api-usage.js +234 -0
- package/dist/rules/code/private-api-usage.js.map +1 -0
- package/dist/rules/index.d.ts +1 -0
- package/dist/rules/index.d.ts.map +1 -1
- package/dist/rules/index.js +6 -0
- package/dist/rules/index.js.map +1 -1
- package/dist/rules/privacy/att-tracking-mismatch.d.ts.map +1 -1
- package/dist/rules/privacy/att-tracking-mismatch.js +16 -0
- package/dist/rules/privacy/att-tracking-mismatch.js.map +1 -1
- package/dist/types/index.d.ts +8 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.DynamicCodeExecutionRule = void 0;
|
|
37
|
+
const index_js_1 = require("../../types/index.js");
|
|
38
|
+
const base_js_1 = require("../base.js");
|
|
39
|
+
const required_reason_api_js_1 = require("../privacy/required-reason-api.js");
|
|
40
|
+
const fs = __importStar(require("fs"));
|
|
41
|
+
const path = __importStar(require("path"));
|
|
42
|
+
/**
|
|
43
|
+
* Well-known Apple framework classes that are safe with NSClassFromString
|
|
44
|
+
*/
|
|
45
|
+
const SAFE_NSCLASSFROMSTRING = new Set([
|
|
46
|
+
// UIKit
|
|
47
|
+
'UIViewController', 'UINavigationController', 'UITabBarController',
|
|
48
|
+
'UITableViewController', 'UICollectionViewController', 'UIAlertController',
|
|
49
|
+
'UIActivityViewController', 'UISplitViewController', 'UISearchController',
|
|
50
|
+
'UIPageViewController', 'UIDocumentPickerViewController',
|
|
51
|
+
'SFSafariViewController', 'SKStoreProductViewController',
|
|
52
|
+
'MFMailComposeViewController', 'MFMessageComposeViewController',
|
|
53
|
+
'UIImagePickerController', 'PHPickerViewController',
|
|
54
|
+
'UIColorPickerViewController', 'UIFontPickerViewController',
|
|
55
|
+
'CNContactPickerViewController', 'EKEventEditViewController',
|
|
56
|
+
'QLPreviewController', 'ASWebAuthenticationSession',
|
|
57
|
+
'ASAuthorizationController', 'WKWebView',
|
|
58
|
+
// SwiftUI
|
|
59
|
+
'UIHostingController',
|
|
60
|
+
// Common patterns in well-known frameworks (Firebase, etc.)
|
|
61
|
+
'FIRApp', 'FIRAnalytics', 'FIRCrashlytics',
|
|
62
|
+
// Accessibility
|
|
63
|
+
'UIAccessibility',
|
|
64
|
+
// Test detection (common pattern)
|
|
65
|
+
'XCTestCase', 'XCTest',
|
|
66
|
+
]);
|
|
67
|
+
/**
|
|
68
|
+
* Patterns for JSContext evaluateScript
|
|
69
|
+
*/
|
|
70
|
+
const JS_EVAL_PATTERNS = [
|
|
71
|
+
/\bJSContext\s*\(\s*\)\.evaluateScript\b/,
|
|
72
|
+
/\bevaluateScript\s*\(/,
|
|
73
|
+
/\bJSContext\b[^}]*\.evaluateScript\b/s,
|
|
74
|
+
];
|
|
75
|
+
/**
|
|
76
|
+
* Patterns for dlopen/dlsym
|
|
77
|
+
*/
|
|
78
|
+
const DLOPEN_PATTERNS = [
|
|
79
|
+
/\bdlopen\s*\(/,
|
|
80
|
+
/\bdlsym\s*\(/,
|
|
81
|
+
];
|
|
82
|
+
/**
|
|
83
|
+
* Patterns for NSBundle load (dynamic framework loading)
|
|
84
|
+
* Must be specific to Bundle/NSBundle to avoid false positives on .load() on other types
|
|
85
|
+
*/
|
|
86
|
+
const BUNDLE_LOAD_PATTERNS = [
|
|
87
|
+
/\bNSBundle\b[^;\n]*\.load\s*\(/,
|
|
88
|
+
/\bBundle\s*\([^)]*\)\s*[.!?]*\s*\.load\s*\(/,
|
|
89
|
+
/\bbundle\s*\.load\s*\(/,
|
|
90
|
+
/\bloadAndReturnError\b/,
|
|
91
|
+
];
|
|
92
|
+
exports.DynamicCodeExecutionRule = {
|
|
93
|
+
id: 'code-003-dynamic-code-execution',
|
|
94
|
+
name: 'Dynamic Code Execution',
|
|
95
|
+
description: 'Detects dynamic code loading/execution that violates App Store guidelines',
|
|
96
|
+
category: index_js_1.RuleCategory.Config,
|
|
97
|
+
severity: index_js_1.Severity.Critical,
|
|
98
|
+
confidence: index_js_1.Confidence.High,
|
|
99
|
+
guidelineReference: '2.5.2',
|
|
100
|
+
async evaluate(context) {
|
|
101
|
+
const sourceFiles = (0, required_reason_api_js_1.findSourceFiles)(context.projectPath);
|
|
102
|
+
const detections = [];
|
|
103
|
+
for (const file of sourceFiles) {
|
|
104
|
+
let content;
|
|
105
|
+
try {
|
|
106
|
+
content = fs.readFileSync(file, 'utf-8');
|
|
107
|
+
}
|
|
108
|
+
catch {
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
const lines = content.split('\n');
|
|
112
|
+
for (let i = 0; i < lines.length; i++) {
|
|
113
|
+
const line = lines[i];
|
|
114
|
+
const lineNum = i + 1;
|
|
115
|
+
const trimmed = line.trim();
|
|
116
|
+
// Skip comments
|
|
117
|
+
if (trimmed.startsWith('//') || trimmed.startsWith('*') || trimmed.startsWith('/*'))
|
|
118
|
+
continue;
|
|
119
|
+
// JSContext evaluateScript
|
|
120
|
+
for (const pattern of JS_EVAL_PATTERNS) {
|
|
121
|
+
if (pattern.test(line)) {
|
|
122
|
+
detections.push({ file, line: lineNum, kind: 'js-eval', match: 'JSContext.evaluateScript' });
|
|
123
|
+
break;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
// dlopen/dlsym
|
|
127
|
+
for (const pattern of DLOPEN_PATTERNS) {
|
|
128
|
+
if (pattern.test(line)) {
|
|
129
|
+
// Avoid false positive for test files or comments
|
|
130
|
+
const fn = line.match(/\b(dlopen|dlsym)\b/)?.[1] ?? 'dlopen/dlsym';
|
|
131
|
+
detections.push({ file, line: lineNum, kind: 'dlopen', match: fn });
|
|
132
|
+
break;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
// NSClassFromString with suspicious classes
|
|
136
|
+
const nscMatch = line.match(/NSClassFromString\(\s*"(\w+)"\s*\)/);
|
|
137
|
+
if (nscMatch) {
|
|
138
|
+
const className = nscMatch[1];
|
|
139
|
+
// Safe prefixes: Apple framework conventions
|
|
140
|
+
const safePrefixes = ['UI', 'NS', 'CL', 'MK', 'AV', 'SK', 'WK', 'SF', 'AS', 'CN', 'EK', 'QL', 'MF', 'PH', 'XC', 'CA', 'CK', 'HK', 'MT', 'SC', 'GK', 'FIR', 'GID', 'FB'];
|
|
141
|
+
const isSafe = SAFE_NSCLASSFROMSTRING.has(className) || safePrefixes.some(p => className.startsWith(p));
|
|
142
|
+
if (!isSafe) {
|
|
143
|
+
detections.push({ file, line: lineNum, kind: 'nsclass-suspicious', match: className });
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
// NSBundle load patterns — only flag explicit Bundle/NSBundle.load() calls
|
|
147
|
+
for (const pattern of BUNDLE_LOAD_PATTERNS) {
|
|
148
|
+
if (pattern.test(line)) {
|
|
149
|
+
// Must actually reference Bundle/NSBundle
|
|
150
|
+
if (/\b(Bundle|NSBundle|bundle)\b/.test(line)) {
|
|
151
|
+
// Avoid false positives on resource bundles
|
|
152
|
+
if (!/\b(UIImage|NSImage|UIFont|NSFont|UIStoryboard|UIViewController)\b/.test(line) &&
|
|
153
|
+
!/\bnib\b/i.test(line) && !/\bstoryboard\b/i.test(line) &&
|
|
154
|
+
!/\bresource\b/i.test(line)) {
|
|
155
|
+
detections.push({ file, line: lineNum, kind: 'bundle-load', match: 'NSBundle.load' });
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
break;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
if (detections.length === 0)
|
|
164
|
+
return [];
|
|
165
|
+
const findings = [];
|
|
166
|
+
// Emit per-detection findings with line numbers for suppression support
|
|
167
|
+
for (const det of detections) {
|
|
168
|
+
const relFile = path.relative(context.projectPath, det.file);
|
|
169
|
+
switch (det.kind) {
|
|
170
|
+
case 'js-eval':
|
|
171
|
+
findings.push((0, base_js_1.makeFinding)(this, {
|
|
172
|
+
title: 'JavaScript Evaluation at Runtime',
|
|
173
|
+
description: `JSContext.evaluateScript detected in ${relFile}:${det.line}. Executing dynamically downloaded JavaScript code can cause rejection.`,
|
|
174
|
+
location: relFile,
|
|
175
|
+
line: det.line,
|
|
176
|
+
fixGuidance: 'If using JavaScriptCore for app logic, ensure scripts are bundled with the app binary, not downloaded at runtime. Consider using native Swift/ObjC instead.',
|
|
177
|
+
}));
|
|
178
|
+
break;
|
|
179
|
+
case 'dlopen':
|
|
180
|
+
case 'dlsym':
|
|
181
|
+
findings.push((0, base_js_1.makeFinding)(this, {
|
|
182
|
+
title: 'Dynamic Library Loading (dlopen/dlsym)',
|
|
183
|
+
description: `dlopen/dlsym call detected in ${relFile}:${det.line}. Loading executable code at runtime violates App Store guidelines.`,
|
|
184
|
+
location: relFile,
|
|
185
|
+
line: det.line,
|
|
186
|
+
fixGuidance: 'Remove dlopen/dlsym calls. Link frameworks at build time instead of loading them dynamically at runtime.',
|
|
187
|
+
}));
|
|
188
|
+
break;
|
|
189
|
+
case 'nsclass-suspicious':
|
|
190
|
+
findings.push((0, base_js_1.makeCustomFinding)(this, index_js_1.Severity.Medium, index_js_1.Confidence.Medium, {
|
|
191
|
+
title: 'Suspicious NSClassFromString Usage',
|
|
192
|
+
description: `NSClassFromString used with non-standard class (${det.match}) in ${relFile}:${det.line}. This may indicate runtime class resolution for code loading.`,
|
|
193
|
+
location: relFile,
|
|
194
|
+
line: det.line,
|
|
195
|
+
fixGuidance: 'Use direct class references instead of NSClassFromString where possible. If used for optional framework detection, ensure the class is from a public Apple framework.',
|
|
196
|
+
}));
|
|
197
|
+
break;
|
|
198
|
+
case 'bundle-load':
|
|
199
|
+
findings.push((0, base_js_1.makeCustomFinding)(this, index_js_1.Severity.High, index_js_1.Confidence.Medium, {
|
|
200
|
+
title: 'Dynamic Bundle Loading',
|
|
201
|
+
description: `NSBundle.load() or equivalent detected in ${relFile}:${det.line}. Loading executable bundles at runtime may violate App Store guidelines.`,
|
|
202
|
+
location: relFile,
|
|
203
|
+
line: det.line,
|
|
204
|
+
fixGuidance: 'Link frameworks at build time. If loading resource bundles (not code), this is fine — verify the bundle contains only resources.',
|
|
205
|
+
}));
|
|
206
|
+
break;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
return findings;
|
|
210
|
+
},
|
|
211
|
+
};
|
|
212
|
+
//# sourceMappingURL=dynamic-code-execution.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dynamic-code-execution.js","sourceRoot":"","sources":["../../../src/rules/code/dynamic-code-execution.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/rules/code/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DynamicCodeExecutionRule = exports.PrivateAPIUsageRule = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Code analysis rules - detect rejection-causing code patterns
|
|
6
|
+
*/
|
|
7
|
+
var private_api_usage_js_1 = require("./private-api-usage.js");
|
|
8
|
+
Object.defineProperty(exports, "PrivateAPIUsageRule", { enumerable: true, get: function () { return private_api_usage_js_1.PrivateAPIUsageRule; } });
|
|
9
|
+
var dynamic_code_execution_js_1 = require("./dynamic-code-execution.js");
|
|
10
|
+
Object.defineProperty(exports, "DynamicCodeExecutionRule", { enumerable: true, get: function () { return dynamic_code_execution_js_1.DynamicCodeExecutionRule; } });
|
|
11
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/rules/code/index.ts"],"names":[],"mappings":";;;AAAA;;GAEG;AACH,+DAA6D;AAApD,2HAAA,mBAAmB,OAAA;AAC5B,yEAAuE;AAA9D,qIAAA,wBAAwB,OAAA"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rule: Private API Usage (§2.5.1)
|
|
3
|
+
*
|
|
4
|
+
* Detects usage of private/undocumented Apple APIs that cause App Store rejection:
|
|
5
|
+
* - UIWebView (deprecated, rejected since iOS 12)
|
|
6
|
+
* - valueForKey/setValue:forKey on UIKit private properties (_placeholderLabel, _searchField, etc.)
|
|
7
|
+
* - Known private framework imports
|
|
8
|
+
* - objc_msgSend to known private selectors
|
|
9
|
+
*/
|
|
10
|
+
import type { Rule } from '../../types/index.js';
|
|
11
|
+
export declare const PrivateAPIUsageRule: Rule;
|
|
12
|
+
//# sourceMappingURL=private-api-usage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"private-api-usage.d.ts","sourceRoot":"","sources":["../../../src/rules/code/private-api-usage.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,EAAE,IAAI,EAAwB,MAAM,sBAAsB,CAAC;AA+FvE,eAAO,MAAM,mBAAmB,EAAE,IA8HjC,CAAC"}
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.PrivateAPIUsageRule = void 0;
|
|
37
|
+
const index_js_1 = require("../../types/index.js");
|
|
38
|
+
const base_js_1 = require("../base.js");
|
|
39
|
+
const required_reason_api_js_1 = require("../privacy/required-reason-api.js");
|
|
40
|
+
const fs = __importStar(require("fs"));
|
|
41
|
+
const path = __importStar(require("path"));
|
|
42
|
+
/**
|
|
43
|
+
* Known private UIKit properties accessed via KVC
|
|
44
|
+
*/
|
|
45
|
+
const PRIVATE_KVC_PROPERTIES = [
|
|
46
|
+
'_placeholderLabel',
|
|
47
|
+
'_searchField',
|
|
48
|
+
'_placeholderColor',
|
|
49
|
+
'_backgroundView',
|
|
50
|
+
'_navigationBarBackIndicatorView',
|
|
51
|
+
'_barTintColor',
|
|
52
|
+
'_titleView',
|
|
53
|
+
'_leftViews',
|
|
54
|
+
'_rightViews',
|
|
55
|
+
'_contentView',
|
|
56
|
+
'_backdropView',
|
|
57
|
+
'_cancelButton',
|
|
58
|
+
'_cancelButtonText',
|
|
59
|
+
'_UINavigationBarBackground',
|
|
60
|
+
'_barPosition',
|
|
61
|
+
'_statusBarWindow',
|
|
62
|
+
'_statusBar',
|
|
63
|
+
];
|
|
64
|
+
/**
|
|
65
|
+
* Known private framework headers
|
|
66
|
+
*/
|
|
67
|
+
const PRIVATE_FRAMEWORK_IMPORTS = [
|
|
68
|
+
/^\s*#import\s+<UIKit\/UI\w+_Private\.h>/,
|
|
69
|
+
/^\s*#import\s+<UIKit\/UIStatusBar\.h>/,
|
|
70
|
+
/^\s*#import\s+<GraphicsServices\//,
|
|
71
|
+
/^\s*#import\s+<SpringBoardServices\//,
|
|
72
|
+
/^\s*#import\s+<BackBoardServices\//,
|
|
73
|
+
/^\s*#import\s+<MobileInstallation\//,
|
|
74
|
+
/^\s*#import\s+<AppSupport\//,
|
|
75
|
+
/^\s*@import\s+UIKitCore\b/,
|
|
76
|
+
];
|
|
77
|
+
/**
|
|
78
|
+
* Patterns for UIWebView usage
|
|
79
|
+
*/
|
|
80
|
+
const UIWEBVIEW_PATTERNS = [
|
|
81
|
+
/\bUIWebView\b/,
|
|
82
|
+
];
|
|
83
|
+
/**
|
|
84
|
+
* Patterns for private KVC access on UIKit objects
|
|
85
|
+
* We look for valueForKey/setValue:forKey with known private property strings
|
|
86
|
+
*/
|
|
87
|
+
function buildKVCPatterns() {
|
|
88
|
+
const patterns = [];
|
|
89
|
+
for (const prop of PRIVATE_KVC_PROPERTIES) {
|
|
90
|
+
// Swift: value(forKey: "_placeholderLabel")
|
|
91
|
+
patterns.push(new RegExp(`value\\(forKey:\\s*"${escapeRegex(prop)}"\\)`));
|
|
92
|
+
// Swift: setValue(xxx, forKey: "_placeholderLabel")
|
|
93
|
+
patterns.push(new RegExp(`setValue\\([^)]*forKey:\\s*"${escapeRegex(prop)}"\\)`));
|
|
94
|
+
// ObjC: [xxx valueForKey:@"_placeholderLabel"]
|
|
95
|
+
patterns.push(new RegExp(`valueForKey:\\s*@"${escapeRegex(prop)}"`));
|
|
96
|
+
// ObjC: [xxx setValue:xxx forKey:@"_placeholderLabel"]
|
|
97
|
+
patterns.push(new RegExp(`setValue:[^\\]]*forKey:\\s*@"${escapeRegex(prop)}"`));
|
|
98
|
+
}
|
|
99
|
+
return patterns;
|
|
100
|
+
}
|
|
101
|
+
function escapeRegex(s) {
|
|
102
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Patterns for objc_msgSend with suspicious selectors
|
|
106
|
+
*/
|
|
107
|
+
const OBJC_MSGSEND_PRIVATE_PATTERNS = [
|
|
108
|
+
/\bobjc_msgSend\s*\([^,]+,\s*@selector\(\s*_\w+\s*\)/,
|
|
109
|
+
/\bobjc_msgSend\s*\([^,]+,\s*sel_registerName\(\s*"_\w+/,
|
|
110
|
+
/\bNSSelectorFromString\(\s*@?"_\w+"\s*\)/,
|
|
111
|
+
/\bSelectortor\(\s*"_\w+"\s*\)/,
|
|
112
|
+
/\bSelector\(\s*"_\w+"\s*\)/,
|
|
113
|
+
/\b#selector\(\s*_\w+\)/,
|
|
114
|
+
];
|
|
115
|
+
const KVC_PATTERNS = buildKVCPatterns();
|
|
116
|
+
exports.PrivateAPIUsageRule = {
|
|
117
|
+
id: 'code-001-private-api-usage',
|
|
118
|
+
name: 'Private API Usage',
|
|
119
|
+
description: 'Detects usage of private/undocumented Apple APIs that cause App Store rejection',
|
|
120
|
+
category: index_js_1.RuleCategory.Config,
|
|
121
|
+
severity: index_js_1.Severity.Critical,
|
|
122
|
+
confidence: index_js_1.Confidence.High,
|
|
123
|
+
guidelineReference: '2.5.1',
|
|
124
|
+
async evaluate(context) {
|
|
125
|
+
const sourceFiles = (0, required_reason_api_js_1.findSourceFiles)(context.projectPath);
|
|
126
|
+
const detections = [];
|
|
127
|
+
for (const file of sourceFiles) {
|
|
128
|
+
let content;
|
|
129
|
+
try {
|
|
130
|
+
content = fs.readFileSync(file, 'utf-8');
|
|
131
|
+
}
|
|
132
|
+
catch {
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
const lines = content.split('\n');
|
|
136
|
+
for (let i = 0; i < lines.length; i++) {
|
|
137
|
+
const line = lines[i];
|
|
138
|
+
const lineNum = i + 1;
|
|
139
|
+
// Skip comments
|
|
140
|
+
const trimmed = line.trim();
|
|
141
|
+
if (trimmed.startsWith('//') || trimmed.startsWith('*') || trimmed.startsWith('/*'))
|
|
142
|
+
continue;
|
|
143
|
+
// UIWebView
|
|
144
|
+
for (const pattern of UIWEBVIEW_PATTERNS) {
|
|
145
|
+
if (pattern.test(line)) {
|
|
146
|
+
// Avoid false positive: WKWebView contains "WebView" but not "UIWebView"
|
|
147
|
+
// Also skip if it's in a comment about migration
|
|
148
|
+
if (!trimmed.startsWith('//') && !trimmed.startsWith('*')) {
|
|
149
|
+
detections.push({ file, line: lineNum, kind: 'uiwebview', match: 'UIWebView' });
|
|
150
|
+
}
|
|
151
|
+
break;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
// Private KVC
|
|
155
|
+
for (const pattern of KVC_PATTERNS) {
|
|
156
|
+
if (pattern.test(line)) {
|
|
157
|
+
const m = line.match(/"(_\w+)"/);
|
|
158
|
+
detections.push({
|
|
159
|
+
file, line: lineNum, kind: 'private-kvc',
|
|
160
|
+
match: m ? m[1] : 'private property',
|
|
161
|
+
});
|
|
162
|
+
break;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
// Private framework imports
|
|
166
|
+
for (const pattern of PRIVATE_FRAMEWORK_IMPORTS) {
|
|
167
|
+
if (pattern.test(line)) {
|
|
168
|
+
detections.push({ file, line: lineNum, kind: 'private-import', match: trimmed });
|
|
169
|
+
break;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
// Private selectors via objc_msgSend/NSSelectorFromString
|
|
173
|
+
for (const pattern of OBJC_MSGSEND_PRIVATE_PATTERNS) {
|
|
174
|
+
if (pattern.test(line)) {
|
|
175
|
+
const m = line.match(/"(_\w+)"/);
|
|
176
|
+
detections.push({
|
|
177
|
+
file, line: lineNum, kind: 'private-selector',
|
|
178
|
+
match: m ? m[1] : 'private selector',
|
|
179
|
+
});
|
|
180
|
+
break;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
if (detections.length === 0)
|
|
186
|
+
return [];
|
|
187
|
+
const findings = [];
|
|
188
|
+
// Emit per-detection findings with line numbers for suppression support
|
|
189
|
+
for (const det of detections) {
|
|
190
|
+
const relFile = path.relative(context.projectPath, det.file);
|
|
191
|
+
switch (det.kind) {
|
|
192
|
+
case 'uiwebview':
|
|
193
|
+
findings.push((0, base_js_1.makeFinding)(this, {
|
|
194
|
+
title: 'UIWebView Usage (Deprecated & Rejected)',
|
|
195
|
+
description: `UIWebView is deprecated since iOS 12 and Apple rejects apps that reference it. Found in: ${relFile}:${det.line}`,
|
|
196
|
+
location: relFile,
|
|
197
|
+
line: det.line,
|
|
198
|
+
fixGuidance: 'Replace all UIWebView usage with WKWebView. Also check your dependencies — some older pods still reference UIWebView.',
|
|
199
|
+
documentationURL: 'https://developer.apple.com/documentation/webkit/wkwebview',
|
|
200
|
+
}));
|
|
201
|
+
break;
|
|
202
|
+
case 'private-kvc':
|
|
203
|
+
findings.push((0, base_js_1.makeFinding)(this, {
|
|
204
|
+
title: 'Private UIKit Property Access via KVC',
|
|
205
|
+
description: `Accessing private UIKit property (${det.match}) via valueForKey/setValue:forKey will cause App Store rejection. Found in: ${relFile}:${det.line}`,
|
|
206
|
+
location: relFile,
|
|
207
|
+
line: det.line,
|
|
208
|
+
fixGuidance: 'Use public API alternatives instead of KVC on private properties. For placeholder color, use attributedPlaceholder. For search fields, use searchTextField (iOS 13+).',
|
|
209
|
+
}));
|
|
210
|
+
break;
|
|
211
|
+
case 'private-import':
|
|
212
|
+
findings.push((0, base_js_1.makeFinding)(this, {
|
|
213
|
+
title: 'Private Framework Import',
|
|
214
|
+
description: `Importing private/undocumented Apple frameworks will cause App Store rejection. Found in: ${relFile}:${det.line}`,
|
|
215
|
+
location: relFile,
|
|
216
|
+
line: det.line,
|
|
217
|
+
fixGuidance: 'Remove imports of private Apple frameworks and use only public APIs.',
|
|
218
|
+
}));
|
|
219
|
+
break;
|
|
220
|
+
case 'private-selector':
|
|
221
|
+
findings.push((0, base_js_1.makeFinding)(this, {
|
|
222
|
+
title: 'Private Selector Usage',
|
|
223
|
+
description: `Using private selector (${det.match}) via objc_msgSend or NSSelectorFromString will cause App Store rejection. Found in: ${relFile}:${det.line}`,
|
|
224
|
+
location: relFile,
|
|
225
|
+
line: det.line,
|
|
226
|
+
fixGuidance: 'Replace private selector calls with equivalent public API methods.',
|
|
227
|
+
}));
|
|
228
|
+
break;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
return findings;
|
|
232
|
+
},
|
|
233
|
+
};
|
|
234
|
+
//# sourceMappingURL=private-api-usage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"private-api-usage.js","sourceRoot":"","sources":["../../../src/rules/code/private-api-usage.ts"],"names":[],"mappings":"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"}
|
package/dist/rules/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/rules/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAG9C,cAAc,oBAAoB,CAAC;AAGnC,cAAc,iBAAiB,CAAC;AAGhC,cAAc,qBAAqB,CAAC;AAGpC,cAAc,mBAAmB,CAAC;AAGlC,cAAc,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/rules/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAG9C,cAAc,oBAAoB,CAAC;AAGnC,cAAc,iBAAiB,CAAC;AAGhC,cAAc,qBAAqB,CAAC;AAGpC,cAAc,mBAAmB,CAAC;AAGlC,cAAc,iBAAiB,CAAC;AAGhC,cAAc,WAAW,CAAC;AAsB1B;;GAEG;AACH,eAAO,MAAM,QAAQ,EAAE,IAAI,EAmB1B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,IAAI,CAE1C,CAAC;AAEF;;GAEG;AACH,wBAAgB,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAEpD;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE,GAAG,gBAAgB,CAkBvE;AAED;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,CAE/C;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,CAG9D"}
|
package/dist/rules/index.js
CHANGED
|
@@ -27,6 +27,8 @@ __exportStar(require("./auth/index.js"), exports);
|
|
|
27
27
|
__exportStar(require("./metadata/index.js"), exports);
|
|
28
28
|
// Config rules
|
|
29
29
|
__exportStar(require("./config/index.js"), exports);
|
|
30
|
+
// Code analysis rules
|
|
31
|
+
__exportStar(require("./code/index.js"), exports);
|
|
30
32
|
// Base utilities
|
|
31
33
|
__exportStar(require("./base.js"), exports);
|
|
32
34
|
// Import all rules for registry
|
|
@@ -46,6 +48,8 @@ const missing_bluetooth_purpose_js_1 = require("./privacy/missing-bluetooth-purp
|
|
|
46
48
|
const missing_face_id_purpose_js_1 = require("./privacy/missing-face-id-purpose.js");
|
|
47
49
|
const missing_supported_orientations_js_1 = require("./metadata/missing-supported-orientations.js");
|
|
48
50
|
const required_reason_api_js_1 = require("./privacy/required-reason-api.js");
|
|
51
|
+
const private_api_usage_js_1 = require("./code/private-api-usage.js");
|
|
52
|
+
const dynamic_code_execution_js_1 = require("./code/dynamic-code-execution.js");
|
|
49
53
|
/**
|
|
50
54
|
* All available rules
|
|
51
55
|
*/
|
|
@@ -66,6 +70,8 @@ exports.allRules = [
|
|
|
66
70
|
missing_encryption_flag_js_1.MissingEncryptionFlagRule,
|
|
67
71
|
missing_launch_storyboard_js_1.MissingLaunchStoryboardRule,
|
|
68
72
|
required_reason_api_js_1.RequiredReasonAPIRule,
|
|
73
|
+
private_api_usage_js_1.PrivateAPIUsageRule,
|
|
74
|
+
dynamic_code_execution_js_1.DynamicCodeExecutionRule,
|
|
69
75
|
];
|
|
70
76
|
/**
|
|
71
77
|
* Rule registry - maps rule IDs to rule instances
|
package/dist/rules/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/rules/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/rules/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AA6EA,0BAEC;AAcD,wDAkBC;AAMD,4BAEC;AAKD,8CAGC;AA1HD,gBAAgB;AAChB,qDAAmC;AAEnC,aAAa;AACb,kDAAgC;AAEhC,iBAAiB;AACjB,sDAAoC;AAEpC,eAAe;AACf,oDAAkC;AAElC,sBAAsB;AACtB,kDAAgC;AAEhC,iBAAiB;AACjB,4CAA0B;AAE1B,gCAAgC;AAChC,mFAA+E;AAC/E,uFAAmF;AACnF,6FAAyF;AACzF,iFAA6E;AAC7E,iGAA4F;AAC5F,2FAAuF;AACvF,uFAAmF;AACnF,sFAAgF;AAChF,wFAAoF;AACpF,4GAAuG;AACvG,oFAAgF;AAChF,wFAAoF;AACpF,yFAAqF;AACrF,qFAAgF;AAChF,oGAAgG;AAChG,6EAAyE;AACzE,sEAAkE;AAClE,gFAA4E;AAE5E;;GAEG;AACU,QAAA,QAAQ,GAAW;IAC9B,oDAAwB;IACxB,wDAA0B;IAC1B,8DAA6B;IAC7B,kDAAuB;IACvB,iEAA8B;IAC9B,4DAA4B;IAC5B,wDAA0B;IAC1B,0DAA2B;IAC3B,qDAAwB;IACxB,wDAAyB;IACzB,wDAA0B;IAC1B,oEAAgC;IAChC,6EAAoC;IACpC,sDAAyB;IACzB,0DAA2B;IAC3B,8CAAqB;IACrB,0CAAmB;IACnB,oDAAwB;CACzB,CAAC;AAEF;;GAEG;AACU,QAAA,YAAY,GAAsB,IAAI,GAAG,CACpD,gBAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC,CACtC,CAAC;AAEF;;GAEG;AACH,SAAgB,OAAO,CAAC,EAAU;IAChC,OAAO,oBAAY,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;AAC9B,CAAC;AAUD;;;GAGG;AACH,SAAgB,sBAAsB,CAAC,GAAc;IACnD,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC7B,OAAO,EAAE,KAAK,EAAE,gBAAQ,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC;IAC7C,CAAC;IAED,MAAM,KAAK,GAAW,EAAE,CAAC;IACzB,MAAM,UAAU,GAAa,EAAE,CAAC;IAEhC,KAAK,MAAM,EAAE,IAAI,GAAG,EAAE,CAAC;QACrB,MAAM,IAAI,GAAG,oBAAY,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAClC,IAAI,IAAI,EAAE,CAAC;YACT,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACnB,CAAC;aAAM,CAAC;YACN,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACtB,CAAC;IACH,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC;AAC/B,CAAC;AAED;;;GAGG;AACH,SAAgB,QAAQ,CAAC,GAAc;IACrC,OAAO,sBAAsB,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC;AAC3C,CAAC;AAED;;GAEG;AACH,SAAgB,iBAAiB,CAAC,UAAoB;IACpD,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,CAAC;IACvC,OAAO,gBAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;AAC3D,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"att-tracking-mismatch.d.ts","sourceRoot":"","sources":["../../../src/rules/privacy/att-tracking-mismatch.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,EAAE,IAAI,EAAwB,MAAM,sBAAsB,CAAC;AASvE,eAAO,MAAM,uBAAuB,EAAE,
|
|
1
|
+
{"version":3,"file":"att-tracking-mismatch.d.ts","sourceRoot":"","sources":["../../../src/rules/privacy/att-tracking-mismatch.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,EAAE,IAAI,EAAwB,MAAM,sBAAsB,CAAC;AASvE,eAAO,MAAM,uBAAuB,EAAE,IA+HrC,CAAC"}
|
|
@@ -18,6 +18,22 @@ exports.ATTTrackingMismatchRule = {
|
|
|
18
18
|
async evaluate(context) {
|
|
19
19
|
// Detect tracking SDKs from dependencies
|
|
20
20
|
const detectedSDKs = (0, framework_detector_js_1.detectTrackingSDKs)(context.dependencies);
|
|
21
|
+
// Also detect from linked frameworks / Swift imports
|
|
22
|
+
const trackingFrameworkMap = {
|
|
23
|
+
'AdSupport': 'AdSupport (IDFA)',
|
|
24
|
+
'FBSDKCoreKit': 'Facebook SDK',
|
|
25
|
+
'FacebookCore': 'Facebook SDK',
|
|
26
|
+
'FBAudienceNetwork': 'Facebook Audience Network',
|
|
27
|
+
'GoogleMobileAds': 'Google Mobile Ads',
|
|
28
|
+
'FirebaseAnalytics': 'Firebase Analytics',
|
|
29
|
+
'Adjust': 'Adjust',
|
|
30
|
+
'AppsFlyerLib': 'AppsFlyer',
|
|
31
|
+
};
|
|
32
|
+
for (const [framework, name] of Object.entries(trackingFrameworkMap)) {
|
|
33
|
+
if (context.hasFramework(framework) && !detectedSDKs.includes(name)) {
|
|
34
|
+
detectedSDKs.push(name);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
21
37
|
if (detectedSDKs.length === 0) {
|
|
22
38
|
return [];
|
|
23
39
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"att-tracking-mismatch.js","sourceRoot":"","sources":["../../../src/rules/privacy/att-tracking-mismatch.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"att-tracking-mismatch.js","sourceRoot":"","sources":["../../../src/rules/privacy/att-tracking-mismatch.ts"],"names":[],"mappings":"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"}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -58,9 +58,15 @@ export interface Finding {
|
|
|
58
58
|
title: string;
|
|
59
59
|
description: string;
|
|
60
60
|
location?: string;
|
|
61
|
+
/** Line number in the source file (1-indexed) */
|
|
62
|
+
line?: number;
|
|
61
63
|
guideline: string;
|
|
62
64
|
fixGuidance: string;
|
|
63
65
|
documentationURL?: string;
|
|
66
|
+
/** Whether this finding was suppressed */
|
|
67
|
+
suppressed?: boolean;
|
|
68
|
+
/** Reason for suppression */
|
|
69
|
+
suppressionReason?: string;
|
|
64
70
|
}
|
|
65
71
|
/**
|
|
66
72
|
* Result of a scan
|
|
@@ -69,6 +75,7 @@ export interface ScanResult {
|
|
|
69
75
|
projectPath: string;
|
|
70
76
|
timestamp: Date;
|
|
71
77
|
findings: Finding[];
|
|
78
|
+
suppressedFindings: Finding[];
|
|
72
79
|
rulesRun: string[];
|
|
73
80
|
duration: number;
|
|
74
81
|
/** Project type detected: xcodeproj, swiftpm, both, or unknown */
|
|
@@ -159,5 +166,6 @@ export interface ScanOptions {
|
|
|
159
166
|
verbose?: boolean;
|
|
160
167
|
rules?: string[];
|
|
161
168
|
exclude?: string[];
|
|
169
|
+
showSuppressed?: boolean;
|
|
162
170
|
}
|
|
163
171
|
//# sourceMappingURL=index.d.ts.map
|