Skip to content

Conversation

@PaperStrange
Copy link
Owner

Changes 🏗️

Patch release focused on frontend stability, error handling, and resilience improvements

Major Improvements

  • Fixed critical React Router nesting issues that caused runtime errors
  • Implemented Material UI ThemeProvider for consistent styling across components
  • Added proper error boundaries and fallback UI for backend service unavailability
  • Created comprehensive stability test suite with automated CI verification

####Technical Enhancements

  • Standardized API module organization with namespaced exports
  • Implemented proper ESLint global declarations for external libraries
  • Added graceful degradation for service failures
  • Enhanced component resilience with error boundaries

Testing Improvements

  • Added Router structure validation tests
  • Created Theme Provider presence tests
  • Implemented backend resilience tests
  • Added automated stability checks to CI/CD pipeline

Documentation Updates

  • Created comprehensive stability tests README
  • Updated core module documentation with API organization guidelines
  • Enhanced project refactoring records with stability improvements
  • Updated GitHub workflows documentation with stability checks

Known Issues

  • No new issues introduced

Checklist 📋

For code changes:

  • I have clearly listed my changes in the PR description
  • I have made a test plan
  • I have tested my changes according to the test plan: docs\stability-test-plan.md
Details Refer to src\tests, Results refer to docs\test-execution-results.md

For configuration changes:

  • .env.example is updated or already compatible with my changes
  • package.json, package-lock.json is updated or already compatible with my changes
  • I have included a list of my configuration changes in the PR description (under Changes)
Details Refer to .cursor\.milestones, .cursor\.project, .cursor\.todos

@PaperStrange PaperStrange self-assigned this Mar 25, 2025

- name: Set up AWS CLI
uses: aws-actions/configure-aws-credentials@v1
uses: aws-actions/configure-aws-credentials@v4

Check warning

Code scanning / CodeQL

Unpinned tag for a non-immutable Action in workflow Medium

Unpinned 3rd party Action 'TourGuideAI CI/CD Pipeline' step
Uses Step
uses 'aws-actions/configure-aws-credentials' with ref 'v4', not a pinned commit hash

- name: Set up AWS CLI
uses: aws-actions/configure-aws-credentials@v1
uses: aws-actions/configure-aws-credentials@v4

Check warning

Code scanning / CodeQL

Unpinned tag for a non-immutable Action in workflow Medium

Unpinned 3rd party Action 'TourGuideAI CI/CD Pipeline' step
Uses Step
uses 'aws-actions/configure-aws-credentials' with ref 'v4', not a pinned commit hash

# Use Dependabot to update dependencies
- name: Enable Dependabot
uses: dependabot/fetch-metadata@v1.6.0

Check warning

Code scanning / CodeQL

Unpinned tag for a non-immutable Action in workflow Medium

Unpinned 3rd party Action 'Dependency Updates' step
Uses Step
uses 'dependabot/fetch-metadata' with ref 'v1.6.0', not a pinned commit hash

# Alternative: Use Renovate for more control
- name: Update dependencies with Renovate
uses: renovatebot/github-action@v39.0.5

Check warning

Code scanning / CodeQL

Unpinned tag for a non-immutable Action in workflow Medium

Unpinned 3rd party Action 'Dependency Updates' step
Uses Step
uses 'renovatebot/github-action' with ref 'v39.0.5', not a pinned commit hash
Comment on lines +15 to +67
runs-on: ubuntu-latest
timeout-minutes: 30

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '18'
cache: 'npm'

- name: Install Dependencies
run: npm ci

- name: Install Playwright
run: npx playwright install --with-deps

- name: Build Application
run: npm run build

- name: Start Application
run: |
npm run start:server &
npm run start:client &
npx wait-on http://localhost:3000 http://localhost:5000/api/health

- name: Run Playwright Tests
run: npx playwright test

- name: Store Playwright Report
uses: actions/upload-artifact@v4
if: always()
with:
name: playwright-report
path: playwright-report/
retention-days: 14

- name: Store Playwright Screenshots
uses: actions/upload-artifact@v4
if: failure()
with:
name: playwright-screenshots
path: test-results/
retention-days: 14

