-
Notifications
You must be signed in to change notification settings - Fork 11
Security: Prevent ANSI injection attacks in user-facing output #12
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
c5ef050
b42656a
7e1b5a4
78c6ea5
5333c46
d3b75e7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,6 +5,7 @@ import { getSpec, loadSubFiles } from '../spec-loader.js'; | |
| import { resolveSpecPath } from '../utils/path-helpers.js'; | ||
| import { loadConfig } from '../config.js'; | ||
| import { autoCheckIfEnabled } from './check.js'; | ||
| import { sanitizeUserInput } from '../utils/ui.js'; | ||
|
|
||
| export async function filesCommand( | ||
| specPath: string, | ||
|
|
@@ -23,7 +24,7 @@ export async function filesCommand( | |
| // Resolve spec path | ||
| const resolvedPath = await resolveSpecPath(specPath, cwd, specsDir); | ||
| if (!resolvedPath) { | ||
| console.error(chalk.red(`Spec not found: ${specPath}`)); | ||
| console.error(chalk.red(`Spec not found: ${sanitizeUserInput(specPath)}`)); | ||
| console.error( | ||
| chalk.gray('Try using the full path or spec name (e.g., 001-my-spec)') | ||
| ); | ||
|
|
@@ -33,15 +34,15 @@ export async function filesCommand( | |
| // Load spec info | ||
| const spec = await getSpec(resolvedPath); | ||
| if (!spec) { | ||
| console.error(chalk.red(`Could not load spec: ${specPath}`)); | ||
| console.error(chalk.red(`Could not load spec: ${sanitizeUserInput(specPath)}`)); | ||
| process.exit(1); | ||
| } | ||
|
|
||
| // Load sub-files | ||
| const subFiles = await loadSubFiles(spec.fullPath); | ||
|
|
||
| console.log(''); | ||
| console.log(chalk.cyan(`📄 Files in ${spec.name}`)); | ||
| console.log(chalk.cyan(`📄 Files in ${sanitizeUserInput(spec.name)}`)); | ||
| console.log(''); | ||
|
|
||
| // Show README.md (required) | ||
|
|
@@ -73,7 +74,7 @@ export async function filesCommand( | |
| console.log(chalk.cyan('Documents:')); | ||
| for (const file of documents) { | ||
| const size = formatSize(file.size); | ||
| console.log(chalk.cyan(` ✓ ${file.name.padEnd(20)} (${size})`)); | ||
| console.log(chalk.cyan(` ✓ ${sanitizeUserInput(file.name).padEnd(20)} (${size})`)); | ||
| } | ||
| console.log(''); | ||
| } | ||
|
|
@@ -82,7 +83,7 @@ export async function filesCommand( | |
| console.log(chalk.yellow('Assets:')); | ||
| for (const file of assets) { | ||
| const size = formatSize(file.size); | ||
| console.log(chalk.yellow(` ✓ ${file.name.padEnd(20)} (${size})`)); | ||
| console.log(chalk.yellow(` ✓ ${sanitizeUserInput(file.name).padEnd(20)} (${size})`)); | ||
|
||
| } | ||
| console.log(''); | ||
| } | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Calling
.padEnd(20)on the sanitized filename can cause misalignment when the filename contains multi-byte unicode characters or emojis. The sanitization preserves unicode/emojis but.padEnd()counts by string length, not visual width. Consider sanitizing after padding or using a display-width-aware padding function.