Skip to content

Commit 98b00f0

Browse files
antonisclaude
andauthored
test(ios): Add unit tests for RNSentryIsPathUnderAllowedRoots (#6068)
Exposes the static path-validator via a thin class-method wrapper (+isPathUnderAllowedRootsForTesting:) declared in RNSentry+Test.h, following the existing +captureReplayWithReturnValue pattern. Adds RNSentryUriValidationTests.m with 9 cases: empty path, dot-dot traversal, paths under tmp/caches/docs (allowed), paths under Library and Library/Application Support (blocked), absolute path outside sandbox, and a symlink-inside-tmp→/etc/passwd (blocked). Closes #6062. Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
1 parent 5682481 commit 98b00f0

4 files changed

Lines changed: 112 additions & 0 deletions

File tree

packages/core/RNSentryCocoaTester/RNSentryCocoaTester.xcodeproj/project.pbxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
/* Begin PBXBuildFile section */
1010
332D33472CDBDBB600547D76 /* RNSentryReplayOptionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 332D33462CDBDBB600547D76 /* RNSentryReplayOptionsTests.swift */; };
1111
3339C4812D6625570088EB3A /* RNSentryUserTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 3339C4802D6625570088EB3A /* RNSentryUserTests.m */; };
12+
B4DEB41739F14AA38202D4D4 /* RNSentryUriValidationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 3E3742693F7643C2ADE1BDF2 /* RNSentryUriValidationTests.m */; };
1213
336084392C32E382008CC412 /* RNSentryReplayBreadcrumbConverterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 336084382C32E382008CC412 /* RNSentryReplayBreadcrumbConverterTests.swift */; };
1314
3380C6C42CE25ECA0018B9B6 /* RNSentryReplayPostInitTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3380C6C32CE25ECA0018B9B6 /* RNSentryReplayPostInitTests.swift */; };
1415
33AFDFED2B8D14B300AAB120 /* RNSentryFramesTrackerListenerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 33AFDFEC2B8D14B300AAB120 /* RNSentryFramesTrackerListenerTests.m */; };
@@ -30,6 +31,7 @@
3031
332D334A2CDCC8EB00547D76 /* RNSentryCocoaTesterTests-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "RNSentryCocoaTesterTests-Bridging-Header.h"; sourceTree = "<group>"; };
3132
3339C47F2D6625260088EB3A /* RNSentry+Test.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "RNSentry+Test.h"; sourceTree = "<group>"; };
3233
3339C4802D6625570088EB3A /* RNSentryUserTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNSentryUserTests.m; sourceTree = "<group>"; };
34+
3E3742693F7643C2ADE1BDF2 /* RNSentryUriValidationTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNSentryUriValidationTests.m; sourceTree = "<group>"; };
3335
336084382C32E382008CC412 /* RNSentryReplayBreadcrumbConverterTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RNSentryReplayBreadcrumbConverterTests.swift; sourceTree = "<group>"; };
3436
3360843A2C32E3A8008CC412 /* RNSentryReplayBreadcrumbConverter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RNSentryReplayBreadcrumbConverter.h; path = ../ios/RNSentryReplayBreadcrumbConverter.h; sourceTree = "<group>"; };
3537
3360843C2C340C76008CC412 /* RNSentryBreadcrumbTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RNSentryBreadcrumbTests.swift; sourceTree = "<group>"; };
@@ -108,6 +110,7 @@
108110
336084382C32E382008CC412 /* RNSentryReplayBreadcrumbConverterTests.swift */,
109111
33F58ACF2977037D008F60EA /* RNSentryTests.m */,
110112
3339C4802D6625570088EB3A /* RNSentryUserTests.m */,
113+
3E3742693F7643C2ADE1BDF2 /* RNSentryUriValidationTests.m */,
111114
33AFDFEC2B8D14B300AAB120 /* RNSentryFramesTrackerListenerTests.m */,
112115
33AFDFF02B8D15E500AAB120 /* RNSentryDependencyContainerTests.m */,
113116
3360843C2C340C76008CC412 /* RNSentryBreadcrumbTests.swift */,
@@ -266,6 +269,7 @@
266269
33DEDFED2D8DC825006066E4 /* RNSentryOnDrawReporter+Test.mm in Sources */,
267270
33F58AD02977037D008F60EA /* RNSentryTests.m in Sources */,
268271
3339C4812D6625570088EB3A /* RNSentryUserTests.m in Sources */,
272+
B4DEB41739F14AA38202D4D4 /* RNSentryUriValidationTests.m in Sources */,
269273
33DEDFF02D9185EB006066E4 /* RNSentryTimeToDisplayTests.swift in Sources */,
270274
3380C6C42CE25ECA0018B9B6 /* RNSentryReplayPostInitTests.swift in Sources */,
271275
33AFDFED2B8D14B300AAB120 /* RNSentryFramesTrackerListenerTests.m in Sources */,

packages/core/RNSentryCocoaTester/RNSentryCocoaTesterTests/RNSentry+Test.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,8 @@
77

88
+ (BOOL)captureReplayWithReturnValue;
99

