Skip to content

Commit 134b5a1

Browse files
Copilotcommjoen
andcommitted
Fix Challenge 58 missing files and Black formatting issues
Co-authored-by: commjoen <[email protected]>
1 parent a0b85b8 commit 134b5a1

File tree

3 files changed

+188
-1
lines changed

3 files changed

+188
-1
lines changed

.github/scripts/generate_thymeleaf_previews.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1352,7 +1352,9 @@ def generate_all_pages(self):
13521352
print(f"Generated {filename}")
13531353

13541354
print(f"Generated {len(pages)} static pages in {pages_dir}")
1355-
print(f"✅ Challenge 57 (LLM Security) and Challenge 58 (Database Connection String Exposure) are both available")
1355+
print(
1356+
f"✅ Challenge 57 (LLM Security) and Challenge 58 (Database Connection String Exposure) are both available"
1357+
)
13561358
print(f"✅ Challenge 58 is featured as the latest challenge")
13571359
return pages_dir
13581360

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<div id="database-challenge-container" style="border: 1px solid #ccc; border-radius: 8px; padding: 20px; margin: 20px; background-color: #f9f9f9;">
2+
<h4>🗄️ Database Connection Error Demo</h4>
3+
<p>This challenge demonstrates how database connection failures can expose sensitive credentials through error messages.</p>
4+
5+
<div style="background: #fff3cd; border: 1px solid #ffeaa7; border-radius: 6px; padding: 15px; margin: 15px 0;">
6+
<p><strong>Try the vulnerable endpoint:</strong></p>
7+
<p>Click the button below to trigger a database connection error that exposes the connection string with embedded credentials.</p>
8+
<a href="/error-demo/database-connection" class="btn btn-warning" style="background-color: #ffc107; border-color: #ffc107; color: #212529; text-decoration: none; display: inline-block; padding: 8px 16px; border-radius: 4px; border: 1px solid transparent; font-weight: 400; text-align: center; vertical-align: middle; cursor: pointer; font-size: 1rem; line-height: 1.5; margin-top: 10px;">
9+
🚨 Trigger Database Connection Error
10+
</a>
11+
<p style="margin-top: 10px;"><small style="color: #666;">This endpoint simulates a database connection failure that exposes the connection string with embedded credentials.</small></p>
12+
</div>
13+
14+
<div style="margin-top: 15px; font-size: 12px; color: #666;">
15+
💡 Tip: Look for the database password in the error message or application logs.
16+
</div>
17+
</div>
Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
import ChallengesPage from '../pages/challengesPage'
2+
3+
describe('Challenge 58 Database Connection String Exposure Tests', () => {
4+
// Challenge 58 specific selectors
5+
const DATABASE_CONTAINER = '#database-challenge-container'
6+
const ERROR_DEMO_LINK = 'a[href="/error-demo/database-connection"]'
7+
8+
beforeEach(() => {
9+
// Visit Challenge 58 page
10+
cy.visit('/challenge/challenge-58')
11+
12+
// Verify the page loads correctly
13+
cy.dataCy(ChallengesPage.CHALLENGE_TITLE).should('contain', 'Challenge 58')
14+
15+
// Wait for database challenge container to be ready
16+
cy.get(DATABASE_CONTAINER, { timeout: 10000 }).should('be.visible')
17+
})
18+
19+
it('Challenge interface displays correctly', () => {
20+
// Verify database container is present with correct structure
21+
cy.get(DATABASE_CONTAINER).should('be.visible')
22+
cy.get(DATABASE_CONTAINER).should('contain', 'Database Connection Error Demo')
23+
24+
// Verify error demo link is present and functional
25+
cy.get(ERROR_DEMO_LINK).should('be.visible').and('not.be.disabled')
26+
cy.get(ERROR_DEMO_LINK).should('contain', 'Trigger Database Connection Error')
27+
28+
// Verify instructional content
29+
cy.get(DATABASE_CONTAINER).should('contain', 'This challenge demonstrates how database connection failures')
30+
cy.get(DATABASE_CONTAINER).should('contain', 'Look for the database password')
31+
})
32+
33+
it('Error demo endpoint is accessible and returns error with exposed credentials', () => {
34+
// Click the error demo link
35+
cy.get(ERROR_DEMO_LINK).click()
36+
37+
// Verify we're redirected to the error demo endpoint
38+
cy.url().should('include', '/error-demo/database-connection')
39+
40+
// Wait for page to load and check for error content
41+
cy.get('body', { timeout: 10000 }).should('be.visible')
42+
43+
// The error page should contain database connection information
44+
cy.get('body').should(($body) => {
45+
const text = $body.text()
46+
// Look for typical database connection error patterns that might expose credentials
47+
const hasErrorIndicators = text.includes('SuperSecretDB2024!') ||
48+
text.includes('connection') ||
49+
text.includes('database') ||
50+
text.includes('error') ||
51+
text.includes('failed') ||
52+
text.includes('postgresql') ||
53+
text.includes('jdbc')
54+
expect(hasErrorIndicators, 'Expected database error page with connection information').to.be.true
55+
})
56+
})
57+
58+
it('Database error exposes the target secret', () => {
59+
// Access the error demo endpoint
60+
cy.visit('/error-demo/database-connection')
61+
62+
// Look for the specific secret in the page content
63+
cy.get('body', { timeout: 10000 }).should('contain', 'SuperSecretDB2024!')
64+
})
65+
66+
it('Can solve the challenge using the exposed database password', () => {
67+
// First, trigger the database error to find the secret
68+
cy.get(ERROR_DEMO_LINK).click()
69+
70+
// Wait for error page and extract the secret
71+
cy.get('body', { timeout: 10000 }).should('contain', 'SuperSecretDB2024!')
72+
73+
// Navigate back to the challenge page
74+
cy.visit('/challenge/challenge-58')
75+
76+
// Use the secret to solve the challenge
77+
cy.dataCy(ChallengesPage.ANSWER_TEXTBOX).type('SuperSecretDB2024!')
78+
cy.dataCy(ChallengesPage.SUBMIT_TEXTBOX_BTN).click()
79+
80+
// Verify success
81+
cy.dataCy(ChallengesPage.SUCCESS_ALERT).should('contain', 'Your answer is correct!')
82+
})
83+
84+
it('Challenge follows WrongSecrets standard structure', () => {
85+
// Verify standard WrongSecrets challenge elements
86+
cy.dataCy(ChallengesPage.CHALLENGE_TITLE).should('be.visible')
87+
cy.dataCy(ChallengesPage.ANSWER_TEXTBOX).should('be.visible')
88+
cy.dataCy(ChallengesPage.SUBMIT_TEXTBOX_BTN).should('be.visible')
89+
90+
// Verify Challenge 58 specific database container
91+
cy.get(DATABASE_CONTAINER).should('be.visible')
92+
cy.get(DATABASE_CONTAINER).should('contain', 'Database Connection Error Demo')
93+
cy.get(DATABASE_CONTAINER).should('contain', 'database connection failures')
94+
95+
// Verify error demo link is present
96+
cy.get(ERROR_DEMO_LINK).should('be.visible')
97+
})
98+
99+
it('Validates the educational objective of database credential exposure', () => {
100+
// This test emphasizes the learning goal following WrongSecrets educational patterns
101+
cy.log('Challenge 58 demonstrates database connection string credential exposure through error handling')
102+
103+
// Verify the error endpoint exposes credentials (educational success criteria)
104+
cy.visit('/error-demo/database-connection')
105+
cy.get('body', { timeout: 10000 }).should('contain', 'SuperSecretDB2024!')
106+
107+
// This demonstrates how poor error handling can expose database credentials
108+
cy.log('Successfully demonstrated database credential exposure - users learn how error handling can leak sensitive connection information')
109+
110+
// Verify this allows solving the challenge
111+
cy.visit('/challenge/challenge-58')
112+
cy.dataCy(ChallengesPage.ANSWER_TEXTBOX).type('SuperSecretDB2024!')
113+
cy.dataCy(ChallengesPage.SUBMIT_TEXTBOX_BTN).click()
114+
cy.dataCy(ChallengesPage.SUCCESS_ALERT).should('contain', 'Your answer is correct!')
115+
})
116+
117+
it('Demonstrates realistic database error scenario for learning', () => {
118+
// Educational test showing how database errors expose credentials in real applications
119+
cy.log('Testing realistic database connection failure scenario')
120+
121+
// Access the error endpoint
122+
cy.visit('/error-demo/database-connection')
123+
124+
// Verify error content contains realistic database connection information
125+
cy.get('body').should(($body) => {
126+
const text = $body.text()
127+
// Look for realistic database connection error patterns
128+
const hasRealisticError = text.includes('connection') ||
129+
text.includes('database') ||
130+
text.includes('failed') ||
131+
text.includes('timeout') ||
132+
text.includes('refused') ||
133+
text.includes('unable')
134+
expect(hasRealisticError, 'Expected realistic database connection error message').to.be.true
135+
})
136+
137+
// Most importantly, verify the credentials are exposed
138+
cy.get('body').should('contain', 'SuperSecretDB2024!')
139+
140+
cy.log('Educational objective achieved: Database credentials exposed through error handling demonstrate real-world vulnerability')
141+
})
142+
143+
it('Error endpoint demonstrates common logging/error disclosure patterns', () => {
144+
// Test that the error endpoint demonstrates realistic error disclosure
145+
cy.visit('/error-demo/database-connection')
146+
147+
// Check for common error patterns that expose secrets
148+
cy.get('body').should(($body) => {
149+
const content = $body.text()
150+
// Look for patterns typical in database connection errors
151+
const hasConnectionString = content.includes('jdbc:') ||
152+
content.includes('postgresql://') ||
153+
content.includes('connection string') ||
154+
content.includes('SuperSecretDB2024!')
155+
expect(hasConnectionString, 'Expected database connection string or credential exposure').to.be.true
156+
})
157+
})
158+
159+
it('Challenge page provides proper educational guidance', () => {
160+
// Verify the challenge provides educational context
161+
cy.get(DATABASE_CONTAINER).should('contain', 'database connection failures can expose sensitive credentials')
162+
cy.get(DATABASE_CONTAINER).should('contain', 'Look for the database password')
163+
164+
// Verify the demo section explains the vulnerability
165+
cy.get(DATABASE_CONTAINER).should('contain', 'Click the button below to trigger a database connection error')
166+
cy.get(DATABASE_CONTAINER).should('contain', 'exposes the connection string with embedded credentials')
167+
})
168+
})

0 commit comments

Comments
 (0)