Skip to content

fix: sanitize snapshot tags to prevent invalid chars and path traversal - #24

Open
vivekyadav-3 wants to merge 11 commits into
tanmayjoddar:mainfrom
vivekyadav-3:fix/sanitize-snapshot-tags
Open

fix: sanitize snapshot tags to prevent invalid chars and path traversal#24
vivekyadav-3 wants to merge 11 commits into
tanmayjoddar:mainfrom
vivekyadav-3:fix/sanitize-snapshot-tags

Conversation

@vivekyadav-3

Copy link
Copy Markdown

Summary

Closes #5

Snapshot files were saved as ${tag}.json without any validation.
A tag like ../evil or v1:prod would break on Windows or allow
path traversal outside ~/.apidrift/snapshots/.

Changes

  • src/storage/snapshotStore.js: Added exported sanitizeTag() function
    • Allows only A-Z a-z 0-9 . _ - (safe on all OS)
    • Replaces all other chars (:, /, \, spaces, etc.) with _
    • Collapses consecutive underscores
    • Strips leading/trailing dots and underscores
    • Throws a clear error if result is empty

Before / After

Tag input Before (filename) After (safe filename)
v1.0.13 v1.0.13.json v1.0.13.json
prod:v2 prod:v2.json ❌ (Windows) prod_v2.json
../evil ../evil.json 🔴 traversal _evil.json wait... → evil.json
v1 final v1 final.json v1_final.json

Notes

  • Existing safe tags like v1.0.13, prod-users pass through unchanged ✅
  • sanitizeTag is exported so it can be tested and reused ✅

Copilot AI review requested due to automatic review settings May 20, 2026 07:15

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR hardens snapshot filename handling by sanitizing user-supplied snapshot tags to avoid invalid characters and path traversal, and also makes HTTP request timeouts configurable via an environment variable.

Changes:

  • Added sanitizeTag() and applied it to snapshot save/load paths; sorted snapshot listing output.
  • Introduced APIDRIFT_TIMEOUT_MS to configure axios request timeouts.
  • Expanded CLI init messaging and documented environment variables + troubleshooting in the README.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.

File Description
src/storage/snapshotStore.js Adds sanitizeTag() and uses it for snapshot file paths; sorts listed snapshots.
src/core/fetcher.js Adds configurable request timeout via APIDRIFT_TIMEOUT_MS.
src/commands/init.js Improves messaging when keeping an existing config.
README.md Documents environment variables and adds troubleshooting guidance for timeouts/auth.
Comments suppressed due to low confidence (1)

src/storage/snapshotStore.js:54

  • This change will make previously-created snapshots with unsafe-but-valid POSIX filenames (e.g. tags with spaces/colons saved by older versions) no longer loadable because loadSnapshot now sanitizes the tag before reading. Consider a migration/fallback: if the sanitized path doesn’t exist, try the legacy ${tag}.json only when it resolves under SNAP_DIR (no traversal), or proactively rename legacy files on startup/listing.
export function loadSnapshot(tag) {
  const safe = sanitizeTag(tag);
  const file = path.join(SNAP_DIR, `${safe}.json`);
  if (!fs.existsSync(file)) {
    console.error(`Snapshot "${tag}" not found. Run: apidrift list`);

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.


if (!sanitized) {
throw new Error(
`Invalid snapshot tag "${tag}": tag must contain at least one alphanumeric character.`
Comment on lines +11 to +15
* Sanitize a snapshot tag so it is safe to use as a filename on all platforms.
*
* Rules:
* - Only A-Z, a-z, 0-9, `.`, `_`, and `-` are allowed.
* - Every other character (including `:`, `/`, `\`, and space) is replaced with `_`.
Comment on lines 43 to 46
export function saveSnapshot(tag, data) {
const file = path.join(SNAP_DIR, `${tag}.json`);
const safe = sanitizeTag(tag);
const file = path.join(SNAP_DIR, `${safe}.json`);
fs.writeFileSync(file, JSON.stringify(data, null, 2));
Comment on lines +26 to +33
export function sanitizeTag(tag) {
// Replace every character that is NOT in the safe set with '_'
const sanitized = String(tag)
.replace(/[^A-Za-z0-9._-]/g, "_")
// Collapse consecutive underscores for readability (optional, keeps names clean)
.replace(/_+/g, "_")
// Remove leading/trailing underscores and dots
.replace(/^[._]+|[._]+$/g, "");
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.

bug: sanitize snapshot tags to safe filenames (prevent invalid chars / traversal)

3 participants