Security
Security
Reporting a vulnerability
Email support@eonix.lk with "DevKit security" in the subject. Please include what you did, what happened, and the version from Settings → About.
We aim to acknowledge within 2 business days and to ship a fix or a mitigation within 30 days for anything that puts user data at risk. There is no bug bounty. If you would like credit in the release notes, say so and we will include it.
Please do not open a public issue for a security problem before we have had a chance to respond.
What DevKit's security model actually is
DevKit's attack surface is unusually small, and most of that is by construction rather than by policy:
- No network. DevKit makes no network requests. On macOS it does not request
com.apple.security.network.client, so the sandbox would refuse one. You can verify this by using the app with the device in Airplane Mode: everything works. - No account, no server, no secrets. There is nothing to sign in to, no API key to store and no credential in the app. It therefore ships no Keychain code and no keychain entitlement.
- No third-party code. Zero dependencies.
Package.resolvedhas no pins, and CI fails if one ever appears. - No analytics, no tracking, no crash SDK.
NSPrivacyTrackingis false and the collected-data list is empty.
What is stored, and where
| Data | Location | Leaves the device? |
|---|---|---|
| History (tool, time, truncated previews) | SwiftData, on device | Only to the user's own private CloudKit database, and only if they are Pro and turn sync on |
| Favourites | Same | Same |
| Drafts (unsent input) | SwiftData, local configuration | Never, deliberately: a half-typed private key should not sync because iCloud is on |
| Preferences | App-group UserDefaults | No |
| Shared items from the extension | A directory of JSON files in the app group | No |
History previews can be turned off in Settings, after which a run stores only the tool, the time and a SHA-256 of the input. "Erase all data" removes everything, including the CloudKit records.
The parts that handle hostile input
Everything a user pastes is untrusted. The parsers are written accordingly:
- Bounded. A 5 MB ceiling on tool input, checked before any allocation. Recursive parsers stop at 100 levels (JSON) and 32 levels (DER), because tools run on an actor whose stack is smaller than the main thread's.
- Total. Every failure is a typed
ToolErrorwith a message and a recovery suggestion. There are no force unwraps and notry!in shipped code, and CI fails if one appears. - Time-bounded where the algorithm is not. The regex tester abandons a run after two seconds and says the pattern is probably backtracking, rather than wedging a thread.
- Fuzzed by contract. Every one of the 42 tools is run against empty input, control characters, emoji, 100 KB of one character, deeply nested structures, path-traversal strings, script tags, SQL injection strings and 5,000 combining marks, plus every other tool's sample input. Anything but a
ToolErrorfails the build.
The web view
DevKit contains exactly one WKWebView, in the HTML preview, with four independent defences:
- JavaScript disabled through
defaultWebpagePreferences.allowsContentJavaScript. - Content loaded with
loadHTMLString(_:baseURL: nil), so relative URLs resolve to nothing. - A
WKContentRuleListthat blocks every resource load ("url-filter": ".*"→block). The preview refuses to render until the rule list has compiled, so there is no window in which HTML could load without it. - A navigation delegate that cancels every navigation after the initial load.
The data store is non-persistent, so nothing the preview touches survives the screen.
Extensions
The share extension and the widgets are sandboxed, hold only the app-group entitlement, and have no network entitlement. The share extension never calls extensionContext.open and never reaches for UIApplication: it does its work in its own process and leaves results in the app group.
Supported versions
| Version | Supported |
|---|---|
| 1.0.x | Yes |
Security fixes ship in the current release. There is no long-term support branch.