T09 · Insecure Skill Coding Practices
- Location
scripts/registry.py:63- Finding
Unsafe Path-Prefix Matching Can Misclassify Sensitive Resources as Public
- Content
View full analysis
Vulnerability Details
File Location:
scripts/registry.py, lines 63–68
Vulnerability Type: Improper resource path matching
Risk Level: MediumVulnerable Code
python for r in registry["resources"]: path = r["path"] # Exact prefix match if resource.startswith(path) or path.startswith(resource): priority = LEVEL_PRIORITY.get(r["level"], 0) if priority > match_priority: matched = r match_priority = priorityTechnical Analysis
The privacy registry compares resource paths as raw strings rather than normalized filesystem paths. It also treats either string being a prefix of the other as a match:
resource.startswith(path)allows sibling names sharing a textual prefix to inherit a privacy classification. For example, apublicmark onexports/publicalso matchesexports/public-backup/secrets.json.path.startswith(resource)allows a parent resource query to inherit the classification of a registered child.- The comparison does not enforce path-component boundaries, distinguish files from directories, normalize
.or.., resolve relative and absolute aliases, or account for symlinks.
After a resource is incorrectly classified as
public,check_action_allowed()at lines 166–172 authorizes every supported action:python def check_action_allowed(level, action): """Check whether an operation is allowed.""" rules = { "owner_only": ["internal_use"], "private": ["internal_use"], "no_export": ["internal_use", "display"], "public": ["share", "export", "display", "internal_use"] } return action in rules.get(level, [])This behavior violates the documented conservative policy for unmarked resources. The flaw affects callers that rely on this CLI's result as an authorization decision. The CLI itself is advisory and does not directly perform or intercept expo ...[truncated 1344 chars]
- Remediation
View remediation
Remediation Suggestions
- Normalize configured and requested paths before comparison. For local resources, use
Path.resolve(strict=False)where resolving against the filesystem is appropriate. - Replace raw string-prefix checks with path-component-aware containment checks, such as
Path.is_relative_to()on supported Python versions. - Remove
path.startswith(resource). A parent query must not inherit a child entry's classification. - Use exact matching for entries representing files. Apply descendant matching only to entries explicitly identified as directories.
- Define a clear policy for relative paths, absolute paths, nonexistent paths, case sensitivity, and symlinks. Reject ambiguous paths when they cannot be safely canonicalized.
- Default to
unmarkedand deny sharing or export whenever matching is ambiguous. - Add regression tests covering:
- Sibling names with shared textual prefixes, such as
publicandpublic-backup - Parent queries when only a child is marked
.and..path segments- Relative and absolute aliases
- Trailing separators
- Symlink traversal
- File entries versus directory entries
- Sibling names with shared textual prefixes, such as
- Normalize configured and requested paths before comparison. For local resources, use
