Commit graph

52 commits

Author SHA1 Message Date
Fade78
e69757ccab Remove chmod from command whitelist
chmod has no legitimate use case in Fileshed context:
- File permissions are managed by Fileshed's own system (zones, groups, modes)
- Unix permissions are never exposed to users via the API
- Allowing chmod creates a security risk (executable scripts)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-02 18:38:14 +01:00
Fade78
0664545b27 Bump version to 1.0.5 - NFS compatibility
- Add sqlite_journal_mode valve for NFS-safe SQLite operations
- Extract _apply_sqlite_journal_mode() helper (DRY)
- Add NFS deployment documentation in SPEC.md
- Add 5 tests for journal modes (1196-1200)
- Update test count to 1200

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-31 16:38:31 +01:00
Fade78
56b4c000e7 Created ZIP: docs.zip 2026-01-31 16:16:13 +01:00
Fade78
1766026fea Created ZIP: docs.zip 2026-01-31 16:00:11 +01:00
Fade78
2a38dc8b2c Created ZIP: docs.zip 2026-01-31 15:59:02 +01:00
Fade78
9d42f512b5 Created ZIP: docs.zip 2026-01-31 15:57:05 +01:00
Fade78
5a617330d6 Bump version to 1.0.4
- Update version in Fileshed.py
- Update README badges (version + tests count 1195)
- Update Exec_tests.md version

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-31 13:44:59 +01:00
Fade78
38aa331306 Refactor shed_create_file: wrap in try/except with StorageError 2026-01-31 13:38:43 +01:00
Fade78
405204f02d Extracted docs.zip to docs 2026-01-31 11:25:13 +01:00
Fade78
de4fa161a7 Add mono-instance concurrency protections (C3-C6)
- C3: FS/DB atomicity with rollback on shed_rename, orphan cleanup in shed_maintenance
- C4: SQLite WAL mode for better concurrent read/write performance
- C5: Git lock (fcntl.flock) for group operations to prevent index corruption
- C6: SQLite retry with exponential backoff (3 retries, 0.1/0.2/0.4s delays)

Also: Change xxd to od in README features (xxd not in container)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-31 09:47:52 +01:00
Fade78
e91b6d741f Add overwrite parameter to bridge functions, fix import hint
Bridge functions:
- shed_move_uploads_to_storage: Added overwrite=False parameter
- shed_move_uploads_to_documents: Added overwrite=False parameter
- shed_copy_storage_to_documents: Added overwrite=False parameter
- shed_move_documents_to_storage: Added overwrite=False parameter
- shed_copy_to_group: Added overwrite=False parameter
- FILE_EXISTS errors now hint "Use overwrite=True to replace"

Import hint fix:
- Removed import_all=True from hint (let user choose)

Tests: 1101 tests passing (+10 for bridge overwrite)
Docs: Updated FUNCTION_HELP, README function table

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 22:07:18 +01:00
Fade78
106d0d5409 Add shed_create_file hint, fix SQL case-insensitive validation, add security tests
- shed_create_file: Add pedagogical hint explaining it's a wrapper
- SQL security: Convert query to uppercase before pattern matching (fixes case bypass)
- Tests: Add 5 SQL security tests (1087-1091) for case-insensitive validation
- Docs: Fix function count (37→38), add shed_create_file to SPEC.md
- README: Update test badge (1086→1091)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 20:01:56 +01:00
Fade78
c07e2bedfc Update docs to recommend shed_create_file for file creation
- README: Updated examples to use shed_create_file instead of
  shed_patch_text(..., overwrite=True)
- HOWTO guides: Updated Quick Reference table
- ASCII banner: Updated file content operations section

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 19:40:00 +01:00
Fade78
17b3d8b46f Add shed_create_file function and overwrite param for shed_patch_bytes
New function: shed_create_file(zone, path, content, file_type='text')
- Simplest way to create/overwrite a file
- Supports both text and bytes (file_type parameter)
- For bytes: content_format='hex', 'base64', or 'raw'
- Delegates to shed_patch_text/bytes with overwrite=True