10+
#if TARGET_OS_IPHONE || TARGET_OS_MACCATALYST
11+
+ (BOOL)isPathUnderAllowedRootsForTesting:(NSString *)path;
12+
#endif
13+
1014
@end
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
#import "RNSentry+Test.h"
2+
#import <XCTest/XCTest.h>
3+
4+
#if TARGET_OS_IPHONE || TARGET_OS_MACCATALYST
5+
6+
@interface RNSentryUriValidationTests : XCTestCase
7+
8+
@property (nonatomic, strong) NSURL *symlinkURL;
9+
10+
@end
11+
12+
@implementation RNSentryUriValidationTests
13+
14+
- (void)tearDown
15+
{
16+
if (self.symlinkURL) {
17+
[[NSFileManager defaultManager] removeItemAtURL:self.symlinkURL error:nil];
18+
self.symlinkURL = nil;
19+
}
20+
[super tearDown];
21+
}
22+
23+
- (void)testEmptyPathReturnsFalse
24+
{
25+
XCTAssertFalse([RNSentry isPathUnderAllowedRootsForTesting:@""]);
26+
}
27+
28+
- (void)testPathWithDotDotComponentReturnsFalse
29+
{
30+
NSString *path = [NSTemporaryDirectory()
31+
stringByAppendingPathComponent:@"../Library/Cookies/Cookies.binarycookies"];
32+
XCTAssertFalse([RNSentry isPathUnderAllowedRootsForTesting:path]);
33+
}
34+
35+
- (void)testPathUnderTmpReturnsTrue
36+
{
37+
NSString *path = [NSTemporaryDirectory() stringByAppendingPathComponent:@"image.jpg"];
38+
XCTAssertTrue([RNSentry isPathUnderAllowedRootsForTesting:path]);
39+
}
40+
41+
- (void)testPathUnderCachesDirReturnsTrue
42+
{
43+
NSString *cachesDir
44+
= NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).firstObject;
45+
NSString *path = [cachesDir stringByAppendingPathComponent:@"thumbnail.png"];
46+
XCTAssertTrue([RNSentry isPathUnderAllowedRootsForTesting:path]);
47+
}
48+
49+
- (void)testPathUnderDocumentsDirReturnsTrue
50+
{
51+
NSString *docsDir
52+
= NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)
53+
.firstObject;
54+
NSString *path = [docsDir stringByAppendingPathComponent:@"attachment.jpg"];
55+
XCTAssertTrue([RNSentry isPathUnderAllowedRootsForTesting:path]);
56+
}
57+
58+
- (void)testPathUnderLibraryReturnsFalse
59+
{
60+
NSString *libraryDir
61+
= NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES)
62+
.firstObject;
63+
NSString *path = [libraryDir stringByAppendingPathComponent:@"Cookies/Cookies.binarycookies"];
64+
XCTAssertFalse([RNSentry isPathUnderAllowedRootsForTesting:path]);
65+
}
66+
67+
- (void)testAbsolutePathOutsideSandboxReturnsFalse
68+
{
69+
XCTAssertFalse([RNSentry isPathUnderAllowedRootsForTesting:@"/etc/passwd"]);
70+
}
71+
72+
- (void)testPathUnderLibraryApplicationSupportReturnsFalse
73+
{
74+
NSString *libraryDir
75+
= NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES)
76+
.firstObject;
77+
NSString *path = [libraryDir stringByAppendingPathComponent:@"Application Support/app.sqlite"];
78+
XCTAssertFalse([RNSentry isPathUnderAllowedRootsForTesting:path]);
79+
}
80+
81+
- (void)testSymlinkInTmpPointingOutsideSandboxReturnsFalse
82+
{
83+
NSString *symlinkPath =
84+
[NSTemporaryDirectory() stringByAppendingPathComponent:@"sentry_test_symlink_passwd"];
85+
self.symlinkURL = [NSURL fileURLWithPath:symlinkPath];
86+
87+
NSError *error = nil;
88+
[[NSFileManager defaultManager] removeItemAtPath:symlinkPath error:nil];
89+
BOOL created = [[NSFileManager defaultManager] createSymbolicLinkAtPath:symlinkPath
90+
withDestinationPath:@"/etc/passwd"
91+
error:&error];
92+
XCTAssertTrue(created, @"Symlink creation failed: %@", error);
93+
94+
XCTAssertFalse([RNSentry isPathUnderAllowedRootsForTesting:symlinkPath]);
95+
}
96+
97+
@end
98+
99+
#endif

packages/core/ios/RNSentry.mm

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -901,6 +901,11 @@ + (BOOL)captureReplayWithReturnValue
901901
}
902902
return NO;
903903
}
904+
905+
+ (BOOL)isPathUnderAllowedRootsForTesting:(NSString *)path
906+
{
907+
return RNSentryIsPathUnderAllowedRoots(path);
908+
}
904909
#endif
905910

906911
RCT_EXPORT_METHOD(getDataFromUri : (NSString *_Nonnull)uri resolve : (

0 commit comments

Comments
 (0)