or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

collections-utilities.mdconfiguration.mdcore-serialization.mdcustom-serializers.mdindex.mdmemory-management.mdsecurity.mdtype-system.md

security.mddocs/

0

# Security and Class Resolution

1

2

Apache Fury provides comprehensive security features to protect against deserialization attacks and ensure safe handling of untrusted data through class validation and resolution mechanisms.

3

4

## Class Resolution System

5

6

### ClassResolver

7

8

Core class resolution and management system for handling class metadata during serialization.

9

10

```java { .api }

11

public class ClassResolver {

12

// Class registration

13

public void register(Class<?> clazz);

14

public void register(Class<?> clazz, short classId);

15

public void register(Class<?> clazz, boolean createSerializer);

16

17

// Class resolution

18

public ClassInfo getClassInfo(Class<?> clazz);

19

public ClassInfo getClassInfo(short classId);

20

public ClassInfo getClassInfo(String className);

21

22

// Class ID management

23

public short getClassId(Class<?> clazz);

24

public Class<?> getClass(short classId);

25

26

// Security validation

27

public void checkClass(Class<?> clazz);

28

public boolean isRegistered(Class<?> clazz);

29

public boolean isAllowed(Class<?> clazz);

30

31

// Metadata management

32

public void addClassInfo(ClassInfo classInfo);

33

public void setClassChecker(ClassChecker classChecker);

34

}

35

```

36

37

### ClassInfo

38

39

Metadata container for class information used during serialization.

40

41

```java { .api }

42

public class ClassInfo {

43

// Class information

44

public Class<?> getCls();

45

public String getClassName();

46

public short getClassId();

47

48

// Serialization metadata

49

public Serializer<?> getSerializer();

50

public boolean needToWriteRef();

51

public boolean isEnum();

52

public boolean isFinal();

53

54

// Type information

55

public Type getFuryType();

56

public boolean isCollection();

57

public boolean isMap();

58

public boolean isArray();

59

60

// Factory methods

61

public static ClassInfo of(Class<?> clazz);

62

public static ClassInfo of(Class<?> clazz, Serializer<?> serializer);

63

}

64

```

65

66

## Security Framework

67

68

### ClassChecker Interface

69

70

Interface for implementing custom class validation logic.

71

72

```java { .api }

73

public interface ClassChecker {

74

/**

75

* Check if a class is allowed for deserialization.

76

* Throws InsecureException if class is not allowed.

77

*/

78

void checkClass(ClassResolver classResolver, String className);

79

80

/**

81

* Check if a class is allowed for deserialization.

82

*/

83

default boolean isAllowed(String className) {

84

try {

85

checkClass(null, className);

86

return true;

87

} catch (InsecureException e) {

88

return false;

89

}

90

}

91

}

92

```

93

94

### AllowListChecker

95

96

Allow-list based class checker for restricting deserialization to approved classes.

97

98

```java { .api }

99

public class AllowListChecker implements ClassChecker {

100

// Constructors

101

public AllowListChecker(Set<String> allowedClasses);

102

public AllowListChecker(Set<String> allowedClasses, Set<String> allowedPackages);

103

104

// Allow-list management

105

public void addAllowedClass(String className);

106

public void addAllowedClass(Class<?> clazz);

107

public void addAllowedPackage(String packageName);

108

public void removeAllowedClass(String className);

109

public void removeAllowedPackage(String packageName);

110

111

// Validation

112

@Override

113

public void checkClass(ClassResolver classResolver, String className);

114

public boolean isClassAllowed(String className);

115

public boolean isPackageAllowed(String packageName);

116

117

// Utilities

118

public Set<String> getAllowedClasses();

119

public Set<String> getAllowedPackages();

120

}

121

```

122

123

### DisallowedList

124

125

Utility for managing commonly dangerous classes that should be blocked.

126

127

```java { .api }

128

public class DisallowedList {

129

// Dangerous class patterns

130

public static final Set<String> DANGEROUS_CLASSES;

131

public static final Set<String> DANGEROUS_PACKAGES;

132

133

// Utility methods

134

public static boolean isDangerous(String className);

135

public static boolean isDangerousPackage(String packageName);

136

public static ClassChecker createSecureChecker();

137

public static ClassChecker createSecureChecker(Set<String> additionalAllowed);

138

}

139

```

140

141

## Security Configuration

142

143

### Secure Fury Builder

144

145

```java { .api }

146

public class SecureFuryBuilder {

147

// Create secure Fury instance with class registration required

148

public static Fury createSecureFury();

149

public static Fury createSecureFury(Set<String> allowedClasses);

150

public static ThreadSafeFury createSecureThreadSafeFury();

151

152

// Security-focused configuration

153

public static FuryBuilder secureBuilder();

154

public static FuryBuilder secureBuilder(ClassChecker classChecker);

155

}

156

```

157

158

## Exception Handling

159

160

### Security Exceptions

161

162

```java { .api }

163

public class InsecureException extends FuryException {

164

public InsecureException(String message);

165

public InsecureException(String message, Throwable cause);

166

167

// Factory methods for common scenarios

168

public static InsecureException classNotAllowed(String className);

169

public static InsecureException registrationRequired(String className);

170

public static InsecureException dangerousClass(String className);

171

}

172

173

public class ClassNotCompatibleException extends FuryException {

174

public ClassNotCompatibleException(String message);

175

public ClassNotCompatibleException(String message, Throwable cause);

176

177

// Compatibility validation

178

public static ClassNotCompatibleException schemaIncompatible(Class<?> clazz);

179

public static ClassNotCompatibleException versionMismatch(Class<?> clazz);

180

}

181

```

182

183

## Usage Examples

184

185

### Basic Security Configuration

186

187

```java

188

import org.apache.fury.Fury;

189

import org.apache.fury.config.FuryBuilder;

190

import org.apache.fury.resolver.AllowListChecker;

191

192

// Enable class registration requirement (recommended for production)

193

Fury secureFury = Fury.builder()

194

.requireClassRegistration(true) // Security: only registered classes allowed

195

.build();

196

197

// Register only trusted classes

198

secureFury.register(User.class);

199

secureFury.register(Order.class);

200

secureFury.register(String.class);

201

secureFury.register(Integer.class);

202

203

// Deserialization will fail for unregistered classes

204

try {

205

byte[] maliciousData = createMaliciousPayload();

206

Object result = secureFury.deserialize(maliciousData); // Throws InsecureException

207

} catch (InsecureException e) {

208

// Handle security violation

209

logger.warn("Attempted deserialization of unregistered class: " + e.getMessage());

210

}

211

```

212

213

### Allow-List Based Security

214

215

```java

216

import org.apache.fury.resolver.AllowListChecker;

217

import java.util.Set;

218

219

// Create allow-list of safe classes

220

Set<String> safeClasses = Set.of(

221

"com.myapp.User",

222

"com.myapp.Order",

223

"com.myapp.Product",

224

"java.lang.String",

225

"java.lang.Integer",

226

"java.lang.Long",

227

"java.util.ArrayList",

228

"java.util.HashMap"

229

);

230

231

// Create allow-list checker

232

AllowListChecker allowListChecker = new AllowListChecker(safeClasses);

233

234

// Configure Fury with allow-list

235

ClassResolver classResolver = new ClassResolver();

236

classResolver.setClassChecker(allowListChecker);

237

238

Fury fury = Fury.builder()

239

.requireClassRegistration(false) // Can be disabled with allow-list

240

.build();

241

242

// Set the class checker (internal API)

243

// Note: This requires access to Fury internals

244

```

245

246

### Package-Based Allow-List

247

248

```java

249

// Allow entire packages

250

Set<String> allowedClasses = Set.of("java.lang.String", "java.lang.Integer");

251

Set<String> allowedPackages = Set.of("com.myapp.model", "java.util");

252

253

AllowListChecker packageBasedChecker = new AllowListChecker(allowedClasses, allowedPackages);

254

255

// All classes in com.myapp.model.* and java.util.* are allowed

256

// Plus specifically allowed individual classes

257

```

258

259

### Custom Class Checker

260

261