Also added overwrite parameter to shed_patch_bytes for consistency
with shed_patch_text.

Function count: 37 → 38

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 19:33:50 +01:00
Fade78
d41294bf73 Fix LLM confusion: accept position="overwrite" when overwrite=True
When overwrite=True, the position parameter is ignored anyway.
Now we skip position validation when overwrite=True, preventing
errors when LLMs confuse the parameter with a position value.

Also added explicit warning in tips:
"⚠️ overwrite is a PARAM (overwrite=True), NOT a position value"

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 19:26:09 +01:00
Fade78
5473950ea0 Fix SEC-01 and ROB-01: improve error messages for LLM guidance
SEC-01: Remove internal paths from error messages
- Remove uploads_dir from FILE_NOT_FOUND details (exposed internal paths)

ROB-01: Add context to generic exception messages (36 occurrences)
- Each "An unexpected error occurred" now describes the operation
- Examples: "Unexpected error during ZIP extraction",
  "Unexpected error while editing text file", etc.

This helps LLMs understand which operation failed without exposing
sensitive system information.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 19:10:08 +01:00
Fade78
e1c234b508 Add LLM Guardrails: type validation with helpful error messages
Validates parameter types before use to prevent TypeError/AttributeError
when LLMs pass wrong types (e.g., "" instead of None, 0 instead of ""):

- max_output, timeout: validate int type
- line, end_line: validate int type in shed_patch_text
- offset, length: validate int type in shed_patch_bytes and shed_hexdump
- regex_flags: validate string type
- to (shed_convert_eol): validate string type

Each error message includes:
- Parameter name
- Received value with type
- Expected format
- Concrete example in hint

Also adds LLM Guardrails section to SPEC.md explaining the rationale:
minimize round-trips by making errors self-correcting.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 18:51:47 +01:00
Claude
914cfd0061
Fix validation bugs in 4 shed_* functions
1. shed_patch_text: Skip line/end_line/pattern validation when overwrite=True
2. shed_patch_bytes: Only validate offset bounds when position uses it (at/replace)
3. shed_lockedit_overwrite: Add explicit validation that content is not None
4. shed_sqlite: Reject contradictory import_csv + query parameters

These parameters were being validated even when ignored, causing unnecessary
errors when LLMs pass default values like end_line=0 or pattern="".

https://claude.ai/code/session_0126dD9QeVgoFVT7ZBxbnhNM
2026-01-30 10:59:12 +00:00
Fade78
0b76bb938c Fix SQL comment bypass vulnerability
Add _strip_sql_comments() to remove /* */ and -- comments before
checking for dangerous SQL patterns (ATTACH, DETACH, LOAD_EXTENSION).
This prevents bypass attacks like AT/**/TACH.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 10:57:24 +01:00
Fade78
6e39e28e6c Add ZIP magic bytes validation and CSV column limit
- Verify ZIP file headers (PK signature) before extraction/info
- Add CSV_MAX_COLUMNS = 5000 limit to prevent DoS with wide files
- New constants: ZIP_MAGIC_BYTES, CSV_MAX_COLUMNS
- New error code: CSV_TOO_WIDE

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 10:57:24 +01:00
Fade78
56a2ed8fbd Refactoring and security improvements from audit
- Refactor 6 functions to use _resolve_zone(): shed_tree, shed_zipinfo,
  shed_file_type, shed_convert_eol, shed_hexdump, shed_link_create
- Add group zone support to shed_zipinfo, shed_file_type, shed_hexdump,
  shed_convert_eol
