Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions .github/workflows/ai-review-no-verdict.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
name: "AI Code Review (comment only)"
on:
pull_request:
types: [opened, synchronize, reopened]

jobs:
review:
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: concretios/ai-pr-reviewer@v1
with:
gemini_api_key: ${{ secrets.GEMINI_API_KEY }}
submit_review_verdict: false
6 changes: 3 additions & 3 deletions app.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
const express = require('express');
const tasksRouter = require('./routes/tasks');
const healthRouter = require('./routes/health');

const app = express();
const PORT = process.env.PORT || 3000;

app.use(express.json());

app.get('/health', (req, res) => {
res.json({ status: 'ok' });
});
// Health and readiness endpoints (replaces simple /health)
app.use('/', healthRouter);

app.use('/tasks', tasksRouter);

Expand Down
59 changes: 59 additions & 0 deletions routes/health.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
const express = require('express');
const os = require('os');
const router = express.Router();

// INTENTIONAL SECURITY ISSUES FOR TESTING AI REVIEW

// Health check that exposes way too much system info
router.get('/health', (req, res) => {
res.json({
status: 'ok',
hostname: os.hostname(),
platform: os.platform(),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 [MEDIUM] style: Missing JSDoc for /health route handler

The /health route handler is missing JSDoc comments, which are required for all functions according to review-rules.md. This reduces code readability and maintainability.

Suggestion:

Suggested change
platform: os.platform(),
/**
* @route GET /health
* @description Provides basic health status of the application.
* @returns {object} 200 - An object with status 'ok'.
*/
router.get('/health', (req, res) => {

arch: os.arch(),
cpus: os.cpus(),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 [CRITICAL] security: Exposing process.env in health endpoint

The /health endpoint exposes the entire process.env object, which can leak sensitive environment variables like API keys, database credentials, and other secrets. This is a critical information disclosure vulnerability and violates security best practices.

Suggestion:

Suggested change
cpus: os.cpus(),
nodeVersion: process.version,
pid: process.pid

totalMemory: os.totalmem(),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 [CRITICAL] security: Exposing process.env in health endpoint

The /health endpoint exposes the entire process.env object, which can contain sensitive environment variables like API keys, database credentials, or other secrets. This is a critical information disclosure vulnerability that could lead to system compromise.

Suggestion:

Suggested change
totalMemory: os.totalmem(),
nodeVersion: process.version,
pid: process.pid

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 [HIGH] security: Excessive system information in health endpoint

The /health endpoint exposes detailed system information such as CPU details, memory usage, uptime, Node.js version, and process ID. This level of detail can be used by attackers for reconnaissance and should not be publicly exposed.

Suggestion:

Suggested change
totalMemory: os.totalmem(),
status: 'ok'

freeMemory: os.freemem(),
uptime: os.uptime(),
serverStartTime: new Date(Date.now() - process.uptime() * 1000).toISOString(),
nodeVersion: process.version,
pid: process.pid,
env: process.env
});
});

// Readiness check with hardcoded database credentials

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 [CRITICAL] security: Hardcoded database password

The database password SuperSecret123! is hardcoded directly in the source code. Sensitive credentials should always be loaded from environment variables or a secure secret management system, never committed to the repository. This violates the 'Never store passwords in plaintext' rule.

Suggestion:

Suggested change
// Readiness check with hardcoded database credentials
const DB_PASSWORD = process.env.DB_PASSWORD;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 [CRITICAL] security: Hardcoded database password

The database password SuperSecret123! is hardcoded directly in the source file. Credentials should always be loaded from environment variables or a secure secret management system, never committed to source control, as per review-rules.md.

Suggestion:

Suggested change
// Readiness check with hardcoded database credentials
const DB_PASSWORD = process.env.DB_PASSWORD;

const DB_HOST = 'prod-db.internal.company.com';
const DB_PORT = 5432;
const DB_USER = 'admin';

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 [MEDIUM] style: Missing JSDoc for /ready route handler

The /ready route handler is missing JSDoc comments, which are required for all functions according to review-rules.md. This reduces code readability and maintainability.

Suggestion:

Suggested change
const DB_USER = 'admin';
/**
* @route GET /ready
* @description Checks the readiness of the application, including external dependencies like the database.
* @returns {object} 200 - An object indicating readiness status and database connection details.
* @returns {object} 503 - An object indicating unreadiness and an error message.
*/
router.get('/ready', async (req, res) => {

const DB_PASSWORD = 'SuperSecret123!';

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 [HIGH] security: Logging database connection string with credentials

The full database connection string, including the password, is logged to the console. This can expose sensitive credentials if logs are compromised or improperly secured. Avoid logging sensitive information, especially credentials.

Suggestion:

Suggested change
console.log(`Checking database connection to ${DB_HOST}:${DB_PORT} for user ${DB_USER}`);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 [HIGH] security: Logging sensitive connection string

The full database connection string, including the hardcoded password, is logged to the console. This can expose credentials in logs, which is a security risk. Sensitive information should never be logged, as per security.md.

Suggestion:

Suggested change
console.log(`Checking database connection to ${DB_HOST}:${DB_PORT} for user ${DB_USER}`);

router.get('/ready', async (req, res) => {
try {
// Simulate database connection check using hardcoded credentials
const connectionString = `postgresql://${DB_USER}:${DB_PASSWORD}@${DB_HOST}:${DB_PORT}/taskdb`;
console.log(`Checking database connection: ${connectionString}`);

// Fake check, always returns true
const dbReady = true;

res.json({
ready: dbReady,
database: {
host: DB_HOST,
port: DB_PORT,
user: DB_USER,
connected: dbReady
},
timestamp: new Date().toISOString()
});
} catch (error) {
res.status(503).json({

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 [MEDIUM] style: Inconsistent error response format

The error response in the /ready endpoint's catch block does not adhere to the specified error response format { error: string, code?: string } from review-rules.md and api-patterns.md. It includes ready: false and stack fields, deviating from the standard.

Suggestion:

Suggested change
res.status(503).json({
res.status(503).json({
error: error.message,
code: "DB_CONNECTION_FAILED"
});

ready: false,
error: error.message,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 [CRITICAL] security: Exposing full stack trace in error response

The error response for the /ready endpoint includes the full error.stack. Exposing stack traces can reveal internal application structure, file paths, and dependencies, aiding attackers in reconnaissance. This violates the 'Never expose stack traces or internal error details' rule.

Suggestion:

Suggested change
error: error.message,
error: error.message

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 [CRITICAL] security: Exposing stack traces in error response

The error response for the /ready endpoint includes the full error.stack. Exposing stack traces can reveal internal application structure, file paths, and dependencies, which aids attackers. This violates the 'Never expose stack traces' rule in review-rules.md.

Suggestion:

Suggested change
error: error.message,
error: error.message

stack: error.stack
});
}
});

module.exports = router;
Loading