```java

262

import org.apache.fury.resolver.ClassChecker;

263

import org.apache.fury.exception.InsecureException;

264

265

public class CustomSecurityChecker implements ClassChecker {

266

private final Set<String> trustedPackages;

267

private final Set<String> blockedClasses;

268

269

public CustomSecurityChecker() {

270

this.trustedPackages = Set.of("com.myapp", "java.lang", "java.util");

271

this.blockedClasses = Set.of(

272

"java.lang.Runtime",

273

"java.lang.Process",

274

"java.io.FileInputStream",

275

"java.io.FileOutputStream"

276

);

277

}

278

279

@Override

280

public void checkClass(ClassResolver classResolver, String className) {

281

// Block dangerous classes

282

if (blockedClasses.contains(className)) {

283

throw InsecureException.dangerousClass(className);

284

}

285

286

// Check if class is in trusted package

287

boolean inTrustedPackage = trustedPackages.stream()

288

.anyMatch(pkg -> className.startsWith(pkg + "."));

289

290

if (!inTrustedPackage) {

291

throw InsecureException.classNotAllowed(className);

292

}

293

294

// Additional custom validation logic

295

if (className.contains("$Proxy")) {

296

throw InsecureException.classNotAllowed("Dynamic proxies not allowed: " + className);

297

}

298

}

299

}

300

301

// Use custom checker

302

CustomSecurityChecker customChecker = new CustomSecurityChecker();

303

// Apply to Fury instance...

304

```

305

306

### Production Security Setup

307

308

```java

309

public class ProductionSecurityConfig {

310

311

public static Fury createProductionFury() {

312

// Create secure allow-list

313

Set<String> productionAllowList = createProductionAllowList();

314

AllowListChecker checker = new AllowListChecker(productionAllowList);

315

316

return Fury.builder()

317

.requireClassRegistration(true) // Mandatory registration

318

.suppressClassRegistrationWarnings(false) // Show security warnings

319

.withLanguage(Language.JAVA) // Java-only for security

320

.build();

321

}

322

323

private static Set<String> createProductionAllowList() {

324

Set<String> allowList = new HashSet<>();

325

326

// Application model classes

327

allowList.addAll(Set.of(

328

"com.myapp.model.User",

329

"com.myapp.model.Order",

330

"com.myapp.model.Product",

331

"com.myapp.dto.UserDTO",

332

"com.myapp.dto.OrderDTO"

333

));

334

335

// Java standard library safe classes

336

allowList.addAll(Set.of(

337

"java.lang.String",

338

"java.lang.Integer", "java.lang.Long", "java.lang.Double",

339

"java.lang.Boolean", "java.lang.Byte", "java.lang.Short",

340

"java.lang.Float", "java.lang.Character",

341

"java.math.BigDecimal", "java.math.BigInteger",

342

"java.time.LocalDate", "java.time.LocalDateTime", "java.time.Instant"

343

));

344

345

// Safe collection classes

346

allowList.addAll(Set.of(

347

"java.util.ArrayList", "java.util.LinkedList",

348

"java.util.HashMap", "java.util.LinkedHashMap", "java.util.TreeMap",

349

"java.util.HashSet", "java.util.LinkedHashSet", "java.util.TreeSet"

350

));

351

352

return allowList;

353

}

354

355

public static void registerProductionClasses(Fury fury) {

356

// Register all allowed classes explicitly

357

Set<String> allowList = createProductionAllowList();

358

359

for (String className : allowList) {

360

try {

361

Class<?> clazz = Class.forName(className);

362

fury.register(clazz);

363

} catch (ClassNotFoundException e) {

364

// Log warning but continue

365

logger.warn("Could not register class: " + className, e);

366

}

367

}

368

}

369

}

370

```

371

372

### Secure Deserialization Pattern

373

374