- Replace subprocess 'which' with shutil.which() in _check_command_available
- Remove printenv and envsubst from whitelist (expose env variables)
- Add symlink check before ZIP extraction (TOCTOU protection)
- Add large_files to tool description howto list

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 10:57:24 +01:00
Fade78
78f81e3c11 Delete .git 2026-01-30 10:57:24 +01:00
Fade78
1fed969d1c Security fixes from multi-axis audit
- Fix ZIP cross-zone extraction: validate dest_path with _resolve_chroot_path
- Fix filename collision: generate unique names with UUID for unknown files
- Fix shed_import: add __user__ None check before _get_user_root
- Fix mutable default arguments: replace = {} with = None
- Fix lock leak: add editzone_path existence check
- Remove chroot path exposure from error messages
- Add _release_lock() centralized function
- Add conv_id validation against path traversal characters
- Update SPEC.md: add ARGUMENT_REQUIRED, sum, uuencode, uudecode
- Remove unused COMMAND_NOT_ALLOWED error code

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 10:57:24 +01:00
Fade78
a6581aa946 Performance and code quality optimizations from multi-axis audit
- Remove unused Callable import (line 78)
- Remove redundant shutil import in _neutralize_git_hooks
- Cache content.encode('utf-8') result in _validate_content_size
- Cache zf.infolist() result in shed_unzip ZIP bomb protection
- Cache zf.namelist() result before extraction in shed_unzip
- Cache items[:100] slice in build_tree function

https://claude.ai/code/session_01THb4YA4SqYG52LVwjwb5Uo
2026-01-30 10:57:24 +01:00
Fade78
1d1ff5be60 Fix medium priority cleanup and edge case issues
- shed_lockedit_open: Clean up orphaned editzone file on copy failure
  before releasing lock
- shed_unzip: Clean up directories (not just files) on partial extraction
  failure, using reverse-sorted order for nested directory cleanup
- shed_exec git clone: Add fallback repo_name="repository" for malformed
  URLs that would result in empty repo name

https://claude.ai/code/session_01THb4YA4SqYG52LVwjwb5Uo
2026-01-30 10:57:24 +01:00
Fade78
5dc331ddbc Fix critical lock management and SQL safety issues
CRITICAL fixes:
- _check_lock_owner: Catch OSError/PermissionError when reading lock file
- _acquire_lock: Ensure complete write with partial write detection and
  cleanup of corrupt lock file on failure
- _acquire_lock race path: Catch OSError/PermissionError when reading
  existing lock, and handle write failure with proper StorageError

HIGH fix:
- SQL queries with limit=0: Use fetchmany() with batching up to
  MAX_SQL_ROWS (10000) to prevent memory exhaustion on large result sets

Added constant:
- MAX_SQL_ROWS = 10000 for SQL query protection

https://claude.ai/code/session_01THb4YA4SqYG52LVwjwb5Uo
2026-01-30 10:57:24 +01:00
Fade78
7079cf5809 Remove unused exception variables (as e) in handlers
- Replace all `except Exception as e:` with `except Exception:` where
  the exception variable `e` was not used (36 occurrences)
- Replace `except ImportError as e:` with `except ImportError:` (1 occurrence)

The exception is intentionally not captured to avoid any potential
information leakage and to clarify that only generic error messages
are returned to users.

https://claude.ai/code/session_01THb4YA4SqYG52LVwjwb5Uo
2026-01-30 10:57:24 +01:00
Fade78
295782c2fd Fix critical/high priority issues from audit
- CRITICAL: Fix lock leak in shed_lockedit_cancel - ensure lock is always
  released via try-finally even if editzone cleanup fails
- HIGH: Add user_id validation in _get_user_root - validate non-empty
  string and UUID format (8-4-4-4-12 hex pattern)
- HIGH: Catch FileNotFoundError in _git_run when git is not installed
- HIGH: Catch OSError/PermissionError in _git_run for subprocess failures
- Remove command details from TimeoutExpired error (info leakage)
- Add UUID_PATTERN constant for efficient validation

