@umutcansu/react-native-pinvault 2.6.0 → 2.7.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/CHANGELOG.md +28 -0
- package/README.md +7 -6
- package/RNPinVault.podspec +1 -1
- package/android/build.gradle +1 -1
- package/android/src/main/java/io/github/umutcansu/pinvault/reactnative/ConfigParser.kt +8 -1
- package/android/src/main/java/io/github/umutcansu/pinvault/reactnative/NativeSecurity.kt +3 -1
- package/ios/Core/ConfigParser.swift +8 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,33 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 2.7.0 — 2026-10-15
|
|
4
|
+
|
|
5
|
+
### Changed
|
|
6
|
+
|
|
7
|
+
- **Release builds take `tokenHosts` only from the native security file**,
|
|
8
|
+
as they already did `clientCertHosts`: where the file has the block but
|
|
9
|
+
names no `tokenHosts`, a `tokenHosts` from JS is refused
|
|
10
|
+
(`E_INVALID_CONFIG`, "declare tokenHosts for Config API … there"). The
|
|
11
|
+
library's default sends `PinVault-Token` to the block's own Config API only,
|
|
12
|
+
so a `tokenHosts` from JS would add hosts that receive the device's token.
|
|
13
|
+
Debug builds and files that name the hosts are unchanged. Move your
|
|
14
|
+
`tokenHosts` into `pinvault-security.json` (Android: `res/raw`, iOS: the
|
|
15
|
+
bundle) if a release build now refuses to start.
|
|
16
|
+
|
|
17
|
+
## 2.6.1 — 2026-10-15
|
|
18
|
+
|
|
19
|
+
### Fixed
|
|
20
|
+
|
|
21
|
+
- **iOS: without `tokenHosts`, only the block's own Config API carries
|
|
22
|
+
`PinVault-Token`** (as Android has since 2.4.1). A block without
|
|
23
|
+
`tokenHosts` sent the token (and `PinVault-Proof`) to every host pinned by
|
|
24
|
+
its live config, so a pinned CDN or analytics host received it. Name your
|
|
25
|
+
API hosts in `tokenHosts` if they need the token.
|
|
26
|
+
|
|
27
|
+
### Changed
|
|
28
|
+
|
|
29
|
+
- Depends on PinVault 2.6.1 (Maven Central, Swift package tag `v2.6.1`).
|
|
30
|
+
|
|
3
31
|
## 2.6.0 — 2026-10-14
|
|
4
32
|
|
|
5
33
|
### Fixed
|
package/README.md
CHANGED
|
@@ -29,9 +29,9 @@ npm install @umutcansu/react-native-pinvault
|
|
|
29
29
|
cd ios && pod install
|
|
30
30
|
```
|
|
31
31
|
|
|
32
|
-
The native libraries come with it, at the package's own version: npm 2.
|
|
33
|
-
uses `io.github.umutcansu:pinvault:2.
|
|
34
|
-
package at tag `v2.
|
|
32
|
+
The native libraries come with it, at the package's own version: npm 2.7.0
|
|
33
|
+
uses `io.github.umutcansu:pinvault:2.7.0` from Maven Central and the Swift
|
|
34
|
+
package at tag `v2.7.0`. The New Architecture must stay on (React Native's
|
|
35
35
|
default since 0.76).
|
|
36
36
|
|
|
37
37
|
**iOS.** The pod depends on the PinVault Swift package through React Native's
|
|
@@ -273,9 +273,10 @@ parsed as strictly; a broken file rejects `start` with `E_INVALID_CONFIG`
|
|
|
273
273
|
- a block's `url`, `enrollmentUrl`, `renewalUrl`, `tokenHosts` and
|
|
274
274
|
`clientCertHosts` are fixed where the file gives them (where the block talks to, and who gets its token and identity),
|
|
275
275
|
and `attestation: true` / `proofOfPossession: true` there cannot be turned off from JS;
|
|
276
|
-
in a release build JS may give `clientCertHosts` only where
|
|
277
|
-
them (the bundle cannot hand the device's identity
|
|
278
|
-
`
|
|
276
|
+
in a release build JS may give `clientCertHosts` and `tokenHosts` only where
|
|
277
|
+
the file names them (the bundle cannot hand the device's identity or its
|
|
278
|
+
`PinVault-Token` to another host; the library's default sends the token to the
|
|
279
|
+
block's own Config API only);
|
|
279
280
|
- `require` only tightens: a protection it turns on stays on whatever JS says,
|
|
280
281
|
its `requireCaTrust` hosts are added to JS's, the expected signer / bundle /
|
|
281
282
|
team ids and iOS `userAuthStrength` are fixed, and `expiredConfigGraceSeconds`
|
package/RNPinVault.podspec
CHANGED
|
@@ -4,7 +4,7 @@ package = JSON.parse(File.read(File.join(__dir__, "package.json")))
|
|
|
4
4
|
|
|
5
5
|
# PinVault for iOS is a Swift package (Package.swift at the repository root,
|
|
6
6
|
# product "PinVault"). React Native's spm_dependency adds it to the Pods project:
|
|
7
|
-
# - consumers: the git URL at the tag of this package's version (v2.
|
|
7
|
+
# - consumers: the git URL at the tag of this package's version (v2.7.0);
|
|
8
8
|
# - development: PINVAULT_IOS_PACKAGE_PATH = a PinVault checkout (the sample's
|
|
9
9
|
# Podfile sets it to this repository), the counterpart of pinvault.localPath.
|
|
10
10
|
pinvault_url = "https://github.com/umutcansu/PinVault.git"
|
package/android/build.gradle
CHANGED
|
@@ -286,11 +286,18 @@ internal object ConfigParser {
|
|
|
286
286
|
throw BridgeInputException("${b.path}.proofOfPossession: the app's native security file turns it on; JS cannot turn it off")
|
|
287
287
|
}
|
|
288
288
|
val proof = jsProof == true || nativeBlock?.proofOfPossession == true
|
|
289
|
+
// Who gets the device's token is the file's call in a release build, like the identity
|
|
290
|
+
// below: the library's default is the block's own Config API only, so a tokenHosts from
|
|
291
|
+
// JS would ADD hosts that receive the token.
|
|
292
|
+
if (release && nativeBlock != null && nativeBlock.tokenHosts == null && jsTokenHosts != null) {
|
|
293
|
+
throw BridgeInputException("${b.path}.tokenHosts: a release build takes it only from the app's native security file " +
|
|
294
|
+
"(${native?.source}); declare tokenHosts for Config API '$id' there")
|
|
295
|
+
}
|
|
289
296
|
val tokenHosts = nativeBlock?.tokenHosts?.also { n ->
|
|
290
297
|
if (jsTokenHosts != null && !NativeSecurity.sameKeys(jsTokenHosts.map(String::lowercase), n.map(String::lowercase))) fixed("tokenHosts")
|
|
291
298
|
} ?: jsTokenHosts
|
|
292
299
|
// Who gets the device's identity is the file's call in a release build: JS cannot
|
|
293
|
-
// add a host the file does not name
|
|
300
|
+
// add a host the file does not name.
|
|
294
301
|
if (release && nativeBlock != null && nativeBlock.clientCertHosts == null && clientCertHosts != null) {
|
|
295
302
|
throw BridgeInputException("${b.path}.clientCertHosts: a release build takes it only from the app's native security file " +
|
|
296
303
|
"(${native?.source}); declare clientCertHosts for Config API '$id' there")
|
|
@@ -50,7 +50,9 @@ import java.io.IOException
|
|
|
50
50
|
* JS are refused unless the file allows them for that block;
|
|
51
51
|
* - `url`, `tokenHosts` and `clientCertHosts` of a block are fixed where the
|
|
52
52
|
* file gives them, and `attestation: true` / `proofOfPossession: true` there
|
|
53
|
-
* cannot be switched off;
|
|
53
|
+
* cannot be switched off; in a release build JS may give `tokenHosts` and
|
|
54
|
+
* `clientCertHosts` only where the file names them (who gets the device's
|
|
55
|
+
* token and identity is the file's call);
|
|
54
56
|
* - `require` only tightens: a protection it turns on stays on whatever JS
|
|
55
57
|
* says, `requireCaTrust` hosts are added to JS's, `expectedSignerSha256` is
|
|
56
58
|
* fixed, and `expiredConfigGraceSeconds` is the most JS may ask for;
|
|
@@ -295,6 +295,13 @@ public enum ConfigParser {
|
|
|
295
295
|
}
|
|
296
296
|
let proof = jsProof == true || nativeBlock?.proofOfPossession == true
|
|
297
297
|
let lower: ([String]) -> [String] = { $0.map { $0.lowercased() } }
|
|
298
|
+
// Who gets the device's token is the file's call in a release build, like the identity
|
|
299
|
+
// below: the library's default is the block's own Config API only, so a tokenHosts from
|
|
300
|
+
// JS would ADD hosts that receive the token.
|
|
301
|
+
if release, let nativeBlock, nativeBlock.tokenHosts == nil, jsTokenHosts != nil {
|
|
302
|
+
throw BridgeInputError("\(b.path).tokenHosts: a release build takes it only from the app's native security file "
|
|
303
|
+
+ "(\(native?.source ?? "")); declare tokenHosts for Config API '\(id)' there")
|
|
304
|
+
}
|
|
298
305
|
var tokenHosts = jsTokenHosts
|
|
299
306
|
if let n = nativeBlock?.tokenHosts {
|
|
300
307
|
if let j = jsTokenHosts, !NativeSecurity.sameKeys(lower(j), lower(n)) { throw fixed("tokenHosts") }
|
|
@@ -311,7 +318,7 @@ public enum ConfigParser {
|
|
|
311
318
|
fixedRenewalUrl = n
|
|
312
319
|
}
|
|
313
320
|
// Who gets the device's identity is the file's call in a release build: JS cannot
|
|
314
|
-
// add a host the file does not name
|
|
321
|
+
// add a host the file does not name.
|
|
315
322
|
if release, let nativeBlock, nativeBlock.clientCertHosts == nil, clientCertHosts != nil {
|
|
316
323
|
throw BridgeInputError("\(b.path).clientCertHosts: a release build takes it only from the app's native security file "
|
|
317
324
|
+ "(\(native?.source ?? "")); declare clientCertHosts for Config API '\(id)' there")
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umutcansu/react-native-pinvault",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.7.0",
|
|
4
4
|
"description": "PinVault for React Native: dynamic certificate pinning with signed remote configs, mTLS enrollment and signed vault files, as a thin bridge over the native PinVault libraries",
|
|
5
5
|
"main": "./lib/module/index.js",
|
|
6
6
|
"types": "./lib/typescript/src/index.d.ts",
|