or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

caching.mdconfiguration.mdcore-fetch.mdindex.mdnetwork.mdretry.mdsecurity.md

security.mddocs/

0

# Security and Integrity

1

2

Security features including SSL configuration, certificate validation, and subresource integrity verification for secure HTTP communications.

3

4

## Capabilities

5

6

### SSL/TLS Configuration

7

8

Configure SSL certificate validation and client certificate authentication:

9

10

```javascript { .api }

11

/**

12

* SSL/TLS configuration options

13

*/

14

interface SSLOptions {

15

strictSSL?: boolean; // Enable/disable SSL certificate validation (default: true)

16

ca?: string | Buffer | string[] | Buffer[]; // Certificate authority certificates

17

cert?: string | Buffer; // Client certificate

18

key?: string | Buffer; // Client private key

19

rejectUnauthorized?: boolean; // Alias for strictSSL (internal use)

20

}

21

```

22

23

**Usage Examples:**

24

25

```javascript

26

const fs = require('fs');

27

const fetch = require('make-fetch-happen');

28

29

// Disable SSL verification (not recommended for production)

30

const response1 = await fetch('https://self-signed.example.com/api', {

31

strictSSL: false

32

});

33

34

// Custom CA certificate

35

const response2 = await fetch('https://internal-api.company.com/data', {

36

ca: fs.readFileSync('./company-ca.pem')

37

});

38

39

// Client certificate authentication

40

const response3 = await fetch('https://secure-api.example.com/data', {

41

cert: fs.readFileSync('./client-cert.pem'),

42

key: fs.readFileSync('./client-key.pem'),

43

ca: fs.readFileSync('./ca-cert.pem')

44

});

45

46

// Multiple CA certificates

47

const response4 = await fetch('https://api.example.com/data', {

48

ca: [

49

fs.readFileSync('./ca1.pem'),

50

fs.readFileSync('./ca2.pem'),

51

fs.readFileSync('./ca3.pem')

52

]

53

});

54

```

55

56

### Environment-Based SSL Configuration

57

58

SSL behavior respects Node.js environment variables:

59

60

```javascript { .api }

61

/**

62

* Environment variable support:

63

* - NODE_TLS_REJECT_UNAUTHORIZED: When set to '0', disables SSL verification

64

* - This affects the default value of strictSSL option

65

*

66

* Priority order:

67

* 1. Explicit strictSSL option in request

68

* 2. NODE_TLS_REJECT_UNAUTHORIZED environment variable

69

* 3. Default (true - SSL verification enabled)

70

*/

71

```

72

73

**Usage Examples:**

74

75

```bash

76

# Disable SSL verification globally (not recommended for production)

77

export NODE_TLS_REJECT_UNAUTHORIZED=0

78

node app.js

79

80

# Or per command

81

NODE_TLS_REJECT_UNAUTHORIZED=0 node app.js

82

```

83

84

```javascript

85

// Environment variable affects default behavior

86

const response = await fetch('https://self-signed.example.com/api');

87

// If NODE_TLS_REJECT_UNAUTHORIZED=0, SSL verification is disabled

88

89

// Explicit override of environment

90

const response2 = await fetch('https://self-signed.example.com/api', {

91

strictSSL: true // Forces SSL verification regardless of environment

92

});

93

```

94

95

### Subresource Integrity (SRI)

96

97

Verify response content integrity using cryptographic hashes:

98

99

```javascript { .api }

100

/**

101

* Subresource Integrity options

102

*/

103

interface IntegrityOptions {

104

integrity?: string; // SRI hash string (sha256-, sha384-, sha512-)

105

algorithms?: string[]; // Allowed hash algorithms for verification

106

size?: number; // Expected content size in bytes

107

}

108

109

/**

110

* Supported SRI hash formats:

111

* - sha256-<base64-hash>

112

* - sha384-<base64-hash>

113

* - sha512-<base64-hash>

114

* - Multiple hashes separated by spaces

115

*/

116

```

117

118

**Usage Examples:**

119

120

```javascript

121

// Verify file integrity with SHA256

122

const response1 = await fetch('https://cdn.example.com/library.js', {

123

integrity: 'sha256-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC'

124

});

125

126

// Multiple hash algorithms (any can match)

127

const response2 = await fetch('https://cdn.example.com/library.js', {

128

integrity: 'sha256-abc123... sha512-def456...'

129

});

130

131

// With size verification

132

const response3 = await fetch('https://cdn.example.com/large-file.zip', {

133

integrity: 'sha256-xyz789...',

134

size: 1024 * 1024 * 50 // Expect 50MB file

135

});

136

137

// Custom algorithms (limits which hashes are accepted)

138

const response4 = await fetch('https://cdn.example.com/file.dat', {

139

integrity: 'sha512-abc123...',

140

algorithms: ['sha512'] // Only accept SHA512 hashes

141

});

142

```

143

144

### Integrity Verification Process

145

146

Understanding how integrity verification works:

147

148

```javascript { .api }

149

/**

150

* Integrity verification process:

151

* 1. Response body is streamed through integrity verification

152

* 2. Hash is calculated as data flows through

153

* 3. Final hash is compared against expected integrity value

154

* 4. If mismatch, request fails with EINTEGRITY error

155

* 5. Verification only occurs on 200 responses

156

*/

157

```

158

159

**Usage Examples:**

160

161

```javascript

162

try {

163

const response = await fetch('https://cdn.example.com/tampered-file.js', {

164

integrity: 'sha256-expected-hash-that-wont-match'

165

});

166

const content = await response.text();

167

} catch (error) {

168

if (error.code === 'EINTEGRITY') {

169

console.log('File integrity verification failed!');

170

console.log('Expected:', error.expected);

171

console.log('Actual:', error.actual);

172

}

173

}

174

175

// Integrity verification with caching

176

const response = await fetch('https://cdn.example.com/library.js', {

177

cachePath: './cache',

178

integrity: 'sha256-abc123...'

179

});

180

// Cached responses are also verified against integrity hash

181

```

182

183

### Certificate Management Patterns

184

185

Common patterns for certificate management:

186

187

```javascript

188

const fs = require('fs');

189

const path = require('path');

190

191

// Certificate loading utility

192

const loadCertificates = (certDir) => {

193

return {

194

ca: fs.readFileSync(path.join(certDir, 'ca.pem')),

195

cert: fs.readFileSync(path.join(certDir, 'client.pem')),

196

key: fs.readFileSync(path.join(certDir, 'client-key.pem'))

197

};

198

};

199

200

// Environment-specific certificate configuration

201

const createSecureFetch = (env) => {

202

const config = {};

203

204

if (env === 'development') {

205

// More permissive for development

206

config.strictSSL = false;

207

} else if (env === 'staging') {

208

// Staging certificates

209

const certs = loadCertificates('./certs/staging');

210

Object.assign(config, certs);

211

} else if (env === 'production') {

212

// Production certificates with strict validation

213

const certs = loadCertificates('./certs/production');

214

Object.assign(config, certs, { strictSSL: true });

215

}

216

217

return fetch.defaults(config);

218

};

219

220

// Certificate rotation handling

221

class CertificateManager {

222

constructor(certDir) {

223

this.certDir = certDir;

224

this.certificates = null;

225

this.lastLoaded = 0;

226

this.refreshInterval = 60 * 60 * 1000; // 1 hour

227

}

228

229

loadCertificates() {

230

const now = Date.now();

231

if (!this.certificates || (now - this.lastLoaded) > this.refreshInterval) {

232

this.certificates = {

233

ca: fs.readFileSync(path.join(this.certDir, 'ca.pem')),

234

cert: fs.readFileSync(path.join(this.certDir, 'client.pem')),

235

key: fs.readFileSync(path.join(this.certDir, 'client-key.pem'))

236

};

237

this.lastLoaded = now;

238

}

239

return this.certificates;

240

}

241

242

createFetch() {

243

const certs = this.loadCertificates();

244

return fetch.defaults(certs);

245

}

246

}

247

248

// Usage

249

const certManager = new CertificateManager('./certs');

250

const secureFetch = certManager.createFetch();

251

```

252

253

### Security Error Handling

254

255

Handle security-related errors appropriately:

256

257

```javascript { .api }

258

/**

259

* Security-related error codes:

260

* - EINTEGRITY: Subresource integrity verification failed

261

* - DEPTH_ZERO_SELF_SIGNED_CERT: Self-signed certificate

262

* - UNABLE_TO_VERIFY_LEAF_SIGNATURE: Certificate verification failed

263

* - CERT_HAS_EXPIRED: Certificate has expired

264

* - CERT_NOT_YET_VALID: Certificate not yet valid

265

* - UNABLE_TO_GET_ISSUER_CERT: Cannot get certificate issuer

266

*/

267

```

268

269

**Usage Examples:**

270

271

```javascript

272

try {

273

const response = await fetch('https://secure-api.example.com/data', {

274

cert: clientCert,

275

key: clientKey,

276

ca: caCert,

277

integrity: 'sha256-expected-hash'

278

});

279

} catch (error) {

280

switch (error.code) {

281

case 'EINTEGRITY':

282

console.log('Response integrity verification failed');

283

// Log security incident

284

break;

285

case 'DEPTH_ZERO_SELF_SIGNED_CERT':

286

console.log('Server uses self-signed certificate');

287

// Decide whether to allow or reject

288

break;

289

case 'CERT_HAS_EXPIRED':

290

console.log('Server certificate has expired');

291

// Alert operations team

292

break;

293

case 'UNABLE_TO_VERIFY_LEAF_SIGNATURE':

294

console.log('Certificate verification failed');

295

// Security error - do not retry

296

break;

297

default:

298

console.log('Security error:', error.message);

299

}

300

}

301

302

// Graceful degradation for certificate issues

303

const fetchWithFallback = async (url, options = {}) => {

304

try {

305

return await fetch(url, options);

306

} catch (error) {

307

if (error.code === 'DEPTH_ZERO_SELF_SIGNED_CERT' &&

308

process.env.NODE_ENV === 'development') {

309

console.warn('Allowing self-signed cert in development');

310

return await fetch(url, { ...options, strictSSL: false });

311

}

312

throw error;

313

}

314

};

315

```

316

317

### Content Security Policies

318

319

Integrate with content security policies and security headers:

320

321

```javascript

322

// Generate SRI hashes for CSP

323

const crypto = require('crypto');

324

325

const generateIntegrityHash = (content, algorithm = 'sha256') => {

326

const hash = crypto.createHash(algorithm);

327

hash.update(content);

328

return `${algorithm}-${hash.digest('base64')}`;

329

};

330

331

// Fetch and generate CSP-compatible integrity hash

332

const response = await fetch('https://cdn.example.com/library.js');

333

const content = await response.text();

334

const integrityHash = generateIntegrityHash(content);

335

336

console.log(`<script src="https://cdn.example.com/library.js"

337

integrity="${integrityHash}"

338

crossorigin="anonymous"></script>`);

339

340

// Verify against known good hashes

341

const knownGoodHashes = {

342

'library.js': 'sha256-abc123...',

343

'framework.js': 'sha256-def456...'

344

};

345

346

const secureResponse = await fetch('https://cdn.example.com/library.js', {

347

integrity: knownGoodHashes['library.js']

348

});

349

```