https://claude.ai/code/session_01THb4YA4SqYG52LVwjwb5Uo
2026-01-30 10:57:24 +01:00
Fade78
ce9bed6587 Fix 6 remaining information leakage issues
Critical fixes:
- L3625: Remove {e} from regex error message → generic message with hint
- L3857: Remove {e} from content error message → generic message with hint

High priority fixes:
- L2748: Remove path from FILE_LOCKED error details
- L4529: Remove path from PERMISSION_DENIED (delete) error details
- L4606: Remove path from PERMISSION_DENIED (rename) error details
- L4682: Remove path from PERMISSION_DENIED (lockedit) error details

All error messages now return minimal information to prevent
information disclosure about internal state or other users' activities.

https://claude.ai/code/session_01THb4YA4SqYG52LVwjwb5Uo
2026-01-30 10:57:24 +01:00
Fade78
94966a5f3c Fix remaining {e} information leakage in error messages
- shed_convert_eol: "Cannot read file: {e}" → "Cannot read file"
- shed_link_create: "Error calling Open WebUI API: {e}" → generic message

Kept user-input validation errors (regex, content) as they help debugging
user-provided data and don't expose system info.

https://claude.ai/code/session_01THb4YA4SqYG52LVwjwb5Uo
2026-01-30 10:57:24 +01:00
Fade78
38647b1c68 Fourth audit fixes: security hardening and code quality
Security fixes:
- Replace bare except with except Exception at L4691
- Sanitize str(e) in ~35 error responses to prevent info leakage
- Remove sensitive data (user_id, conv_id) from lock error messages
- Add None-safety to _get_user_root, _get_conv_id, _resolve_zone

Robustness fixes:
- Add cleanup for partial ZIP extraction on error
- Define module-level constants (BYTES_PER_MB, ZIP_MAX_*, etc.)

Code quality:
- Move ZIP bomb limits to module constants
- Use MAX_HEXDUMP_BYTES constant instead of magic number

https://claude.ai/code/session_01THb4YA4SqYG52LVwjwb5Uo
2026-01-30 10:57:24 +01:00
Fade78
c913a06d24 Fix critical lock management issues: ensure locks are always released
- _patch_text_impl: Move editzone operations inside try block so lock
  is released by finally if mkdir/copy/touch fails after acquisition

- _patch_bytes_impl: Same fix as _patch_text_impl for binary patching

- shed_lockedit_open: Wrap post-lock operations in try/except to release
  lock on failure (mkdir, copy to editzone)

- shed_lockedit_save: Use try/finally after successful copy to ensure
  lock is released even if git commit or cleanup fails

These fixes prevent locks from being permanently stuck when errors occur
between lock acquisition and the main try block.

https://claude.ai/code/session_01THb4YA4SqYG52LVwjwb5Uo
2026-01-30 10:57:24 +01:00
Fade78
232116026b Security and robustness fixes from second audit
Security:
- Add ZIP bomb protection (max 500MB decompressed, 10k files, 100:1 ratio)
- Escape SQL table/column names with double quotes
- Sanitize owner_id from error messages (prevent info leakage)

Robustness:
- Add editzone cleanup in finally blocks (_patch_text_impl, _patch_bytes_impl)
- Add explicit SQLite rollback on error (CSV import and SQL query modes)
- Fix mutable default parameter: args: list = [] -> args: list = None

https://claude.ai/code/session_01THb4YA4SqYG52LVwjwb5Uo
2026-01-30 10:57:24 +01:00
Fade78
29256be988 Refactor _exec_command and add type hints to _OpenWebUIBridge
_exec_command improvements:
- Extract _calculate_effective_max() helper to DRY max output calculation
- Extract _truncate_output() helper to DRY truncation logic
- Consolidate args_str calculation at function start (was computed 3x)

_OpenWebUIBridge improvements:
- Add return type hints (-> Any, -> bool) to all methods