- name: Publish Test Results
uses: EnricoMi/publish-unit-test-result-action@v2
if: always()
with:
files: |
playwright-report/*.xml No newline at end of file

Check warning

Code scanning / CodeQL

Workflow does not contain permissions Medium

Actions Job or Workflow does not set permissions

# Run Trivy vulnerability scanner
- name: Run Trivy vulnerability scanner
uses: aquasecurity/trivy-action@master

Check warning

Code scanning / CodeQL

Unpinned tag for a non-immutable Action in workflow Medium

Unpinned 3rd party Action 'Security Scan' step
Uses Step
uses 'aquasecurity/trivy-action' with ref 'master', not a pinned commit hash

# Secret scanning
- name: Secret Scanning with GitLeaks
uses: gitleaks/gitleaks-action@v2

Check warning

Code scanning / CodeQL

Unpinned tag for a non-immutable Action in workflow Medium

Unpinned 3rd party Action 'Security Scan' step
Uses Step
uses 'gitleaks/gitleaks-action' with ref 'v2', not a pinned commit hash

# Check package.json for issues
- name: Package.json security audit
uses: lirantal/lockfile-lint-action@master

Check warning

Code scanning / CodeQL

Unpinned tag for a non-immutable Action in workflow Medium

Unpinned 3rd party Action 'Security Scan' step
Uses Step
uses 'lirantal/lockfile-lint-action' with ref 'master', not a pinned commit hash
# OWASP ZAP Baseline Scan
- name: ZAP Baseline Scan
uses: zaproxy/action-baseline@v0.7.0
uses: zaproxy/action-baseline@v0.9.0

Check warning

Code scanning / CodeQL

Unpinned tag for a non-immutable Action in workflow Medium

Unpinned 3rd party Action 'Security Scan' step
Uses Step
uses 'zaproxy/action-baseline' with ref 'v0.9.0', not a pinned commit hash

# License compliance scanning
- name: License Scanning
uses: fossas/fossa-action@main

Check warning

Code scanning / CodeQL

Unpinned tag for a non-immutable Action in workflow Medium

Unpinned 3rd party Action 'Security Scan' step
Uses Step
uses 'fossas/fossa-action' with ref 'main', not a pinned commit hash
// Extract token from request
const token = jwtAuth.extractTokenFromRequest(req);

if (!token) {

Check failure

Code scanning / CodeQL

User-controlled bypass of security check High

This condition guards a sensitive
action
, but a
user-provided value
controls it.
// Extract token from request
const token = jwtAuth.extractTokenFromRequest(req);

if (!token) {

Check failure

Code scanning / CodeQL

User-controlled bypass of security check High

This condition guards a sensitive
action
, but a
user-provided value
controls it.

// Send welcome email
emailService.sendWelcomeEmail(user)
.catch(error => logger.error('Error sending welcome email', { error, userId: user.id }));

Check failure

Code scanning / CodeQL

Clear-text logging of sensitive information High

This logs sensitive data returned by
an access to userWithoutPassword
as clear text.

Copilot Autofix

AI 10 months ago

To fix the problem, we should avoid logging sensitive user information. Instead of logging the entire userId, we can log a generic message or a hashed version of the userId to maintain some level of traceability without exposing the actual identifier. This way, we can still have useful logs for debugging without compromising user privacy.

  • Replace the logging statements that include { error, userId: user.id } with a more generic message or a hashed version of the userId.
  • Update the relevant lines in server/routes/auth.js.
Suggested changeset 1
server/routes/auth.js

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/server/routes/auth.js b/server/routes/auth.js
--- a/server/routes/auth.js
+++ b/server/routes/auth.js
@@ -126,3 +126,3 @@
     emailService.sendWelcomeEmail(user)
-      .catch(error => logger.error('Error sending welcome email', { error, userId: user.id }));
+      .catch(error => logger.error('Error sending welcome email', { error: error.message }));
     
@@ -130,3 +130,3 @@
     emailService.sendVerificationEmail(user)
-      .catch(error => logger.error('Error sending verification email', { error, userId: user.id }));
+      .catch(error => logger.error('Error sending verification email', { error: error.message }));
     
EOF
@@ -126,3 +126,3 @@
emailService.sendWelcomeEmail(user)
.catch(error => logger.error('Error sending welcome email', { error, userId: user.id }));
.catch(error => logger.error('Error sending welcome email', { error: error.message }));

@@ -130,3 +130,3 @@
emailService.sendVerificationEmail(user)
.catch(error => logger.error('Error sending verification email', { error, userId: user.id }));
.catch(error => logger.error('Error sending verification email', { error: error.message }));

Copilot is powered by AI and may make mistakes. Always verify output.

// Send email verification
emailService.sendVerificationEmail(user)
.catch(error => logger.error('Error sending verification email', { error, userId: user.id }));

Check failure

Code scanning / CodeQL

Clear-text logging of sensitive information High

This logs sensitive data returned by
an access to userWithoutPassword
as clear text.

Copilot Autofix

AI 10 months ago

To fix the problem, we should avoid logging sensitive information such as user identifiers. Instead, we can log a generic error message without including sensitive details. This ensures that sensitive data is not exposed in the logs while still providing useful information for debugging purposes.

  • Replace the logging statements that include sensitive information with more generic messages.
  • Specifically, update the logging statements in the catch blocks to exclude the userId field.
  • No additional methods, imports, or definitions are needed to implement these changes.
Suggested changeset 1
server/routes/auth.js

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/server/routes/auth.js b/server/routes/auth.js
--- a/server/routes/auth.js
+++ b/server/routes/auth.js
@@ -126,3 +126,3 @@
     emailService.sendWelcomeEmail(user)
-      .catch(error => logger.error('Error sending welcome email', { error, userId: user.id }));
+      .catch(error => logger.error('Error sending welcome email', { error }));
     
@@ -130,3 +130,3 @@
     emailService.sendVerificationEmail(user)
-      .catch(error => logger.error('Error sending verification email', { error, userId: user.id }));
+      .catch(error => logger.error('Error sending verification email', { error }));
     
EOF
@@ -126,3 +126,3 @@
emailService.sendWelcomeEmail(user)
.catch(error => logger.error('Error sending welcome email', { error, userId: user.id }));
.catch(error => logger.error('Error sending welcome email', { error }));

@@ -130,3 +130,3 @@
emailService.sendVerificationEmail(user)
.catch(error => logger.error('Error sending verification email', { error, userId: user.id }));
.catch(error => logger.error('Error sending verification email', { error }));

Copilot is powered by AI and may make mistakes. Always verify output.
if (sendInvite) {
// Send welcome email
emailService.sendWelcomeEmail(user)
.catch(error => logger.error('Error sending welcome email', { error, userId: user.id }));

Check failure

Code scanning / CodeQL

Clear-text logging of sensitive information High

This logs sensitive data returned by
an access to userWithoutPassword
as clear text.
html
});
} catch (error) {
logger.error('Error sending password reset email', { error, email });

Check failure

Code scanning / CodeQL

Clear-text logging of sensitive information High

This logs sensitive data returned by
an access to passwordResetToken
as clear text.
This logs sensitive data returned by
an access to passwordResetExpires
as clear text.

Copilot Autofix

AI 10 months ago

To fix the problem, we should avoid logging sensitive information such as email addresses directly. Instead, we can log a generic message or use a placeholder to indicate the presence of sensitive data without exposing it. This can be achieved by removing the email parameter from the logger.error call and replacing it with a generic message.

  • Update the logger.error call in the sendPasswordResetEmail function to remove the email parameter.
  • Ensure that the log message still provides enough context to understand the error without exposing sensitive information.
Suggested changeset 1
server/services/emailService.js

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/server/services/emailService.js b/server/services/emailService.js
--- a/server/services/emailService.js
+++ b/server/services/emailService.js
@@ -329,3 +329,3 @@
   } catch (error) {
-    logger.error('Error sending password reset email', { error, email });
+    logger.error('Error sending password reset email', { error });
     return false;
EOF
@@ -329,3 +329,3 @@
} catch (error) {
logger.error('Error sending password reset email', { error, email });
logger.error('Error sending password reset email', { error });
return false;
Copilot is powered by AI and may make mistakes. Always verify output.
} else {
// Otherwise create a new secret
const secretId = await vaultService.storeSecret(secretType, serviceName, token);
this.secretIdMapping[serviceName] = secretId;

Check failure

Code scanning / CodeQL

Remote property injection High

A property name to write to depends on a
user-provided value
.

return true;
} catch (error) {
logger.error(`Failed to store token for ${serviceName}`, { error });

Check warning

Code scanning / CodeQL

Log injection Medium

Log entry depends on a
user-provided value
.

Copilot Autofix

AI 10 months ago

To fix the log injection issue, we need to sanitize the serviceName before logging it. Specifically, we should remove any newline characters from the serviceName to prevent log injection. This can be done using String.prototype.replace to ensure no line endings are present in the user input.

Suggested changeset 1
server/utils/tokenProvider.js

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/server/utils/tokenProvider.js b/server/utils/tokenProvider.js
--- a/server/utils/tokenProvider.js
+++ b/server/utils/tokenProvider.js
@@ -173,3 +173,4 @@
     } catch (error) {
-      logger.error(`Failed to store token for ${serviceName}`, { error });
+      const sanitizedServiceName = serviceName.replace(/\n|\r/g, "");
+      logger.error(`Failed to store token for ${sanitizedServiceName}`, { error });
       throw error;
EOF
@@ -173,3 +173,4 @@
} catch (error) {
logger.error(`Failed to store token for ${serviceName}`, { error });
const sanitizedServiceName = serviceName.replace(/\n|\r/g, "");
logger.error(`Failed to store token for ${sanitizedServiceName}`, { error });
throw error;
Copilot is powered by AI and may make mistakes. Always verify output.

return true;
} catch (error) {
logger.error(`Failed to rotate token for ${serviceName}`, { error });

Check warning

Code scanning / CodeQL

Log injection Medium

Log entry depends on a
user-provided value
.

Copilot Autofix

AI 10 months ago

To fix the log injection issue, we need to sanitize the serviceName before logging it. Specifically, we should remove any newline characters from the serviceName to prevent log injection. This can be done using String.prototype.replace to ensure no line endings are present in the user input.

Suggested changeset 2
server/utils/tokenProvider.js

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/server/utils/tokenProvider.js b/server/utils/tokenProvider.js
--- a/server/utils/tokenProvider.js
+++ b/server/utils/tokenProvider.js
@@ -196,3 +196,4 @@
     } catch (error) {
-      logger.error(`Failed to rotate token for ${serviceName}`, { error });
+      const sanitizedServiceName = serviceName.replace(/\n|\r/g, "");
+      logger.error(`Failed to rotate token for ${sanitizedServiceName}`, { error });
       throw error;
EOF
@@ -196,3 +196,4 @@
} catch (error) {
logger.error(`Failed to rotate token for ${serviceName}`, { error });
const sanitizedServiceName = serviceName.replace(/\n|\r/g, "");
logger.error(`Failed to rotate token for ${sanitizedServiceName}`, { error });
throw error;
server/routes/admin.js
Outside changed files

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/server/routes/admin.js b/server/routes/admin.js
--- a/server/routes/admin.js
+++ b/server/routes/admin.js
@@ -65,3 +65,4 @@
   } catch (error) {
-    logger.error('Error rotating token', { error, serviceName: req.body.serviceName });
+    const sanitizedServiceName = req.body.serviceName.replace(/\n|\r/g, "");
+    logger.error('Error rotating token', { error, serviceName: sanitizedServiceName });
     res.status(500).json({
EOF
@@ -65,3 +65,4 @@
} catch (error) {
logger.error('Error rotating token', { error, serviceName: req.body.serviceName });
const sanitizedServiceName = req.body.serviceName.replace(/\n|\r/g, "");
logger.error('Error rotating token', { error, serviceName: sanitizedServiceName });
res.status(500).json({
Copilot is powered by AI and may make mistakes. Always verify output.
try {
await fs.access(this.vaultPath);
// Load existing vault
const encryptedVault = await fs.readFile(this.vaultPath, 'utf8');

Check failure

Code scanning / CodeQL

Potential file system race condition High

The file may have changed since it
was checked
.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants