
Security News
Free Certified Patch for Critical Rails Active Storage Vulnerability
Socket has released a free Certified Patch for a critical Rails Active Storage vulnerability, giving developers time to upgrade to a secure Rails version.
@cp949/console-feed
Advanced tools
A React component that displays console logs from the current page, an iframe or transported across a server
한국어 | English
A React component that captures and displays browser console output in a user interface. Supports React 18 and 19.
This is a fork of samdenty/console-feed v3.6.0 with security vulnerability fixes.
Current prepared release: 3.7.2
npm install @cp949/console-feed
Package info: https://www.npmjs.com/package/@cp949/console-feed
The package root keeps the existing public API for compatibility:
import { Console, Hook, Decode, Unhook } from '@cp949/console-feed'
import type { Message, HookedConsole, Methods } from '@cp949/console-feed'
Non-UI utilities can also be imported from stable subpaths:
import Hook from '@cp949/console-feed/hook'
import Unhook from '@cp949/console-feed/unhook'
import { Decode, Encode } from '@cp949/console-feed/transform'
The library artifacts target Chrome 75. The package neither injects global polyfills nor requires consumers to install core-js.
pnpm --filter @cp949/console-feed check:chrome75 is a static audit of the built package output. node fixtures/chrome75-consumer/scripts/build-packed.mjs checks an installed tarball in a standalone consumer. Run the exact-browser smoke on Linux with Docker:
bash scripts/test-chrome75.sh
The recorded exact smoke uses Docker on Linux and Node 24 with Chromium/HeadlessChrome 75.0.3770.90; the packed consumer completed capture, decode, render, restoration, and style checks, with no fixture or CDP errors. The historical image downloads its snapshot over HTTPS and verifies the pinned Chromium deb SHA-1; trusted=yes applies only to that snapshot source. Podman and Node 22 have no equivalent execution record. This smoke verifies only the computed style checks in the fixture; broader CSS behavior, other browser engines, and other operating systems remain unverified.
전체 변경 이력은 CHANGELOG.md를 참조하세요. 아래는 최근 주요 변경의 요약입니다.
esbuild vulnerability (GHSA-g7r4-m6w7-qqqr) left unresolved by prior dependency updates, plus routine dependency bumps (dompurify, linkify-*, testing libraries). No public API change. See CHANGELOG.md for details.dist/) is identical to 3.7.0 — fixes the test:compat matrix and updates the README. See CHANGELOG.md for details.@emotion/react, @emotion/styled, react-inspector moved to peerDependencies — consumers must install these packages explicitly.strict mode enabled — tsconfig.json consolidated to "strict": true. HookedConsole.feed is now an optional property (feed?); runtime behavior unchanged but consumers compiling under strict may need an optional guard when accessing console.feed directly.react-inline-center dependency removed — replaced by inline flex styles at the single call site.tsdown (replaces the previous tsc-only CJS build)exports map now branches on import / require for the root and every public subpath (./component, ./hook, ./unhook, ./transform)./hook, ./unhook, ./component) are emitted so that require('@cp949/console-feed/hook') and import Hook from '@cp949/console-feed/hook' both resolve to the function directly — fixes Next/Webpack interop where Hook was being received as { default: fn }__proto__, constructor, prototype key filteringconsole.time/timeEnd support)Function component (Hooks):
import React, { useState, useEffect } from 'react'
import { Console, Hook, Decode, Unhook } from '@cp949/console-feed'
import type { Message } from '@cp949/console-feed'
const LogsContainer = () => {
const [logs, setLogs] = useState<Message[]>([])
useEffect(() => {
const hookedConsole = Hook(
window.console,
(encoded, message) => {
// When encode is true: encoded is a serialized message, so Decode is required
// When encode is false: encoded is a parsed message, but using Decode is safe
const decoded = Decode(encoded)
const logMessage: Message = {
...decoded,
id: `log-${Date.now()}-${Math.random()}`,
data: decoded.data || [],
}
setLogs((prevLogs) => [...prevLogs, logMessage])
},
true, // encode: true - serialization for network transfer
100, // limit: 100 - serialization depth limit
)
// Cleanup: Unhook when component unmounts
return () => {
Unhook(hookedConsole)
}
}, [])
return <Console logs={logs} variant="dark" />
}
A React component that displays log messages.
Props:
logs: Array of log messages (Message[]) - Requiredvariant?: Theme ("dark" | "light", default: "dark")styles?: Custom style objectfilter?: Method filter array (Methods[]) - Display only specified methodssearchKeywords?: Search keyword string - Regex search in log contentlogFilter?: Log filtering function - Custom filtering logic when used with searchKeywordslogGrouping?: Enable log grouping (default: true) - Group identical logs and display with amountlinkifyOptions?: linkifyjs options object - URL link handling optionscomponents?: Component override object - Replace with custom componentsWraps window.console or a console-like object to capture logs.
Hook(
console: Console,
callback: (encoded: Message, message: Payload) => void,
encode?: boolean, // Default: true
limit?: number // Default: 100 (serialization depth limit)
): HookedConsole
Parameters:
console: Console object to hookcallback: Callback function called when a log is captured
encoded: Log message (first argument)
encode is true: Serialized message (suitable for network transfer/storage)encode is false: Parsed message (not serialized, for use in the same memory space)message: Parsed message (second argument, always non-serialized parsed result)encode: Whether to serialize logs (default: true)
true: Serialize parsed messages for network transfer or localStorage storagefalse: Use parsed messages without serialization (more efficient when used in the same memory space)limit: Serialization depth limit (default: 100, only applies when encode is true)Return Value:
HookedConsole: Hooked Console object (can be passed to Unhook)Restores a console wrapped by Hook to its original state. Must be called when the component unmounts.
Unhook(hookedConsole: HookedConsole): boolean
Parameters:
hookedConsole: Console object wrapped by HookReturn Value:
boolean: Success status (true: success, false: failure)Used when transmitting logs across network boundaries.
Encode<T>(data: any, limit?: number): T
Decode(data: any): Message
Encode:
limit: Serialization depth limit (default: 100)JSON.stringify()Decode:
Message objectsmethod propertyencode is true: The first argument (encoded) of the callback is a serialized message, so Decode must be calledencode is false: The first argument (encoded) of the callback is a parsed message, but calling Decode is recommended for safe usageUsage Example:
import { Encode, Decode } from '@cp949/console-feed'
// 1. Create log message
const logMessage = {
method: 'log' as const,
data: [
'Hello World',
{ name: 'console-feed', version: '3.7.2' },
[1, 2, 3],
],
timestamp: new Date().toISOString(),
}
// 2. Encode: Serialize for network transfer
const encoded = Encode(logMessage, 100)
// encoded is an object that can be serialized with JSON.stringify()
// Example: { method: 'log', data: [...], timestamp: '...' }
// 3. Simulate network transfer (convert to JSON)
const jsonString = JSON.stringify(encoded)
// Can be stored in localStorage or sent over network
// 4. Parse JSON on receiving side
const received = JSON.parse(jsonString)
// 5. Decode: Deserialize to restore original form
const decoded = Decode(received)
// decoded is a complete log object of type Message
// { method: 'log', data: [...], timestamp: '...' }
// 6. Pass to Console component
<Console logs={[decoded]} variant="dark" />
Real-world Usage Scenario:
// Send log to server
const sendLogToServer = (log: Message) => {
const encoded = Encode(log, 100)
fetch('/api/logs', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(encoded), // Can be safely serialized
})
}
// Display logs received from server
const receiveLogFromServer = async () => {
const response = await fetch('/api/logs')
const encodedLogs = await response.json()
const decodedLogs = encodedLogs.map((encoded: any) => Decode(encoded))
setLogs(decodedLogs)
}
You can display console methods like console.log(), console.error() executed inside an iframe in the main window's console-feed.
Simple Method:
After the iframe loads, hook the iframe's contentWindow.console.
import React, { useState, useEffect, useRef } from 'react'
import { Console, Hook, Decode, Unhook } from '@cp949/console-feed'
import type { Message, HookedConsole } from '@cp949/console-feed'
const IframeLogsContainer = () => {
const [logs, setLogs] = useState<Message[]>([])
const iframeRef = useRef<HTMLIFrameElement | null>(null)
useEffect(() => {
const iframe = iframeRef.current
if (!iframe) return
let hookedConsole: HookedConsole | null = null
// Wait for iframe to load
const handleLoad = () => {
if (!iframe.contentWindow) {
console.error('iframe contentWindow is not available')
return
}
// Hook iframe's console
const iframeConsole = iframe.contentWindow.console
hookedConsole = Hook(
iframeConsole,
(encoded, message) => {
// encode is true, so use Decode to decode the log (required!)
const decoded = Decode(encoded)
const logMessage: Message = {
...decoded,
id: `log-${Date.now()}-${Math.random()}`,
data: decoded.data || [],
}
setLogs((prevLogs) => [...prevLogs, logMessage])
},
true, // encode: true
100, // limit: 100
)
}
iframe.addEventListener('load', handleLoad)
// Cleanup: Clean up when component unmounts
return () => {
if (hookedConsole && iframe.contentWindow) {
Unhook(hookedConsole)
}
iframe.removeEventListener('load', handleLoad)
}
}, [])
return (
<div>
<iframe ref={iframeRef} src="./your-iframe.html" />
<Console logs={logs} variant="dark" />
</div>
)
}
Notes:
load event)contentWindow.consoleUnhook when the component unmounts to clean upconsole-feed/
├── apps/
│ └── demo/ # Demo app (Vite + React)
├── packages/
│ └── console-feed/ # Library core
├── turbo.json # Turborepo configuration
├── pnpm-workspace.yaml # pnpm workspace setup
└── package.json # Root workspace
^22.18.0 (CI baseline)11.27.1# Install dependencies
pnpm install
# Run development server for entire workspace
pnpm dev
# Build entire workspace
pnpm build
# Test entire workspace
pnpm test
# Run specific package only
pnpm --filter @cp949/console-feed build # Build library
pnpm --filter demo dev # Run demo app only
pnpm --filter @cp949/console-feed test # Test library
# Test both React 18 and 19
pnpm test:compat
# Test React 18 only
pnpm test:react18
# Test React 19 only
pnpm test:react19
Script: packages/console-feed/scripts/test-react-compat.sh
Only the library package (@cp949/console-feed) is published to npm.
Before releasing, update and commit CHANGELOG.md; release-it requires a clean working tree.
# Starts the interactive release flow from the repository root.
pnpm release-it
The flow updates only this package's package.json, runs prepublishOnly (build, test, test:dist), publishes to npm, then interactively confirms the release commit, v<version> tag, and push. Use the prompts to choose the version and approve each external action.
MIT
FAQs
A React component that displays console logs from the current page, an iframe or transported across a server
The npm package @cp949/console-feed receives a total of 43 weekly downloads. As such, @cp949/console-feed popularity was classified as not popular.
We found that @cp949/console-feed demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.

Security News
Socket has released a free Certified Patch for a critical Rails Active Storage vulnerability, giving developers time to upgrade to a secure Rails version.

Security News
/Threat Research
A malicious Ruby gem runs a credential-stealing worm during installation, poisons AI coding tools, and can wipe files when a stolen GitHub token is revoked.

Security News
GitHub is tightening GitHub Actions security with new restrictions on privileged pull request workflows. Here's what changes and how maintainers are affected.