
Research
Supply Chain Attack on Axios Pulls Malicious Dependency from npm
A supply chain attack on Axios introduced a malicious dependency, plain-crypto-js@4.2.1, published minutes earlier and absent from the project’s GitHub releases.
@invictusdev/invictus-logger
Advanced tools
Centralized error and log notification service for Invictus microservices
Centralized error and log notification service for Invictus microservices. This package provides a unified way to send errors and logs directly to Telegram, eliminating the need for an intermediate notify service.
npm install @invictusdev/invictus-logger
Works with both TypeScript and JavaScript projects! See JavaScript Usage section below.
Telegram credentials are already hardcoded in the library, so you only need to specify the service name:
import { createErrorNotifier } from "@invictusdev/invictus-logger";
const errorNotifier = createErrorNotifier({
serviceName: "MY_SERVICE", // Must match a key in MessageThreadId
});
export default errorNotifier;
If you need to use custom Telegram credentials:
import { createErrorNotifier } from "@invictusdev/invictus-logger";
const errorNotifier = createErrorNotifier({
serviceName: "MY_SERVICE",
telegramBotToken: process.env.CUSTOM_BOT_TOKEN, // optional
telegramChatId: process.env.CUSTOM_CHAT_ID, // optional
timeout: 5000, // optional, defaults to 5000ms
});
export default errorNotifier;
The library reads credentials from environment variables by default:
TELEGRAM_BOT_TOKEN=your_bot_token_here
TELEGRAM_CHAT_ID=your_chat_id_here
You can override them per service if needed.
// In your error handler middleware
app.use(async (err, req, res, next) => {
console.error(err);
// Send error to Telegram via notify service
await errorNotifier.sendError(err, req);
res.status(500).json({ error: "Internal server error" });
});
// Send a log message
await errorNotifier.sendLog("Important event occurred", req);
// Or with custom context
await errorNotifier.sendLog("Cron job failed", {
path: "/cron/job",
method: "CRON",
env: process.env.NODE_ENV,
});
import { ErrorNotifier } from "@invictusdev/invictus-logger";
const errorNotifier = new ErrorNotifier({
serviceName: "GRAPHQL_SERVICE",
});
const errorPlugin = {
requestDidStart() {
return {
async didEncounterErrors(requestContext) {
if (requestContext.errors?.length > 0) {
const error = new Error(requestContext.errors[0].message);
await errorNotifier.sendError(error, {
path: requestContext.request.operationName,
method: "GraphQL",
user: requestContext.context.user,
});
}
},
};
},
};
try {
await someCronTask();
} catch (error) {
await errorNotifier.sendError(error as Error, {
path: "/cron/task",
method: "CRON",
env: process.env.NODE_ENV,
});
}
The library now captures ALL additional context you provide, giving you maximum debugging information:
// Cluster/Worker errors
await errorNotifier.sendError(error, {
path: "/api/users",
method: "POST",
body: req.body,
query: req.query, // 🆕 Query params
headers: req.headers, // 🆕 Headers (sensitive data filtered)
user: req.user,
workerId: worker.id, // 🆕 Worker ID
workerPid: worker.process.pid, // 🆕 Worker PID
instanceId: process.env.INSTANCE_ID, // 🆕 ECS/K8s instance
reason: "uncaughtException", // 🆕 Error reason
source: "cluster/worker-3", // 🆕 Error source
memory: process.memoryUsage(), // 🆕 Memory stats
customData: {
/* anything */
}, // 🆕 Any custom fields
});
What you'll see in Telegram:
🚨 Error in MY_SERVICE
🕐 Time: 2025-10-29 15:30:45 (UTC+5)
🌐 ENV: production
👤 User: 507f1f77bcf86cd799439011
⚙️ Worker: 3 ← 🆕
🔧 PID: 12345 ← 🆕
🖥️ Instance: i-0abc123def456789 ← 🆕
📝 Reason: uncaughtException ← 🆕
📍 Source: cluster/worker-3 ← 🆕
📌 Path: /api/users
💊 Method: POST
🚨 Error: Cannot read property 'id' of undefined
🔍 Query Params: ← 🆕
{ "limit": "10", "sort": "createdAt" }
📋 Headers: ← 🆕
{ "content-type": "application/json", "user-agent": "axios/1.6.0", "authorization": "[REDACTED]" ← Sensitive data filtered }
📦 Request Body:
{ "name": "John", "email": "john@example.com" }
💾 Memory: ← 🆕
{ "heapUsed": 125829120, "heapTotal": 142606336, "rss": 189345792 }
📦 Stack Trace:
at UserController.create (/app/src/controllers/user.ts:45:12) ...
**Security Features:**
- 🔒 **Automatic sensitive data filtering** for headers:
- `authorization`, `cookie`, `x-api-key`, `x-auth-token`, `x-csrf-token`, `password`, `secret`
- Replaced with `[REDACTED]`
- 📏 **Smart message truncation**:
- Automatically fits into Telegram's 4000 character limit
- Prioritizes important sections (stack trace kept last)
- Truncated sections show `...truncated...`
## Telegram Thread Mapping
Each service sends messages to its own thread in the Telegram group. The service name must match one of these:
```typescript
import { MessageThreadId } from "@invictusdev/invictus-logger";
// Available services:
// - NOTIFY
// - CONTENT_SERVICE
// - PAYMENT_SERVICE
// - MAIN_SERVICE
// - SOCIETY_SERVICE
// - GYMBUDDY_SERVICE
// - COACH_SERVICE
// - RABBITMQ
// - CRONS
To add a new service, update the MessageThreadId in the library.
createErrorNotifier(config)Creates a new ErrorNotifier instance.
Parameters:
config.serviceName (string, required) - Name of your service (must match MessageThreadId key)config.telegramBotToken (string, required) - Telegram bot tokenconfig.telegramChatId (string, required) - Telegram chat IDconfig.timeout (number, optional) - Request timeout in ms (default: 5000)config.suppressWarnings (boolean, optional) - Suppress warnings (default: false)errorNotifier.sendError(error, reqOrContext?)Sends an error notification.
Parameters:
error (Error, required) - The error object to sendreqOrContext (RequestLike | ErrorContext, optional) - Express request or custom contexterrorNotifier.sendLog(message, reqOrContext?)Sends a log notification.
Parameters:
message (string, required) - The log messagereqOrContext (RequestLike | ErrorContext, optional) - Express request or custom contexterrorNotifier.send(error, reqOrContext?)Alias for sendError() for backward compatibility.
interface ErrorContext {
path?: string;
method?: string;
body?: unknown;
query?: unknown; // 🆕 v1.6.0
user?: any;
env?: string;
headers?: Record<string, string | string[] | undefined>; // 🆕 v1.6.0
[key: string]: any; // Any additional fields (workerId, memory, etc.)
}
interface RequestLike {
originalUrl?: string;
path?: string;
method?: string;
body?: unknown;
query?: unknown; // 🆕 v1.6.0
user?: any;
headers?: Record<string, string | string[] | undefined>;
[key: string]: any; // Any additional fields
}
Before:
// Old: services/error-notifier.service.ts
import axios from "axios";
class ErrorNotifierService {
async send(error: Error, req: any) {
await axios.post(`${NOTIFY_SERVICE_URL}/api/errors`, {
service: "MY_SERVICE",
message: error.message,
stack: error.stack,
context: {
/* ... */
},
});
}
}
After:
// New: config/errorNotifier.ts
import { createErrorNotifier } from "@invictusdev/invictus-logger";
const errorNotifier = createErrorNotifier({
serviceName: "MY_SERVICE",
telegramBotToken: process.env.TELEGRAM_BOT_TOKEN!,
telegramChatId: process.env.TELEGRAM_CHAT_ID!,
});
export default errorNotifier;
// Usage remains the same:
await errorNotifier.sendError(error, req);
await errorNotifier.send(error, req); // backward compatible
The library includes a ready-to-use Morgan configuration for HTTP request logging:
import express from "express";
import morgan from "morgan";
import {
createMorganConfig,
captureResponseBody,
} from "@invictusdev/invictus-logger";
const app = express();
app.use(express.json());
// Capture response body (BEFORE morgan)
app.use(captureResponseBody());
// Use Morgan with configuration
const morganConfig = createMorganConfig({
nodeEnv: process.env.NODE_ENV,
});
app.use(morgan(morganConfig.format, morganConfig.options));
Features:
See MORGAN_GUIDE.md for detailed documentation.
Automatically catch and log unhandled errors and process shutdowns:
import {
createErrorNotifier,
setupProcessErrorHandlers,
} from "@invictusdev/invictus-logger";
const errorNotifier = createErrorNotifier({
serviceName: "MY_SERVICE",
});
// Setup automatic handlers for uncaught errors
setupProcessErrorHandlers(errorNotifier, {
onBeforeExit: async () => {
// Cleanup: close DB, Redis, RabbitMQ, etc.
await closeAllConnections();
},
});
Features:
uncaughtExceptionunhandledRejectionSIGTERM (Docker/Kubernetes shutdown)SIGINT (Ctrl+C)What gets logged:
See PROCESS_HANDLERS.md for detailed documentation.
This library works perfectly with plain JavaScript projects (no TypeScript required):
// CommonJS
const { createErrorNotifier } = require("@invictusdev/invictus-logger");
const errorNotifier = createErrorNotifier({
serviceName: "MY_SERVICE",
});
module.exports = errorNotifier;
// ES Modules
import { createErrorNotifier } from "@invictusdev/invictus-logger";
export default createErrorNotifier({
serviceName: "MY_SERVICE",
});
Features:
See JAVASCRIPT_USAGE.md for complete JavaScript examples.
ISC
FAQs
Centralized error and log notification service for Invictus microservices
We found that @invictusdev/invictus-logger demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 15 open source maintainers collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Research
A supply chain attack on Axios introduced a malicious dependency, plain-crypto-js@4.2.1, published minutes earlier and absent from the project’s GitHub releases.

Research
Malicious versions of the Telnyx Python SDK on PyPI delivered credential-stealing malware via a multi-stage supply chain attack.

Security News
TeamPCP is partnering with ransomware group Vect to turn open source supply chain attacks on tools like Trivy and LiteLLM into large-scale ransomware operations.