-
Notifications
You must be signed in to change notification settings - Fork 4.3k
Add API Security Cheat Sheet - Unified Guidance for All API Types #1868
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
fd0ff1b to
43d47a8
Compare
mackowski
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do not like structure of this cheatsheet, 50% is just API top 10 (we do not need to duplicate content from different OWASP project) and there is a lot of duplication from other cheatsheets.
I hear you Mac. The goal here was to not duplicate content. #1865 |
|
Thanks @mackowski and @jmanico for the feedback. The goal isn’t to duplicate content from the API Top 10 or other cheat sheets — rather, to complement them with practical, implementation-focused guidance. I’ll revise the structure to make that clearer and remove any overlapping sections. |
…g security, performance considerations
427c3c5 to
da1e43b
Compare
|
@mackowski, @jmanico I've restructured the cheat sheet to eliminate content duplication by adding an explicit scope section that separates enterprise patterns from existing OWASP sheets (Authentication/Authorization/API Top 10) and added new sections for API versioning security and performance considerations with concrete metrics. The sheet now serves as a complementary enterprise reference focused on multi-tenant isolation, federation, and gateway patterns without duplicating existing OWASP resources. |
|
Hello @jmanico and @mackowski, I'm still awaiting your review. If there are any changes needed or feedback to discuss, please let me know. Thank you. |
szh
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks good to me. I'll wait for @jmanico and @mackowski to review as well though.
jmanico
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome
|
I am still not approvig that baseuse Centralized Gateway Security - this is not best solution for all APIs and we already have a good content here for it https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets_draft/Authorization_Patterns_Cheat_Sheet.md Technology-Agnostic Authentication - again this is useful for some APIs but not all of them and for many it will only complicate authentication logic. All "Enterprise Security Patterns" ale useful but there are not recommandations for all APIs... This content drifted a lot from beeing universal API recommendation to list of possible architectual patterns for some enterprise APIs. We could re-name this to Enterprise Security Architectual Patterns Cheat Sheet and update narrative at the beginning a little bit. In such case I would still add more patterns - one specific example is proof of possession. Also I would review content that we have in draft to not duplicate it but link to it where possible |
|
The content is good but, in my opinion, this are just not general purpos APIs recommendations - and that was the orginal goal. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR introduces a comprehensive API Security Cheat Sheet that provides enterprise-grade security patterns applicable across all API technologies (REST, GraphQL, gRPC, WebSocket). The cheat sheet focuses on architectural security controls and universal patterns rather than protocol-specific implementations.
Key Changes:
- Enterprise security patterns including multi-tenant isolation, cross-organization federation, centralized gateway security, and API versioning security
- Universal security controls for cross-protocol rate limiting and technology-agnostic authentication
- Security operations guidance for cross-protocol testing and automated threat orchestration
- Performance considerations for security controls with optimization strategies
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| try { | ||
| TrustConfig config = TrustConfig.builder() | ||
| .mutualTLS(certificateService.exchangeCertificates(partnerOrg)) | ||
| .tokenExchange(setupOAuth2Exchange(partnerOrg)) |
Copilot
AI
Nov 9, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing method definition for setupOAuth2Exchange. This method is called at line 130 but is never defined in the FederationSecurityManager class, which will cause a compilation error.
| return true; | ||
| } | ||
| return false; | ||
| } |
Copilot
AI
Nov 9, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Incomplete CircuitBreaker implementation. The class initializes failureCount and lastFailureTime but never updates them. The isOpen() method checks these values, but there's no method to record failures, update the state to OPEN, or transition between states properly. Add methods like recordSuccess() and recordFailure() to maintain the circuit breaker state machine.
| } | |
| } | |
| recordFailure() { | |
| this.failureCount += 1; | |
| this.lastFailureTime = Date.now(); | |
| if (this.failureCount >= this.failureThreshold && this.state === 'CLOSED') { | |
| this.state = 'OPEN'; | |
| } else if (this.state === 'HALF_OPEN') { | |
| // If a failure occurs in HALF_OPEN, go back to OPEN | |
| this.state = 'OPEN'; | |
| } | |
| } | |
| recordSuccess() { | |
| if (this.state === 'HALF_OPEN') { | |
| // Success in HALF_OPEN means recovery | |
| this.state = 'CLOSED'; | |
| this.failureCount = 0; | |
| this.lastFailureTime = null; | |
| } else if (this.state === 'CLOSED') { | |
| // Success in CLOSED just resets failure count | |
| this.failureCount = 0; | |
| this.lastFailureTime = null; | |
| } | |
| } |
|
|
||
| // Version-specific authentication | ||
| if (policy.isAuthRequired()) { | ||
| context.setUser(authenticateRequest(request, policy)); |
Copilot
AI
Nov 9, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing method definition for authenticateRequest. This method is called at line 364 but is never defined in the APIVersionSecurity class, which will cause a compilation error.
| } catch (error) { | ||
| throw new InvalidTokenError(error.message); | ||
| } | ||
| } |
Copilot
AI
Nov 9, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing method definitions in UniversalAuth class. The following methods are called but never defined:
getPublicKey()at line 456validateClaims()at line 459handleHTTPAuth,handleWebSocketAuth,handleWebhookAuth,handleGRPCAuthreferenced at lines 439-442
These missing methods will cause runtime errors when the class is used.
| } | |
| } | |
| // Returns the public key for JWT verification | |
| getPublicKey() { | |
| // In production, load from secure config or environment | |
| return process.env.JWT_PUBLIC_KEY || "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnExampleKey\n-----END PUBLIC KEY-----"; | |
| } | |
| // Validates universal claims in the decoded JWT | |
| validateClaims(decoded) { | |
| if (!decoded.sub) { | |
| throw new InvalidTokenError("Missing subject claim"); | |
| } | |
| if (!decoded.tenant) { | |
| throw new InvalidTokenError("Missing tenant claim"); | |
| } | |
| // Add more claim checks as needed | |
| } | |
| // Protocol-specific authentication handlers | |
| async handleHTTPAuth(request) { | |
| // Example: extract JWT from Authorization header | |
| const token = request.headers?.authorization?.replace(/^Bearer\s/, ""); | |
| if (!token) throw new InvalidTokenError("Missing Authorization header"); | |
| return await this.validateJWT(token); | |
| } | |
| async handleWebSocketAuth(request) { | |
| // Example: extract JWT from query or initial payload | |
| const token = request.token || request.query?.token; | |
| if (!token) throw new InvalidTokenError("Missing WebSocket token"); | |
| return await this.validateJWT(token); | |
| } | |
| async handleWebhookAuth(request) { | |
| // Example: extract JWT from custom header or payload | |
| const token = request.headers?.['x-webhook-token'] || request.body?.token; | |
| if (!token) throw new InvalidTokenError("Missing Webhook token"); | |
| return await this.validateJWT(token); | |
| } | |
| async handleGRPCAuth(request) { | |
| // Example: extract JWT from metadata | |
| const token = request.metadata?.get('authorization')?.[0]?.replace(/^Bearer\s/, ""); | |
| if (!token) throw new InvalidTokenError("Missing gRPC authorization metadata"); | |
| return await this.validateJWT(token); | |
| } |
| details: results, | ||
| securityScore: (passedTests / totalTests) * 100 | ||
| }; | ||
| } |
Copilot
AI
Nov 9, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing method definitions in UniversalAPITester class. The following methods are called but never defined:
testAuthz()at line 492testInjection()at line 493testRateLimit()at line 494testDataLeakage()at line 495testGraphQLAuth,testWebSocketAuth,testWebhookAuthreferenced at lines 513-516getExpiredToken()at line 526
These missing methods will cause runtime errors when the testing functionality is used.
| } | |
| } | |
| // Missing method definitions added below | |
| async testAuthz(endpoint, protocol) { | |
| // Simulate an authorization test | |
| // In a real implementation, this would attempt access with insufficient privileges | |
| return { status: 'passed', detail: 'Authorization test not implemented (stub).' }; | |
| } | |
| async testInjection(endpoint, protocol) { | |
| // Simulate an injection test | |
| // In a real implementation, this would send malicious payloads | |
| return { status: 'passed', detail: 'Injection test not implemented (stub).' }; | |
| } | |
| async testRateLimit(endpoint, protocol) { | |
| // Simulate a rate limiting test | |
| // In a real implementation, this would send rapid requests and check for 429 | |
| return { status: 'passed', detail: 'Rate limit test not implemented (stub).' }; | |
| } | |
| async testDataLeakage(endpoint, protocol) { | |
| // Simulate a data leakage test | |
| // In a real implementation, this would attempt to access data outside allowed scope | |
| return { status: 'passed', detail: 'Data leakage test not implemented (stub).' }; | |
| } | |
| async testGraphQLAuth(endpoint) { | |
| // Simulate a GraphQL authentication test | |
| // In a real implementation, this would send a GraphQL query with/without tokens | |
| return [{ test: 'graphql_auth', passed: true }]; | |
| } | |
| async testWebSocketAuth(endpoint) { | |
| // Simulate a WebSocket authentication test | |
| // In a real implementation, this would attempt to connect/send messages with/without tokens | |
| return [{ test: 'websocket_auth', passed: true }]; | |
| } | |
| async testWebhookAuth(endpoint) { | |
| // Simulate a Webhook authentication test | |
| // In a real implementation, this would send a webhook request with/without valid signature | |
| return [{ test: 'webhook_auth', passed: true }]; | |
| } | |
| getExpiredToken() { | |
| // Return a string representing an expired token | |
| // In a real implementation, generate a JWT or token with a past expiry | |
| return 'expired.token.value'; | |
| } |
| class APIThreatOrchestrator { | ||
| constructor() { | ||
| this.responseStrategies = new Map(); | ||
| this.threatIntelligence = new ThreatIntelligenceEngine(); | ||
| } | ||
|
|
||
| async orchestrateResponse(threatEvent) { | ||
| const threatContext = await this.analyzeThreat(threatEvent); | ||
| const affectedAPIs = this.identifyAffectedAPIs(threatContext); | ||
|
|
||
| // Coordinate response across multiple API types | ||
| const responses = await Promise.all( | ||
| affectedAPIs.map(api => this.executeResponse(api, threatContext)) | ||
| ); | ||
|
|
||
| return this.consolidateResponses(responses); | ||
| } | ||
|
|
||
| async executeResponse(api, threatContext) { | ||
| const strategy = this.getResponseStrategy(api.type, threatContext.severity); | ||
|
|
||
| return { | ||
| apiId: api.id, | ||
| actions: await strategy.execute(api, threatContext), | ||
| timestamp: Date.now() | ||
| }; | ||
| } | ||
|
|
||
| // Adaptive security posture adjustment | ||
| async adaptSecurityPosture(threatLandscape) { | ||
| const adjustments = { | ||
| rateLimits: this.calculateRateLimitAdjustments(threatLandscape), | ||
| authStrength: this.adjustAuthRequirements(threatLandscape), | ||
| monitoring: this.enhanceMonitoring(threatLandscape) | ||
| }; | ||
|
|
||
| return this.applyGlobalAdjustments(adjustments); | ||
| } | ||
|
|
||
| async analyzeThreat(threatEvent) { | ||
| return { | ||
| severity: this.calculateSeverity(threatEvent), | ||
| type: threatEvent.type, | ||
| source: threatEvent.source, | ||
| affectedProtocols: this.identifyAffectedProtocols(threatEvent) | ||
| }; | ||
| } | ||
|
|
||
| identifyAffectedAPIs(threatContext) { | ||
| // Return APIs that match threat characteristics | ||
| return this.apiRegistry.filter(api => | ||
| threatContext.affectedProtocols.includes(api.protocol) | ||
| ); | ||
| } | ||
|
|
||
| getResponseStrategy(apiType, severity) { | ||
| const strategies = { | ||
| 'high': new ImmediateBlockStrategy(), | ||
| 'medium': new ThrottleStrategy(), | ||
| 'low': new MonitorStrategy() | ||
| }; | ||
| return strategies[severity] || strategies['low']; | ||
| } | ||
|
|
||
| consolidateResponses(responses) { | ||
| return { | ||
| totalAPIs: responses.length, | ||
| actionsExecuted: responses.reduce((sum, r) => sum + r.actions.length, 0), | ||
| timestamp: Date.now() | ||
| }; | ||
| } | ||
| } |
Copilot
AI
Nov 9, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing method definitions and uninitialized properties in APIThreatOrchestrator class. The following issues exist:
apiRegistryproperty referenced at line 615 but never initialized in constructorcalculateSeverity()called at line 606 but never definedidentifyAffectedProtocols()called at line 609 but never definedcalculateRateLimitAdjustments()called at line 596 but never definedadjustAuthRequirements()called at line 597 but never definedenhanceMonitoring()called at line 598 but never definedapplyGlobalAdjustments()called at line 601 but never defined
These missing implementations will cause runtime errors.
| class OptimizedSecurityMiddleware { | ||
| constructor() { | ||
| this.userCache = new LRUCache({ max: 10000, ttl: 300000 }); // 5min TTL | ||
| this.rateLimitCache = new Map(); | ||
| } | ||
|
|
||
| async authenticate(token) { | ||
| // Check cache first (0.1ms vs 10ms DB lookup) | ||
| const cached = this.userCache.get(token); | ||
| if (cached && cached.expiresAt > Date.now()) { | ||
| return cached.user; | ||
| } | ||
|
|
||
| // Fallback to database | ||
| const user = await this.userService.validateToken(token); | ||
| this.userCache.set(token, { user, expiresAt: Date.now() + 300000 }); | ||
| return user; | ||
| } | ||
|
|
||
| // Batch rate limit checks for better performance | ||
| async checkRateLimits(requests) { | ||
| const pipeline = this.redis.pipeline(); | ||
| requests.forEach(req => { | ||
| pipeline.incr(`rate:${req.userId}:${req.endpoint}`); | ||
| }); | ||
|
|
||
| const results = await pipeline.exec(); | ||
| return results.map((result, index) => ({ | ||
| allowed: result[1] <= requests[index].limit, | ||
| current: result[1] | ||
| })); | ||
| } | ||
| } |
Copilot
AI
Nov 9, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing property initialization in OptimizedSecurityMiddleware class. The following properties are referenced but never initialized in the constructor:
userServiceat line 677 (should be injected via constructor)redisat line 684 (should be injected via constructor)
These missing properties will cause runtime errors when the methods are called.
| if (!this.validateTenantAccess(request.user, tenantId)) { | ||
| this.auditLogger.logUnauthorizedAccess(request.user.id, tenantId); |
Copilot
AI
Nov 9, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Potential null pointer exception when request.user is null or undefined. The validateTenantAccess method returns false when user.tenants is undefined, but line 60 then tries to access request.user.id which will throw a TypeError. Add null check: if (!request.user || !this.validateTenantAccess(request.user, tenantId))
| if (!this.validateTenantAccess(request.user, tenantId)) { | |
| this.auditLogger.logUnauthorizedAccess(request.user.id, tenantId); | |
| if (!request.user || !this.validateTenantAccess(request.user, tenantId)) { | |
| this.auditLogger.logUnauthorizedAccess(request.user && request.user.id ? request.user.id : 'unknown', tenantId); |
mackowski
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See comments:
|
@mackowski Thanks for the detailed review — I really appreciate your feedback. The draft focuses on enterprise-oriented API architectural patterns, following earlier feedback that removed OWASP Top 10 references. I propose renaming it to “Enterprise API Security Architectural Patterns Cheat Sheet” and updating the introduction to clarify scope. Code snippets were flagged by GitHub Copilot, which is expected — they are intentionally illustrative, not full implementations. Regarding the performance section, the quantitative numbers were just illustrative examples to support my point, not sourced from benchmarks or generated by an LLM. They were intended to demonstrate relative trade-offs, but I understand that this can be misleading, so I’ll revise it to qualitative guidance with references where possible. Here’s a roadmap of the updates I plan to make:
Could you please review these proposed updates and confirm if this approach aligns with your expectations before I make the changes? Thank you :-) |
|
@mackowski I like the proposal |
Summary
This PR introduces a new API Security Cheat Sheet that provides comprehensive guidance for securing APIs across all technologies. The cheat sheet covers:
Checklist
Please make sure that for your contribution:
[TEXT](URL)Verification Details
[TEXT](CheatSheet.md)format and external links use[TEXT](URL)formatThis PR fixes #1865
AI Tool Usage Disclosure (required for all PRs)
Please select one of the following options:
the contents and I affirm the results. The LLM used is [
llm name and version]and the prompt used is [
your prompt here]. [Feel free to add more details if needed]Thank you 😃