https://claude.ai/code/session_01THb4YA4SqYG52LVwjwb5Uo
2026-01-30 10:57:24 +01:00
Fade78
1c40d972d2 Multi-axis audit fixes: security, code quality, API consistency
Security fixes:
- Add explicit symlink detection in _resolve_chroot_path
- Fix TOCTOU race conditions in _patch_text_impl and _patch_bytes_impl
- Sanitize SQLite error messages to prevent information leakage
- Add finally:conn.close() to prevent SQLite connection leaks
- Add readonly check for output_csv in shed_sqlite

Code quality:
- Replace bare except with specific exceptions (OSError, UnicodeDecodeError, etc.)
- Translate French comments to English in shed_import
- Refactor shed_sqlite to use centralized _resolve_zone()

API improvements:
- Change safe=False to safe=True by default in patch_text/patch_bytes
- Change message='' to message=None in zone movement functions

Documentation:
- Add comprehensive error codes reference table to SPEC.md

https://claude.ai/code/session_01THb4YA4SqYG52LVwjwb5Uo
2026-01-30 10:57:24 +01:00
Fade78
d75e174d44 Add zone prefix validation to all remaining functions for consistency
Updated functions with allow_zone_in_path parameter and zone_name validation:
- shed_tree (path)
- shed_zipinfo (path)
- shed_file_type (path)
- shed_hexdump (path)
- shed_force_unlock (path - both group and personal zones)
- shed_group_set_mode (path)
- shed_group_chown (path)

Also fixed zone_name consistency:
- Changed "group:{id}" to "Group:{id}" in _patch_text_impl and _patch_bytes_impl
- Changed "group:{group}" to "Group:{group}" in shed_copy_to_group

All zone names now consistently use capital letters (Storage, Documents,
Uploads, Group:) for internal discipline while accepting case-insensitive
input from users.

https://claude.ai/code/session_01THb4YA4SqYG52LVwjwb5Uo
2026-01-30 10:57:24 +01:00
Fade78
551a72a2d2 Add zone prefix validation to builtin functions (zip, unzip, sqlite, etc.)
Added allow_zone_in_path parameter and zone_name validation to:
- shed_unzip (src + dest paths)
- shed_zip (src + dest paths)
- shed_sqlite (path, import_csv, output_csv paths)
- shed_convert_eol (path)
- shed_import (dest_subdir)

This prevents LLMs from accidentally duplicating zone names in paths
(e.g., zone="storage", path="Storage/folder").

https://claude.ai/code/session_01THb4YA4SqYG52LVwjwb5Uo
2026-01-30 10:57:24 +01:00
Fade78
563e477ecd Add zone prefix validation to bridge functions (move/copy between zones)
Extended zone_name validation to:
- shed_move_uploads_to_storage
- shed_move_uploads_to_documents
- shed_copy_storage_to_documents
- shed_move_documents_to_storage

These functions previously had NO path validation and could create
duplicate zone folders (e.g., Storage/Storage/file.txt).

Also updated shed_help documentation to list all functions supporting
allow_zone_in_path parameter.

https://claude.ai/code/session_01THb4YA4SqYG52LVwjwb5Uo
2026-01-30 10:57:24 +01:00
Fade78
6f5044a684 Add zone prefix validation to lockedit_* and shed_copy_to_group
Extended zone_name validation to:
- All 5 lockedit_* functions (open, exec, overwrite, save, cancel)
- shed_copy_to_group (validates both src_path and dest_path)

Also updated shed_help paths documentation to include lockedit_* in
the list of functions supporting allow_zone_in_path.

https://claude.ai/code/session_01THb4YA4SqYG52LVwjwb5Uo
2026-01-30 10:57:24 +01:00
Fade78
1e2dc56042 Add zone prefix validation to prevent path duplication errors
Refactored path validation to detect when paths start with the zone name
(e.g., "Documents/folder" in zone="documents"), which causes unwanted
directory duplication. The validation rejects such paths by default with
a helpful error message.