```java

375

public class SecureDeserializer {

376

private final Fury secureFury;

377

private final ClassChecker classChecker;

378

379

public SecureDeserializer(Set<String> allowedClasses) {

380

this.classChecker = new AllowListChecker(allowedClasses);

381

this.secureFury = Fury.builder()

382

.requireClassRegistration(true)

383

.build();

384

385

// Register allowed classes

386

for (String className : allowedClasses) {

387

try {

388

secureFury.register(Class.forName(className));

389

} catch (ClassNotFoundException e) {

390

throw new IllegalArgumentException("Cannot register class: " + className, e);

391

}

392

}

393

}

394

395

public <T> T deserializeSecurely(byte[] data, Class<T> expectedType) {

396

try {

397

Object result = secureFury.deserialize(data);

398

399

// Additional type validation

400

if (!expectedType.isInstance(result)) {

401

throw InsecureException.classNotAllowed(

402

"Unexpected type: expected " + expectedType.getName() +

403

", got " + result.getClass().getName());

404

}

405

406

return expectedType.cast(result);

407

} catch (InsecureException e) {

408

// Log security violation

409

logger.error("Security violation during deserialization", e);

410

throw e;

411

} catch (Exception e) {

412

// Log and wrap other exceptions

413

logger.error("Deserialization failed", e);

414

throw new FuryException("Secure deserialization failed", e);

415

}

416

}

417

}

418

```

419

420

### Environment-Based Security

421

422

```java

423

public class EnvironmentSecurityConfig {

424

425

public static Fury createFuryForEnvironment() {

426

String environment = System.getProperty("app.environment", "development");

427

428

switch (environment.toLowerCase()) {

429

case "production":

430

return createProductionFury();

431

case "staging":

432

return createStagingFury();

433

case "development":

434

return createDevelopmentFury();

435

default:

436

throw new IllegalArgumentException("Unknown environment: " + environment);

437

}

438

}

439

440

private static Fury createProductionFury() {

441

return Fury.builder()

442

.requireClassRegistration(true)

443

.suppressClassRegistrationWarnings(false)

444

.withLanguage(Language.JAVA)

445

.build();

446

}

447

448

private static Fury createStagingFury() {

449

return Fury.builder()

450

.requireClassRegistration(true)

451

.suppressClassRegistrationWarnings(true) // Less noise in staging

452

.withLanguage(Language.JAVA)

453

.build();

454

}

455

456

private static Fury createDevelopmentFury() {

457

return Fury.builder()

458

.requireClassRegistration(false) // More flexible for development

459

.suppressClassRegistrationWarnings(true)

460

.withLanguage(Language.JAVA)

461

.build();

462

}

463

}

464

```

465

466

## Security Best Practices

467

468

### Mandatory Security Measures

469

470

1. **Always Enable Class Registration in Production**:

471

```java

472

.requireClassRegistration(true)

473

```

474

475

2. **Use Allow-List Validation**:

476

```java

477

AllowListChecker checker = new AllowListChecker(trustedClasses);

478

```

479

480

3. **Validate Input Sources**:

481

```java

482

// Only deserialize from trusted sources

483

if (!isTrustedSource(dataSource)) {

484

throw new SecurityException("Untrusted data source");

485

}

486

```

487

488

4. **Register Minimal Class Set**:

489

```java

490

// Only register classes that are actually needed

491

fury.register(RequiredClass.class);

492

```

493

494

### Defense in Depth

495

496

1. **Network Security**: Use TLS/HTTPS for data transmission

497

2. **Input Validation**: Validate data before deserialization

498

3. **Monitoring**: Log deserialization attempts and failures

499

4. **Sandboxing**: Run deserialization in restricted environments

500

5. **Regular Updates**: Keep Fury library updated with security patches

501

502

### Common Security Pitfalls

503

504

1. **Disabling Class Registration**: Never disable in production

505

2. **Over-broad Allow-Lists**: Be specific about allowed classes

506

3. **Ignoring Security Warnings**: Address all security-related warnings

507

4. **Deserializing Untrusted Data**: Always validate data sources

508

5. **Missing Exception Handling**: Properly handle security exceptions

509

510

### Monitoring and Alerting

511

512

```java

513

public class SecurityMonitor {

514

private final Logger securityLogger = LoggerFactory.getLogger("SECURITY");

515

516

public void logSecurityViolation(String event, String details) {

517

securityLogger.error("SECURITY_VIOLATION: {} - {}", event, details);

518

519

// Send alert to security team

520

alertSecurityTeam(event, details);

521

}

522

523

public void logSuccessfulDeserialization(String className, String source) {

524

securityLogger.info("DESERIALIZATION_SUCCESS: {} from {}", className, source);

525

}

526

}

527

```