Changes:
- Added zone_name and allow_zone_in_path params to _validate_relative_path
- Refactored _validate_path_args to call _validate_relative_path
- Extracted _is_expression_not_path helper for cleaner code
- Updated shed_exec, shed_patch_text, shed_patch_bytes, shed_delete,
  shed_rename to pass zone context and allow_zone_in_path parameter
- Updated _patch_text_impl and _patch_bytes_impl accordingly

LLMs can now set allow_zone_in_path=True if they intentionally want a
subfolder named after the zone.

https://claude.ai/code/session_01THb4YA4SqYG52LVwjwb5Uo
2026-01-30 10:57:24 +01:00
Fade78
f464a0598b Use generic example name in paths documentation
https://claude.ai/code/session_01THb4YA4SqYG52LVwjwb5Uo
2026-01-30 10:57:24 +01:00
Fade78
9085c141d5 Improve shed_help paths guide with explicit duplication warning
LLMs often mistakenly include the zone name in paths (e.g., zone="Documents"
with args=["Documents/folder"]) creating unwanted duplicate folders. Added
detailed explanation with concrete examples showing the mistake and its
consequence.

https://claude.ai/code/session_01THb4YA4SqYG52LVwjwb5Uo
2026-01-30 10:57:24 +01:00
Claude
547a47ac5a
Simplify shed_import message (remove warning field)
Keep context minimal: just remind about shed_delete in message.

https://claude.ai/code/session_01DLaRR2nnTryPWd2p7MyUtf
2026-01-29 00:25:12 +00:00
Claude
7862445a29
Add warning in shed_import about Uploads persistence
Warn users that files imported to Uploads are permanent and NOT deleted
when the conversation is deleted. They must be removed manually with
shed_delete(zone='uploads', path='...').

https://claude.ai/code/session_01DLaRR2nnTryPWd2p7MyUtf
2026-01-29 00:21:46 +00:00
Claude
1b760e6652
Remove warning from shed_unzip (moved to shed_import)
The Uploads persistence warning will be handled by shed_import instead.

https://claude.ai/code/session_01DLaRR2nnTryPWd2p7MyUtf
2026-01-29 00:20:19 +00:00
Claude
345d8299b3
Add warning when extracting ZIP from Uploads zone
Remind users that the source ZIP file remains in Uploads after extraction,
that Uploads files are NOT deleted when the conversation is deleted,
and suggest using shed_delete to remove it manually.

https://claude.ai/code/session_01DLaRR2nnTryPWd2p7MyUtf
2026-01-29 00:05:10 +00:00
Claude
7dc71daa88
Fix shed_help to return normal help when howto is empty string
When LLM passes howto="" instead of omitting the parameter,
treat it as a request for normal help instead of an unknown howto error.

https://claude.ai/code/session_01DLaRR2nnTryPWd2p7MyUtf
2026-01-28 23:56:06 +00:00
Claude
2f57d7f81f
Fix zone names capitalization in shed_unzip
Use canonical zone names with capital letters (Uploads, Storage, Documents)
in documentation, hints, and response data for consistency with the rest
of the codebase.

https://claude.ai/code/session_01DLaRR2nnTryPWd2p7MyUtf
2026-01-28 23:49:23 +00:00
Claude
7384e2d92a
Add src_zone parameter to shed_unzip for cross-zone extraction
Allow extracting ZIP files from Uploads zone without moving them first.
The new src_zone parameter accepts "uploads", "storage", or "documents"
while zone parameter remains the destination (storage/documents only).

Bump version to 1.0.2.

https://claude.ai/code/session_01DLaRR2nnTryPWd2p7MyUtf
2026-01-28 23:43:28 +00:00
Claude
8c47ec27bb
Bump version to 1.0.1
https://claude.ai/code/session_014zLd33kdJPBqDvjpWtHfuX
2026-01-28 18:07:34 +00:00